99c4db55b749c89dbd1cb657c35bc90ebb97773c
[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                                 bool disable_allocation_sites,
110                                 ArgumentClass argument_class);
111   HValue* BuildInternalArrayConstructor(ElementsKind kind,
112                                         ArgumentClass argument_class);
113
114  private:
115   HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder);
116   HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder,
117                                           ElementsKind kind);
118
119   SmartArrayPointer<HParameter*> parameters_;
120   HValue* arguments_length_;
121   CompilationInfoWithZone info_;
122   CodeStubInterfaceDescriptor* descriptor_;
123   HContext* context_;
124 };
125
126
127 bool CodeStubGraphBuilderBase::BuildGraph() {
128   // Update the static counter each time a new code stub is generated.
129   isolate()->counters()->code_stubs()->Increment();
130
131   if (FLAG_trace_hydrogen) {
132     const char* name = CodeStub::MajorName(stub()->MajorKey(), false);
133     PrintF("-----------------------------------------------------------\n");
134     PrintF("Compiling stub %s using hydrogen\n", name);
135     isolate()->GetHTracer()->TraceCompilation(&info_);
136   }
137
138   Zone* zone = this->zone();
139   int param_count = descriptor_->register_param_count_;
140   HEnvironment* start_environment = graph()->start_environment();
141   HBasicBlock* next_block = CreateBasicBlock(start_environment);
142   current_block()->Goto(next_block);
143   next_block->SetJoinId(BailoutId::StubEntry());
144   set_current_block(next_block);
145
146   HConstant* undefined_constant = new(zone) HConstant(
147       isolate()->factory()->undefined_value(), Representation::Tagged());
148   AddInstruction(undefined_constant);
149   graph()->set_undefined_constant(undefined_constant);
150
151   for (int i = 0; i < param_count; ++i) {
152     HParameter* param =
153         new(zone) HParameter(i, HParameter::REGISTER_PARAMETER);
154     AddInstruction(param);
155     start_environment->Bind(i, param);
156     parameters_[i] = param;
157   }
158
159   HInstruction* stack_parameter_count;
160   if (descriptor_->stack_parameter_count_ != NULL) {
161     ASSERT(descriptor_->environment_length() == (param_count + 1));
162     stack_parameter_count = new(zone) HParameter(param_count,
163                                                  HParameter::REGISTER_PARAMETER,
164                                                  Representation::Integer32());
165     stack_parameter_count->set_type(HType::Smi());
166     // It's essential to bind this value to the environment in case of deopt.
167     AddInstruction(stack_parameter_count);
168     start_environment->Bind(param_count, stack_parameter_count);
169     arguments_length_ = stack_parameter_count;
170   } else {
171     ASSERT(descriptor_->environment_length() == param_count);
172     stack_parameter_count = graph()->GetConstantMinus1();
173     arguments_length_ = graph()->GetConstant0();
174   }
175
176   context_ = new(zone) HContext();
177   AddInstruction(context_);
178   start_environment->BindContext(context_);
179
180   AddSimulate(BailoutId::StubEntry());
181
182   NoObservableSideEffectsScope no_effects(this);
183
184   HValue* return_value = BuildCodeStub();
185
186   // We might have extra expressions to pop from the stack in addition to the
187   // arguments above.
188   HInstruction* stack_pop_count = stack_parameter_count;
189   if (descriptor_->function_mode_ == JS_FUNCTION_STUB_MODE) {
190     if (!stack_parameter_count->IsConstant() &&
191         descriptor_->hint_stack_parameter_count_ < 0) {
192       HInstruction* amount = graph()->GetConstant1();
193       stack_pop_count = AddInstruction(
194           HAdd::New(zone, context_, stack_parameter_count, amount));
195       stack_pop_count->ChangeRepresentation(Representation::Integer32());
196       stack_pop_count->ClearFlag(HValue::kCanOverflow);
197     } else {
198       int count = descriptor_->hint_stack_parameter_count_;
199       stack_pop_count = AddInstruction(new(zone)
200           HConstant(count, Representation::Integer32()));
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                                          Representation::Integer32()));
396   checker.IfCompare(boilerplate_size, size_in_words, Token::EQ);
397   checker.Then();
398
399   HValue* size_in_bytes =
400       AddInstruction(new(zone) HConstant(size, Representation::Integer32()));
401   HAllocate::Flags flags = HAllocate::CAN_ALLOCATE_IN_NEW_SPACE;
402   if (isolate()->heap()->ShouldGloballyPretenure()) {
403     flags = static_cast<HAllocate::Flags>(
404        flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
405   }
406
407   HInstruction* object = AddInstruction(new(zone)
408       HAllocate(context(), size_in_bytes, HType::JSObject(), flags));
409
410   for (int i = 0; i < size; i += kPointerSize) {
411     HObjectAccess access = HObjectAccess::ForJSObjectOffset(i);
412     AddStore(object, access, AddLoad(boilerplate, access));
413   }
414
415   checker.ElseDeopt();
416   return object;
417 }
418
419
420 Handle<Code> FastCloneShallowObjectStub::GenerateCode() {
421   return DoGenerateCode(this);
422 }
423
424
425 template <>
426 HValue* CodeStubGraphBuilder<KeyedLoadFastElementStub>::BuildCodeStub() {
427   HInstruction* load = BuildUncheckedMonomorphicElementAccess(
428       GetParameter(0), GetParameter(1), NULL, NULL,
429       casted_stub()->is_js_array(), casted_stub()->elements_kind(),
430       false, NEVER_RETURN_HOLE, STANDARD_STORE);
431   return load;
432 }
433
434
435 Handle<Code> KeyedLoadFastElementStub::GenerateCode() {
436   return DoGenerateCode(this);
437 }
438
439
440 template<>
441 HValue* CodeStubGraphBuilder<LoadFieldStub>::BuildCodeStub() {
442   HObjectAccess access = casted_stub()->is_inobject() ?
443       HObjectAccess::ForJSObjectOffset(casted_stub()->offset()) :
444       HObjectAccess::ForBackingStoreOffset(casted_stub()->offset());
445   return AddInstruction(BuildLoadNamedField(GetParameter(0), access,
446       casted_stub()->representation()));
447 }
448
449
450 Handle<Code> LoadFieldStub::GenerateCode() {
451   return DoGenerateCode(this);
452 }
453
454
455 template<>
456 HValue* CodeStubGraphBuilder<KeyedLoadFieldStub>::BuildCodeStub() {
457   HObjectAccess access = casted_stub()->is_inobject() ?
458       HObjectAccess::ForJSObjectOffset(casted_stub()->offset()) :
459       HObjectAccess::ForBackingStoreOffset(casted_stub()->offset());
460   return AddInstruction(BuildLoadNamedField(GetParameter(0), access,
461       casted_stub()->representation()));
462 }
463
464
465 Handle<Code> KeyedLoadFieldStub::GenerateCode() {
466   return DoGenerateCode(this);
467 }
468
469
470 template <>
471 HValue* CodeStubGraphBuilder<KeyedStoreFastElementStub>::BuildCodeStub() {
472   BuildUncheckedMonomorphicElementAccess(
473       GetParameter(0), GetParameter(1), GetParameter(2), NULL,
474       casted_stub()->is_js_array(), casted_stub()->elements_kind(),
475       true, NEVER_RETURN_HOLE, casted_stub()->store_mode());
476
477   return GetParameter(2);
478 }
479
480
481 Handle<Code> KeyedStoreFastElementStub::GenerateCode() {
482   return DoGenerateCode(this);
483 }
484
485
486 template <>
487 HValue* CodeStubGraphBuilder<TransitionElementsKindStub>::BuildCodeStub() {
488   Zone* zone = this->zone();
489
490   HValue* js_array = GetParameter(0);
491   HValue* map = GetParameter(1);
492
493   info()->MarkAsSavesCallerDoubles();
494
495   AddInstruction(new(zone) HTrapAllocationMemento(js_array));
496
497   HInstruction* array_length =
498       AddLoad(js_array, HObjectAccess::ForArrayLength());
499   array_length->set_type(HType::Smi());
500
501   ElementsKind to_kind = casted_stub()->to_kind();
502   BuildNewSpaceArrayCheck(array_length, to_kind);
503
504   IfBuilder if_builder(this);
505
506   if_builder.IfCompare(array_length, graph()->GetConstant0(), Token::EQ);
507   if_builder.Then();
508
509   // Nothing to do, just change the map.
510
511   if_builder.Else();
512
513   HInstruction* elements = AddLoadElements(js_array);
514
515   HInstruction* elements_length =
516       AddInstruction(new(zone) HFixedArrayBaseLength(elements));
517
518   HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader(
519       context(), to_kind, elements_length);
520
521   BuildCopyElements(context(), elements,
522                     casted_stub()->from_kind(), new_elements,
523                     to_kind, array_length, elements_length);
524
525   AddStore(js_array, HObjectAccess::ForElementsPointer(), new_elements);
526
527   if_builder.End();
528
529   AddStore(js_array, HObjectAccess::ForMap(), map);
530
531   return js_array;
532 }
533
534
535 Handle<Code> TransitionElementsKindStub::GenerateCode() {
536   return DoGenerateCode(this);
537 }
538
539 HValue* CodeStubGraphBuilderBase::BuildArrayConstructor(
540     ElementsKind kind, bool disable_allocation_sites,
541     ArgumentClass argument_class) {
542   HValue* constructor = GetParameter(ArrayConstructorStubBase::kConstructor);
543   HValue* property_cell = GetParameter(ArrayConstructorStubBase::kPropertyCell);
544   HInstruction* array_function = BuildGetArrayFunction(context());
545
546   ArrayContextChecker(this, constructor, array_function);
547   JSArrayBuilder array_builder(this, kind, property_cell,
548                                disable_allocation_sites);
549   HValue* result = NULL;
550   switch (argument_class) {
551     case NONE:
552       result = array_builder.AllocateEmptyArray();
553       break;
554     case SINGLE:
555       result = BuildArraySingleArgumentConstructor(&array_builder);
556       break;
557     case MULTIPLE:
558       result = BuildArrayNArgumentsConstructor(&array_builder, kind);
559       break;
560   }
561   return result;
562 }
563
564
565 HValue* CodeStubGraphBuilderBase::BuildInternalArrayConstructor(
566     ElementsKind kind, ArgumentClass argument_class) {
567   HValue* constructor = GetParameter(
568       InternalArrayConstructorStubBase::kConstructor);
569   JSArrayBuilder array_builder(this, kind, constructor);
570
571   HValue* result = NULL;
572   switch (argument_class) {
573     case NONE:
574       result = array_builder.AllocateEmptyArray();
575       break;
576     case SINGLE:
577       result = BuildArraySingleArgumentConstructor(&array_builder);
578       break;
579     case MULTIPLE:
580       result = BuildArrayNArgumentsConstructor(&array_builder, kind);
581       break;
582   }
583   return result;
584 }
585
586
587 HValue* CodeStubGraphBuilderBase::BuildArraySingleArgumentConstructor(
588     JSArrayBuilder* array_builder) {
589   // Smi check and range check on the input arg.
590   HValue* constant_one = graph()->GetConstant1();
591   HValue* constant_zero = graph()->GetConstant0();
592
593   HInstruction* elements = AddInstruction(
594       new(zone()) HArgumentsElements(false));
595   HInstruction* argument = AddInstruction(
596       new(zone()) HAccessArgumentsAt(elements, constant_one, constant_zero));
597
598   HConstant* max_alloc_length =
599       new(zone()) HConstant(JSObject::kInitialMaxFastElementArray);
600   AddInstruction(max_alloc_length);
601   const int initial_capacity = JSArray::kPreallocatedArrayElements;
602   HConstant* initial_capacity_node = new(zone()) HConstant(initial_capacity);
603   AddInstruction(initial_capacity_node);
604
605   HBoundsCheck* checked_arg = AddBoundsCheck(argument, max_alloc_length);
606   IfBuilder if_builder(this);
607   if_builder.IfCompare(checked_arg, constant_zero, Token::EQ);
608   if_builder.Then();
609   Push(initial_capacity_node);  // capacity
610   Push(constant_zero);  // length
611   if_builder.Else();
612   Push(checked_arg);  // capacity
613   Push(checked_arg);  // length
614   if_builder.End();
615
616   // Figure out total size
617   HValue* length = Pop();
618   HValue* capacity = Pop();
619   return array_builder->AllocateArray(capacity, length, true);
620 }
621
622
623 HValue* CodeStubGraphBuilderBase::BuildArrayNArgumentsConstructor(
624     JSArrayBuilder* array_builder, ElementsKind kind) {
625   // We need to fill with the hole if it's a smi array in the multi-argument
626   // case because we might have to bail out while copying arguments into
627   // the array because they aren't compatible with a smi array.
628   // If it's a double array, no problem, and if it's fast then no
629   // problem either because doubles are boxed.
630   HValue* length = GetArgumentsLength();
631   bool fill_with_hole = IsFastSmiElementsKind(kind);
632   HValue* new_object = array_builder->AllocateArray(length,
633                                                     length,
634                                                     fill_with_hole);
635   HValue* elements = array_builder->GetElementsLocation();
636   ASSERT(elements != NULL);
637
638   // Now populate the elements correctly.
639   LoopBuilder builder(this,
640                       context(),
641                       LoopBuilder::kPostIncrement);
642   HValue* start = graph()->GetConstant0();
643   HValue* key = builder.BeginBody(start, length, Token::LT);
644   HInstruction* argument_elements = AddInstruction(
645       new(zone()) HArgumentsElements(false));
646   HInstruction* argument = AddInstruction(new(zone()) HAccessArgumentsAt(
647       argument_elements, length, key));
648
649   AddInstruction(new(zone()) HStoreKeyed(elements, key, argument, kind));
650   builder.EndBody();
651   return new_object;
652 }
653
654
655 template <>
656 HValue* CodeStubGraphBuilder<ArrayNoArgumentConstructorStub>::BuildCodeStub() {
657   ElementsKind kind = casted_stub()->elements_kind();
658   bool disable_allocation_sites = casted_stub()->disable_allocation_sites();
659   return BuildArrayConstructor(kind, disable_allocation_sites, NONE);
660 }
661
662
663 Handle<Code> ArrayNoArgumentConstructorStub::GenerateCode() {
664   return DoGenerateCode(this);
665 }
666
667
668 template <>
669 HValue* CodeStubGraphBuilder<ArraySingleArgumentConstructorStub>::
670     BuildCodeStub() {
671   ElementsKind kind = casted_stub()->elements_kind();
672   bool disable_allocation_sites = casted_stub()->disable_allocation_sites();
673   return BuildArrayConstructor(kind, disable_allocation_sites, SINGLE);
674 }
675
676
677 Handle<Code> ArraySingleArgumentConstructorStub::GenerateCode() {
678   return DoGenerateCode(this);
679 }
680
681
682 template <>
683 HValue* CodeStubGraphBuilder<ArrayNArgumentsConstructorStub>::BuildCodeStub() {
684   ElementsKind kind = casted_stub()->elements_kind();
685   bool disable_allocation_sites = casted_stub()->disable_allocation_sites();
686   return BuildArrayConstructor(kind, disable_allocation_sites, MULTIPLE);
687 }
688
689
690 Handle<Code> ArrayNArgumentsConstructorStub::GenerateCode() {
691   return DoGenerateCode(this);
692 }
693
694
695 template <>
696 HValue* CodeStubGraphBuilder<InternalArrayNoArgumentConstructorStub>::
697     BuildCodeStub() {
698   ElementsKind kind = casted_stub()->elements_kind();
699   return BuildInternalArrayConstructor(kind, NONE);
700 }
701
702
703 Handle<Code> InternalArrayNoArgumentConstructorStub::GenerateCode() {
704   return DoGenerateCode(this);
705 }
706
707
708 template <>
709 HValue* CodeStubGraphBuilder<InternalArraySingleArgumentConstructorStub>::
710     BuildCodeStub() {
711   ElementsKind kind = casted_stub()->elements_kind();
712   return BuildInternalArrayConstructor(kind, SINGLE);
713 }
714
715
716 Handle<Code> InternalArraySingleArgumentConstructorStub::GenerateCode() {
717   return DoGenerateCode(this);
718 }
719
720
721 template <>
722 HValue* CodeStubGraphBuilder<InternalArrayNArgumentsConstructorStub>::
723     BuildCodeStub() {
724   ElementsKind kind = casted_stub()->elements_kind();
725   return BuildInternalArrayConstructor(kind, MULTIPLE);
726 }
727
728
729 Handle<Code> InternalArrayNArgumentsConstructorStub::GenerateCode() {
730   return DoGenerateCode(this);
731 }
732
733
734 template <>
735 HValue* CodeStubGraphBuilder<CompareNilICStub>::BuildCodeInitializedStub() {
736   CompareNilICStub* stub = casted_stub();
737   HIfContinuation continuation;
738   Handle<Map> sentinel_map(graph()->isolate()->heap()->meta_map());
739   BuildCompareNil(GetParameter(0),
740                   stub->GetTypes(), sentinel_map,
741                   RelocInfo::kNoPosition, &continuation);
742   IfBuilder if_nil(this, &continuation);
743   if_nil.Then();
744   if (continuation.IsFalseReachable()) {
745     if_nil.Else();
746     if_nil.Return(graph()->GetConstant0());
747   }
748   if_nil.End();
749   return continuation.IsTrueReachable()
750       ? graph()->GetConstant1()
751       : graph()->GetConstantUndefined();
752 }
753
754
755 Handle<Code> CompareNilICStub::GenerateCode() {
756   return DoGenerateCode(this);
757 }
758
759
760 template <>
761 HValue* CodeStubGraphBuilder<ToBooleanStub>::BuildCodeInitializedStub() {
762   ToBooleanStub* stub = casted_stub();
763
764   IfBuilder if_true(this);
765   if_true.If<HBranch>(GetParameter(0), stub->GetTypes());
766   if_true.Then();
767     if_true.Return(graph()->GetConstant1());
768   if_true.Else();
769   if_true.End();
770   return graph()->GetConstant0();
771 }
772
773
774 Handle<Code> ToBooleanStub::GenerateCode() {
775   return DoGenerateCode(this);
776 }
777
778
779 } }  // namespace v8::internal