v8: upgrade to v3.20.2
[platform/upstream/nodejs.git] / deps / v8 / src / code-stubs-hydrogen.cc
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #include "v8.h"
29
30 #include "code-stubs.h"
31 #include "hydrogen.h"
32 #include "lithium.h"
33
34 namespace v8 {
35 namespace internal {
36
37
38 static LChunk* OptimizeGraph(HGraph* graph) {
39   DisallowHeapAllocation no_allocation;
40   DisallowHandleAllocation no_handles;
41   DisallowHandleDereference no_deref;
42
43   ASSERT(graph != NULL);
44   SmartArrayPointer<char> bailout_reason;
45   if (!graph->Optimize(&bailout_reason)) {
46     FATAL(bailout_reason.is_empty() ? "unknown" : *bailout_reason);
47   }
48   LChunk* chunk = LChunk::NewChunk(graph);
49   if (chunk == NULL) {
50     FATAL(graph->info()->bailout_reason());
51   }
52   return chunk;
53 }
54
55
56 class CodeStubGraphBuilderBase : public HGraphBuilder {
57  public:
58   CodeStubGraphBuilderBase(Isolate* isolate, HydrogenCodeStub* stub)
59       : HGraphBuilder(&info_),
60         arguments_length_(NULL),
61         info_(stub, isolate),
62         context_(NULL) {
63     descriptor_ = stub->GetInterfaceDescriptor(isolate);
64     parameters_.Reset(new HParameter*[descriptor_->register_param_count_]);
65   }
66   virtual bool BuildGraph();
67
68  protected:
69   virtual HValue* BuildCodeStub() = 0;
70   HParameter* GetParameter(int parameter) {
71     ASSERT(parameter < descriptor_->register_param_count_);
72     return parameters_[parameter];
73   }
74   HValue* GetArgumentsLength() {
75     // This is initialized in BuildGraph()
76     ASSERT(arguments_length_ != NULL);
77     return arguments_length_;
78   }
79   CompilationInfo* info() { return &info_; }
80   HydrogenCodeStub* stub() { return info_.code_stub(); }
81   HContext* context() { return context_; }
82   Isolate* isolate() { return info_.isolate(); }
83
84   class ArrayContextChecker {
85    public:
86     ArrayContextChecker(HGraphBuilder* builder, HValue* constructor,
87                         HValue* array_function)
88         : checker_(builder) {
89       checker_.If<HCompareObjectEqAndBranch, HValue*>(constructor,
90                                                       array_function);
91       checker_.Then();
92     }
93
94     ~ArrayContextChecker() {
95       checker_.ElseDeopt();
96       checker_.End();
97     }
98    private:
99     IfBuilder checker_;
100   };
101
102   enum ArgumentClass {
103     NONE,
104     SINGLE,
105     MULTIPLE
106   };
107
108   HValue* BuildArrayConstructor(ElementsKind kind,
109                                 ContextCheckMode context_mode,
110                                 AllocationSiteOverrideMode override_mode,
111                                 ArgumentClass argument_class);
112   HValue* BuildInternalArrayConstructor(ElementsKind kind,
113                                         ArgumentClass argument_class);
114
115  private:
116   HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder);
117   HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder,
118                                           ElementsKind kind);
119
120   SmartArrayPointer<HParameter*> parameters_;
121   HValue* arguments_length_;
122   CompilationInfoWithZone info_;
123   CodeStubInterfaceDescriptor* descriptor_;
124   HContext* context_;
125 };
126
127
128 bool CodeStubGraphBuilderBase::BuildGraph() {
129   // Update the static counter each time a new code stub is generated.
130   isolate()->counters()->code_stubs()->Increment();
131
132   if (FLAG_trace_hydrogen) {
133     const char* name = CodeStub::MajorName(stub()->MajorKey(), false);
134     PrintF("-----------------------------------------------------------\n");
135     PrintF("Compiling stub %s using hydrogen\n", name);
136     isolate()->GetHTracer()->TraceCompilation(&info_);
137   }
138
139   Zone* zone = this->zone();
140   int param_count = descriptor_->register_param_count_;
141   HEnvironment* start_environment = graph()->start_environment();
142   HBasicBlock* next_block = CreateBasicBlock(start_environment);
143   current_block()->Goto(next_block);
144   next_block->SetJoinId(BailoutId::StubEntry());
145   set_current_block(next_block);
146
147   HConstant* undefined_constant = new(zone) HConstant(
148       isolate()->factory()->undefined_value());
149   AddInstruction(undefined_constant);
150   graph()->set_undefined_constant(undefined_constant);
151
152   for (int i = 0; i < param_count; ++i) {
153     HParameter* param =
154         new(zone) HParameter(i, HParameter::REGISTER_PARAMETER);
155     AddInstruction(param);
156     start_environment->Bind(i, param);
157     parameters_[i] = param;
158   }
159
160   HInstruction* stack_parameter_count;
161   if (descriptor_->stack_parameter_count_ != NULL) {
162     ASSERT(descriptor_->environment_length() == (param_count + 1));
163     stack_parameter_count = new(zone) HParameter(param_count,
164                                                  HParameter::REGISTER_PARAMETER,
165                                                  Representation::Integer32());
166     stack_parameter_count->set_type(HType::Smi());
167     // It's essential to bind this value to the environment in case of deopt.
168     AddInstruction(stack_parameter_count);
169     start_environment->Bind(param_count, stack_parameter_count);
170     arguments_length_ = stack_parameter_count;
171   } else {
172     ASSERT(descriptor_->environment_length() == param_count);
173     stack_parameter_count = graph()->GetConstantMinus1();
174     arguments_length_ = graph()->GetConstant0();
175   }
176
177   context_ = new(zone) HContext();
178   AddInstruction(context_);
179   start_environment->BindContext(context_);
180
181   AddSimulate(BailoutId::StubEntry());
182
183   NoObservableSideEffectsScope no_effects(this);
184
185   HValue* return_value = BuildCodeStub();
186
187   // We might have extra expressions to pop from the stack in addition to the
188   // arguments above.
189   HInstruction* stack_pop_count = stack_parameter_count;
190   if (descriptor_->function_mode_ == JS_FUNCTION_STUB_MODE) {
191     if (!stack_parameter_count->IsConstant() &&
192         descriptor_->hint_stack_parameter_count_ < 0) {
193       HInstruction* amount = graph()->GetConstant1();
194       stack_pop_count = AddInstruction(
195           HAdd::New(zone, context_, stack_parameter_count, amount));
196       stack_pop_count->ChangeRepresentation(Representation::Integer32());
197       stack_pop_count->ClearFlag(HValue::kCanOverflow);
198     } else {
199       int count = descriptor_->hint_stack_parameter_count_;
200       stack_pop_count = AddInstruction(new(zone) HConstant(count));
201     }
202   }
203
204   if (current_block() != NULL) {
205     HReturn* hreturn_instruction = new(zone) HReturn(return_value,
206                                                      context_,
207                                                      stack_pop_count);
208     current_block()->Finish(hreturn_instruction);
209     set_current_block(NULL);
210   }
211   return true;
212 }
213
214
215 template <class Stub>
216 class CodeStubGraphBuilder: public CodeStubGraphBuilderBase {
217  public:
218   explicit CodeStubGraphBuilder(Stub* stub)
219       : CodeStubGraphBuilderBase(Isolate::Current(), stub) {}
220
221  protected:
222   virtual HValue* BuildCodeStub() {
223     if (casted_stub()->IsUninitialized()) {
224       return BuildCodeUninitializedStub();
225     } else {
226       return BuildCodeInitializedStub();
227     }
228   }
229
230   virtual HValue* BuildCodeInitializedStub() {
231     UNIMPLEMENTED();
232     return NULL;
233   }
234
235   virtual HValue* BuildCodeUninitializedStub() {
236     // Force a deopt that falls back to the runtime.
237     HValue* undefined = graph()->GetConstantUndefined();
238     IfBuilder builder(this);
239     builder.IfNot<HCompareObjectEqAndBranch, HValue*>(undefined, undefined);
240     builder.Then();
241     builder.ElseDeopt();
242     return undefined;
243   }
244
245   Stub* casted_stub() { return static_cast<Stub*>(stub()); }
246 };
247
248
249 Handle<Code> HydrogenCodeStub::GenerateLightweightMissCode(Isolate* isolate) {
250   Factory* factory = isolate->factory();
251
252   // Generate the new code.
253   MacroAssembler masm(isolate, NULL, 256);
254
255   {
256     // Update the static counter each time a new code stub is generated.
257     isolate->counters()->code_stubs()->Increment();
258
259     // Nested stubs are not allowed for leaves.
260     AllowStubCallsScope allow_scope(&masm, false);
261
262     // Generate the code for the stub.
263     masm.set_generating_stub(true);
264     NoCurrentFrameScope scope(&masm);
265     GenerateLightweightMiss(&masm);
266   }
267
268   // Create the code object.
269   CodeDesc desc;
270   masm.GetCode(&desc);
271
272   // Copy the generated code into a heap object.
273   Code::Flags flags = Code::ComputeFlags(
274       GetCodeKind(),
275       GetICState(),
276       GetExtraICState(),
277       GetStubType(),
278       GetStubFlags());
279   Handle<Code> new_object = factory->NewCode(
280       desc, flags, masm.CodeObject(), NeedsImmovableCode());
281   return new_object;
282 }
283
284
285 template <class Stub>
286 static Handle<Code> DoGenerateCode(Stub* stub) {
287   Isolate* isolate = Isolate::Current();
288   CodeStub::Major  major_key =
289       static_cast<HydrogenCodeStub*>(stub)->MajorKey();
290   CodeStubInterfaceDescriptor* descriptor =
291       isolate->code_stub_interface_descriptor(major_key);
292   if (descriptor->register_param_count_ < 0) {
293     stub->InitializeInterfaceDescriptor(isolate, descriptor);
294   }
295
296   // If we are uninitialized we can use a light-weight stub to enter
297   // the runtime that is significantly faster than using the standard
298   // stub-failure deopt mechanism.
299   if (stub->IsUninitialized() && descriptor->has_miss_handler()) {
300     ASSERT(descriptor->stack_parameter_count_ == NULL);
301     return stub->GenerateLightweightMissCode(isolate);
302   }
303   CodeStubGraphBuilder<Stub> builder(stub);
304   LChunk* chunk = OptimizeGraph(builder.CreateGraph());
305   return chunk->Codegen();
306 }
307
308
309 template <>
310 HValue* CodeStubGraphBuilder<FastCloneShallowArrayStub>::BuildCodeStub() {
311   Zone* zone = this->zone();
312   Factory* factory = isolate()->factory();
313   HValue* undefined = graph()->GetConstantUndefined();
314   AllocationSiteMode alloc_site_mode = casted_stub()->allocation_site_mode();
315   FastCloneShallowArrayStub::Mode mode = casted_stub()->mode();
316   int length = casted_stub()->length();
317
318   HInstruction* boilerplate =
319       AddInstruction(new(zone) HLoadKeyed(GetParameter(0),
320                                           GetParameter(1),
321                                           NULL,
322                                           FAST_ELEMENTS));
323
324   IfBuilder checker(this);
325   checker.IfNot<HCompareObjectEqAndBranch, HValue*>(boilerplate, undefined);
326   checker.Then();
327
328   if (mode == FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS) {
329     HValue* elements = AddLoadElements(boilerplate);
330
331     IfBuilder if_fixed_cow(this);
332     if_fixed_cow.IfCompareMap(elements, factory->fixed_cow_array_map());
333     if_fixed_cow.Then();
334     environment()->Push(BuildCloneShallowArray(context(),
335                                                boilerplate,
336                                                alloc_site_mode,
337                                                FAST_ELEMENTS,
338                                                0/*copy-on-write*/));
339     if_fixed_cow.Else();
340
341     IfBuilder if_fixed(this);
342     if_fixed.IfCompareMap(elements, factory->fixed_array_map());
343     if_fixed.Then();
344     environment()->Push(BuildCloneShallowArray(context(),
345                                                boilerplate,
346                                                alloc_site_mode,
347                                                FAST_ELEMENTS,
348                                                length));
349     if_fixed.Else();
350     environment()->Push(BuildCloneShallowArray(context(),
351                                                boilerplate,
352                                                alloc_site_mode,
353                                                FAST_DOUBLE_ELEMENTS,
354                                                length));
355   } else {
356     ElementsKind elements_kind = casted_stub()->ComputeElementsKind();
357     environment()->Push(BuildCloneShallowArray(context(),
358                                                boilerplate,
359                                                alloc_site_mode,
360                                                elements_kind,
361                                                length));
362   }
363
364   HValue* result = environment()->Pop();
365   checker.ElseDeopt();
366   return result;
367 }
368
369
370 Handle<Code> FastCloneShallowArrayStub::GenerateCode() {
371   return DoGenerateCode(this);
372 }
373
374
375 template <>
376 HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() {
377   Zone* zone = this->zone();
378   HValue* undefined = graph()->GetConstantUndefined();
379
380   HInstruction* boilerplate =
381       AddInstruction(new(zone) HLoadKeyed(GetParameter(0),
382                                           GetParameter(1),
383                                           NULL,
384                                           FAST_ELEMENTS));
385
386   IfBuilder checker(this);
387   checker.IfNot<HCompareObjectEqAndBranch, HValue*>(boilerplate, undefined);
388   checker.And();
389
390   int size = JSObject::kHeaderSize + casted_stub()->length() * kPointerSize;
391   HValue* boilerplate_size =
392       AddInstruction(new(zone) HInstanceSize(boilerplate));
393   HValue* size_in_words =
394       AddInstruction(new(zone) HConstant(size >> kPointerSizeLog2));
395   checker.IfCompare(boilerplate_size, size_in_words, Token::EQ);
396   checker.Then();
397
398   HValue* size_in_bytes = AddInstruction(new(zone) HConstant(size));
399   HAllocate::Flags flags = HAllocate::CAN_ALLOCATE_IN_NEW_SPACE;
400   if (isolate()->heap()->ShouldGloballyPretenure()) {
401     flags = static_cast<HAllocate::Flags>(
402        flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
403   }
404
405   HInstruction* object = AddInstruction(new(zone)
406       HAllocate(context(), size_in_bytes, HType::JSObject(), flags));
407
408   for (int i = 0; i < size; i += kPointerSize) {
409     HObjectAccess access = HObjectAccess::ForJSObjectOffset(i);
410     AddStore(object, access, AddLoad(boilerplate, access));
411   }
412
413   checker.ElseDeopt();
414   return object;
415 }
416
417
418 Handle<Code> FastCloneShallowObjectStub::GenerateCode() {
419   return DoGenerateCode(this);
420 }
421
422
423 template <>
424 HValue* CodeStubGraphBuilder<KeyedLoadFastElementStub>::BuildCodeStub() {
425   HInstruction* load = BuildUncheckedMonomorphicElementAccess(
426       GetParameter(0), GetParameter(1), NULL, NULL,
427       casted_stub()->is_js_array(), casted_stub()->elements_kind(),
428       false, NEVER_RETURN_HOLE, STANDARD_STORE);
429   return load;
430 }
431
432
433 Handle<Code> KeyedLoadFastElementStub::GenerateCode() {
434   return DoGenerateCode(this);
435 }
436
437
438 template<>
439 HValue* CodeStubGraphBuilder<LoadFieldStub>::BuildCodeStub() {
440   HObjectAccess access = casted_stub()->is_inobject() ?
441       HObjectAccess::ForJSObjectOffset(casted_stub()->offset()) :
442       HObjectAccess::ForBackingStoreOffset(casted_stub()->offset());
443   return AddInstruction(BuildLoadNamedField(GetParameter(0), access,
444       casted_stub()->representation()));
445 }
446
447
448 Handle<Code> LoadFieldStub::GenerateCode() {
449   return DoGenerateCode(this);
450 }
451
452
453 template<>
454 HValue* CodeStubGraphBuilder<KeyedLoadFieldStub>::BuildCodeStub() {
455   HObjectAccess access = casted_stub()->is_inobject() ?
456       HObjectAccess::ForJSObjectOffset(casted_stub()->offset()) :
457       HObjectAccess::ForBackingStoreOffset(casted_stub()->offset());
458   return AddInstruction(BuildLoadNamedField(GetParameter(0), access,
459       casted_stub()->representation()));
460 }
461
462
463 Handle<Code> KeyedLoadFieldStub::GenerateCode() {
464   return DoGenerateCode(this);
465 }
466
467
468 template <>
469 HValue* CodeStubGraphBuilder<KeyedStoreFastElementStub>::BuildCodeStub() {
470   BuildUncheckedMonomorphicElementAccess(
471       GetParameter(0), GetParameter(1), GetParameter(2), NULL,
472       casted_stub()->is_js_array(), casted_stub()->elements_kind(),
473       true, NEVER_RETURN_HOLE, casted_stub()->store_mode());
474
475   return GetParameter(2);
476 }
477
478
479 Handle<Code> KeyedStoreFastElementStub::GenerateCode() {
480   return DoGenerateCode(this);
481 }
482
483
484 template <>
485 HValue* CodeStubGraphBuilder<TransitionElementsKindStub>::BuildCodeStub() {
486   Zone* zone = this->zone();
487
488   HValue* js_array = GetParameter(0);
489   HValue* map = GetParameter(1);
490
491   info()->MarkAsSavesCallerDoubles();
492
493   AddInstruction(new(zone) HTrapAllocationMemento(js_array));
494
495   HInstruction* array_length =
496       AddLoad(js_array, HObjectAccess::ForArrayLength());
497   array_length->set_type(HType::Smi());
498
499   ElementsKind to_kind = casted_stub()->to_kind();
500   BuildNewSpaceArrayCheck(array_length, to_kind);
501
502   IfBuilder if_builder(this);
503
504   if_builder.IfCompare(array_length, graph()->GetConstant0(), Token::EQ);
505   if_builder.Then();
506
507   // Nothing to do, just change the map.
508
509   if_builder.Else();
510
511   HInstruction* elements = AddLoadElements(js_array);
512
513   HInstruction* elements_length = AddLoadFixedArrayLength(elements);
514
515   HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader(
516       context(), to_kind, elements_length);
517
518   BuildCopyElements(context(), elements,
519                     casted_stub()->from_kind(), new_elements,
520                     to_kind, array_length, elements_length);
521
522   AddStore(js_array, HObjectAccess::ForElementsPointer(), new_elements);
523
524   if_builder.End();
525
526   AddStore(js_array, HObjectAccess::ForMap(), map);
527
528   return js_array;
529 }
530
531
532 Handle<Code> TransitionElementsKindStub::GenerateCode() {
533   return DoGenerateCode(this);
534 }
535
536 HValue* CodeStubGraphBuilderBase::BuildArrayConstructor(
537     ElementsKind kind,
538     ContextCheckMode context_mode,
539     AllocationSiteOverrideMode override_mode,
540     ArgumentClass argument_class) {
541   HValue* constructor = GetParameter(ArrayConstructorStubBase::kConstructor);
542   if (context_mode == CONTEXT_CHECK_REQUIRED) {
543     HInstruction* array_function = BuildGetArrayFunction(context());
544     ArrayContextChecker checker(this, constructor, array_function);
545   }
546
547   HValue* property_cell = GetParameter(ArrayConstructorStubBase::kPropertyCell);
548   JSArrayBuilder array_builder(this, kind, property_cell, constructor,
549                                override_mode);
550   HValue* result = NULL;
551   switch (argument_class) {
552     case NONE:
553       result = array_builder.AllocateEmptyArray();
554       break;
555     case SINGLE:
556       result = BuildArraySingleArgumentConstructor(&array_builder);
557       break;
558     case MULTIPLE:
559       result = BuildArrayNArgumentsConstructor(&array_builder, kind);
560       break;
561   }
562
563   return result;
564 }
565
566
567 HValue* CodeStubGraphBuilderBase::BuildInternalArrayConstructor(
568     ElementsKind kind, ArgumentClass argument_class) {
569   HValue* constructor = GetParameter(
570       InternalArrayConstructorStubBase::kConstructor);
571   JSArrayBuilder array_builder(this, kind, constructor);
572
573   HValue* result = NULL;
574   switch (argument_class) {
575     case NONE:
576       result = array_builder.AllocateEmptyArray();
577       break;
578     case SINGLE:
579       result = BuildArraySingleArgumentConstructor(&array_builder);
580       break;
581     case MULTIPLE:
582       result = BuildArrayNArgumentsConstructor(&array_builder, kind);
583       break;
584   }
585   return result;
586 }
587
588
589 HValue* CodeStubGraphBuilderBase::BuildArraySingleArgumentConstructor(
590     JSArrayBuilder* array_builder) {
591   // Smi check and range check on the input arg.
592   HValue* constant_one = graph()->GetConstant1();
593   HValue* constant_zero = graph()->GetConstant0();
594
595   HInstruction* elements = AddInstruction(
596       new(zone()) HArgumentsElements(false));
597   HInstruction* argument = AddInstruction(
598       new(zone()) HAccessArgumentsAt(elements, constant_one, constant_zero));
599
600   HConstant* max_alloc_length =
601       new(zone()) HConstant(JSObject::kInitialMaxFastElementArray);
602   AddInstruction(max_alloc_length);
603   const int initial_capacity = JSArray::kPreallocatedArrayElements;
604   HConstant* initial_capacity_node = new(zone()) HConstant(initial_capacity);
605   AddInstruction(initial_capacity_node);
606
607   HBoundsCheck* checked_arg = Add<HBoundsCheck>(argument, max_alloc_length);
608   IfBuilder if_builder(this);
609   if_builder.IfCompare(checked_arg, constant_zero, Token::EQ);
610   if_builder.Then();
611   Push(initial_capacity_node);  // capacity
612   Push(constant_zero);  // length
613   if_builder.Else();
614   Push(checked_arg);  // capacity
615   Push(checked_arg);  // length
616   if_builder.End();
617
618   // Figure out total size
619   HValue* length = Pop();
620   HValue* capacity = Pop();
621   return array_builder->AllocateArray(capacity, length, true);
622 }
623
624
625 HValue* CodeStubGraphBuilderBase::BuildArrayNArgumentsConstructor(
626     JSArrayBuilder* array_builder, ElementsKind kind) {
627   // We need to fill with the hole if it's a smi array in the multi-argument
628   // case because we might have to bail out while copying arguments into
629   // the array because they aren't compatible with a smi array.
630   // If it's a double array, no problem, and if it's fast then no
631   // problem either because doubles are boxed.
632   HValue* length = GetArgumentsLength();
633   bool fill_with_hole = IsFastSmiElementsKind(kind);
634   HValue* new_object = array_builder->AllocateArray(length,
635                                                     length,
636                                                     fill_with_hole);
637   HValue* elements = array_builder->GetElementsLocation();
638   ASSERT(elements != NULL);
639
640   // Now populate the elements correctly.
641   LoopBuilder builder(this,
642                       context(),
643                       LoopBuilder::kPostIncrement);
644   HValue* start = graph()->GetConstant0();
645   HValue* key = builder.BeginBody(start, length, Token::LT);
646   HInstruction* argument_elements = AddInstruction(
647       new(zone()) HArgumentsElements(false));
648   HInstruction* argument = AddInstruction(new(zone()) HAccessArgumentsAt(
649       argument_elements, length, key));
650
651   AddInstruction(new(zone()) HStoreKeyed(elements, key, argument, kind));
652   builder.EndBody();
653   return new_object;
654 }
655
656
657 template <>
658 HValue* CodeStubGraphBuilder<ArrayNoArgumentConstructorStub>::BuildCodeStub() {
659   ElementsKind kind = casted_stub()->elements_kind();
660   ContextCheckMode context_mode = casted_stub()->context_mode();
661   AllocationSiteOverrideMode override_mode = casted_stub()->override_mode();
662   return BuildArrayConstructor(kind, context_mode, override_mode, NONE);
663 }
664
665
666 Handle<Code> ArrayNoArgumentConstructorStub::GenerateCode() {
667   return DoGenerateCode(this);
668 }
669
670
671 template <>
672 HValue* CodeStubGraphBuilder<ArraySingleArgumentConstructorStub>::
673     BuildCodeStub() {
674   ElementsKind kind = casted_stub()->elements_kind();
675   ContextCheckMode context_mode = casted_stub()->context_mode();
676   AllocationSiteOverrideMode override_mode = casted_stub()->override_mode();
677   return BuildArrayConstructor(kind, context_mode, override_mode, SINGLE);
678 }
679
680
681 Handle<Code> ArraySingleArgumentConstructorStub::GenerateCode() {
682   return DoGenerateCode(this);
683 }
684
685
686 template <>
687 HValue* CodeStubGraphBuilder<ArrayNArgumentsConstructorStub>::BuildCodeStub() {
688   ElementsKind kind = casted_stub()->elements_kind();
689   ContextCheckMode context_mode = casted_stub()->context_mode();
690   AllocationSiteOverrideMode override_mode = casted_stub()->override_mode();
691   return BuildArrayConstructor(kind, context_mode, override_mode, MULTIPLE);
692 }
693
694
695 Handle<Code> ArrayNArgumentsConstructorStub::GenerateCode() {
696   return DoGenerateCode(this);
697 }
698
699
700 template <>
701 HValue* CodeStubGraphBuilder<InternalArrayNoArgumentConstructorStub>::
702     BuildCodeStub() {
703   ElementsKind kind = casted_stub()->elements_kind();
704   return BuildInternalArrayConstructor(kind, NONE);
705 }
706
707
708 Handle<Code> InternalArrayNoArgumentConstructorStub::GenerateCode() {
709   return DoGenerateCode(this);
710 }
711
712
713 template <>
714 HValue* CodeStubGraphBuilder<InternalArraySingleArgumentConstructorStub>::
715     BuildCodeStub() {
716   ElementsKind kind = casted_stub()->elements_kind();
717   return BuildInternalArrayConstructor(kind, SINGLE);
718 }
719
720
721 Handle<Code> InternalArraySingleArgumentConstructorStub::GenerateCode() {
722   return DoGenerateCode(this);
723 }
724
725
726 template <>
727 HValue* CodeStubGraphBuilder<InternalArrayNArgumentsConstructorStub>::
728     BuildCodeStub() {
729   ElementsKind kind = casted_stub()->elements_kind();
730   return BuildInternalArrayConstructor(kind, MULTIPLE);
731 }
732
733
734 Handle<Code> InternalArrayNArgumentsConstructorStub::GenerateCode() {
735   return DoGenerateCode(this);
736 }
737
738
739 template <>
740 HValue* CodeStubGraphBuilder<CompareNilICStub>::BuildCodeInitializedStub() {
741   Isolate* isolate = graph()->isolate();
742   CompareNilICStub* stub = casted_stub();
743   HIfContinuation continuation;
744   Handle<Map> sentinel_map(isolate->heap()->meta_map());
745   Handle<Type> type =
746       CompareNilICStub::StateToType(isolate, stub->GetState(), sentinel_map);
747   BuildCompareNil(GetParameter(0), type, RelocInfo::kNoPosition, &continuation);
748   IfBuilder if_nil(this, &continuation);
749   if_nil.Then();
750   if (continuation.IsFalseReachable()) {
751     if_nil.Else();
752     if_nil.Return(graph()->GetConstant0());
753   }
754   if_nil.End();
755   return continuation.IsTrueReachable()
756       ? graph()->GetConstant1()
757       : graph()->GetConstantUndefined();
758 }
759
760
761 Handle<Code> CompareNilICStub::GenerateCode() {
762   return DoGenerateCode(this);
763 }
764
765
766 template <>
767 HValue* CodeStubGraphBuilder<ToBooleanStub>::BuildCodeInitializedStub() {
768   ToBooleanStub* stub = casted_stub();
769
770   IfBuilder if_true(this);
771   if_true.If<HBranch>(GetParameter(0), stub->GetTypes());
772   if_true.Then();
773     if_true.Return(graph()->GetConstant1());
774   if_true.Else();
775   if_true.End();
776   return graph()->GetConstant0();
777 }
778
779
780 Handle<Code> ToBooleanStub::GenerateCode() {
781   return DoGenerateCode(this);
782 }
783
784
785 } }  // namespace v8::internal