v8: upgrade to v3.19.3
[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   Isolate* isolate =  graph->isolate();
40   AssertNoAllocation no_gc;
41   NoHandleAllocation no_handles(isolate);
42   HandleDereferenceGuard no_deref(isolate, HandleDereferenceGuard::DISALLOW);
43
44   ASSERT(graph != NULL);
45   SmartArrayPointer<char> bailout_reason;
46   if (!graph->Optimize(&bailout_reason)) {
47     FATAL(bailout_reason.is_empty() ? "unknown" : *bailout_reason);
48   }
49   LChunk* chunk = LChunk::NewChunk(graph);
50   if (chunk == NULL) {
51     FATAL(graph->info()->bailout_reason());
52   }
53   return chunk;
54 }
55
56
57 class CodeStubGraphBuilderBase : public HGraphBuilder {
58  public:
59   CodeStubGraphBuilderBase(Isolate* isolate, HydrogenCodeStub* stub)
60       : HGraphBuilder(&info_),
61         arguments_length_(NULL),
62         info_(stub, isolate),
63         context_(NULL) {
64     descriptor_ = stub->GetInterfaceDescriptor(isolate);
65     parameters_.Reset(new HParameter*[descriptor_->register_param_count_]);
66   }
67   virtual bool BuildGraph();
68
69  protected:
70   virtual HValue* BuildCodeStub() = 0;
71   HParameter* GetParameter(int parameter) {
72     ASSERT(parameter < descriptor_->register_param_count_);
73     return parameters_[parameter];
74   }
75   HValue* GetArgumentsLength() {
76     // This is initialized in BuildGraph()
77     ASSERT(arguments_length_ != NULL);
78     return arguments_length_;
79   }
80   CompilationInfo* info() { return &info_; }
81   HydrogenCodeStub* stub() { return info_.code_stub(); }
82   HContext* context() { return context_; }
83   Isolate* isolate() { return info_.isolate(); }
84
85   class ArrayContextChecker {
86    public:
87     ArrayContextChecker(HGraphBuilder* builder, HValue* constructor,
88                         HValue* array_function)
89         : checker_(builder) {
90       checker_.If<HCompareObjectEqAndBranch, HValue*>(constructor,
91                                                       array_function);
92       checker_.Then();
93     }
94
95     ~ArrayContextChecker() {
96       checker_.ElseDeopt();
97       checker_.End();
98     }
99    private:
100     IfBuilder checker_;
101   };
102
103  private:
104   SmartArrayPointer<HParameter*> parameters_;
105   HValue* arguments_length_;
106   CompilationInfoWithZone info_;
107   CodeStubInterfaceDescriptor* descriptor_;
108   HContext* context_;
109 };
110
111
112 bool CodeStubGraphBuilderBase::BuildGraph() {
113   // Update the static counter each time a new code stub is generated.
114   isolate()->counters()->code_stubs()->Increment();
115
116   if (FLAG_trace_hydrogen) {
117     const char* name = CodeStub::MajorName(stub()->MajorKey(), false);
118     PrintF("-----------------------------------------------------------\n");
119     PrintF("Compiling stub %s using hydrogen\n", name);
120     isolate()->GetHTracer()->TraceCompilation(&info_);
121   }
122
123   Zone* zone = this->zone();
124   int param_count = descriptor_->register_param_count_;
125   HEnvironment* start_environment = graph()->start_environment();
126   HBasicBlock* next_block = CreateBasicBlock(start_environment);
127   current_block()->Goto(next_block);
128   next_block->SetJoinId(BailoutId::StubEntry());
129   set_current_block(next_block);
130
131   HConstant* undefined_constant = new(zone) HConstant(
132       isolate()->factory()->undefined_value(), Representation::Tagged());
133   AddInstruction(undefined_constant);
134   graph()->set_undefined_constant(undefined_constant);
135
136   for (int i = 0; i < param_count; ++i) {
137     HParameter* param =
138         new(zone) HParameter(i, HParameter::REGISTER_PARAMETER);
139     AddInstruction(param);
140     start_environment->Bind(i, param);
141     parameters_[i] = param;
142   }
143
144   HInstruction* stack_parameter_count;
145   if (descriptor_->stack_parameter_count_ != NULL) {
146     ASSERT(descriptor_->environment_length() == (param_count + 1));
147     stack_parameter_count = new(zone) HParameter(param_count,
148                                                  HParameter::REGISTER_PARAMETER,
149                                                  Representation::Integer32());
150     stack_parameter_count->set_type(HType::Smi());
151     // it's essential to bind this value to the environment in case of deopt
152     AddInstruction(stack_parameter_count);
153     start_environment->Bind(param_count, stack_parameter_count);
154     arguments_length_ = stack_parameter_count;
155   } else {
156     ASSERT(descriptor_->environment_length() == param_count);
157     stack_parameter_count = graph()->GetConstantMinus1();
158     arguments_length_ = graph()->GetConstant0();
159   }
160
161   context_ = new(zone) HContext();
162   AddInstruction(context_);
163   start_environment->BindContext(context_);
164
165   AddSimulate(BailoutId::StubEntry());
166
167   NoObservableSideEffectsScope no_effects(this);
168
169   HValue* return_value = BuildCodeStub();
170
171   // We might have extra expressions to pop from the stack in addition to the
172   // arguments above
173   HInstruction* stack_pop_count = stack_parameter_count;
174   if (descriptor_->function_mode_ == JS_FUNCTION_STUB_MODE) {
175     if (!stack_parameter_count->IsConstant() &&
176         descriptor_->hint_stack_parameter_count_ < 0) {
177       HInstruction* amount = graph()->GetConstant1();
178       stack_pop_count = AddInstruction(
179           HAdd::New(zone, context_, stack_parameter_count, amount));
180       stack_pop_count->ChangeRepresentation(Representation::Integer32());
181       stack_pop_count->ClearFlag(HValue::kCanOverflow);
182     } else {
183       int count = descriptor_->hint_stack_parameter_count_;
184       stack_pop_count = AddInstruction(new(zone)
185           HConstant(count, Representation::Integer32()));
186     }
187   }
188
189   if (!current_block()->IsFinished()) {
190     HReturn* hreturn_instruction = new(zone) HReturn(return_value,
191                                                      context_,
192                                                      stack_pop_count);
193     current_block()->Finish(hreturn_instruction);
194   }
195   return true;
196 }
197
198
199 template <class Stub>
200 class CodeStubGraphBuilder: public CodeStubGraphBuilderBase {
201  public:
202   explicit CodeStubGraphBuilder(Stub* stub)
203       : CodeStubGraphBuilderBase(Isolate::Current(), stub) {}
204
205  protected:
206   virtual HValue* BuildCodeStub() {
207     if (casted_stub()->IsMiss()) {
208       return BuildCodeInitializedStub();
209     } else {
210       return BuildCodeUninitializedStub();
211     }
212   }
213
214   virtual HValue* BuildCodeInitializedStub() {
215     UNIMPLEMENTED();
216     return NULL;
217   }
218
219   virtual HValue* BuildCodeUninitializedStub() {
220     // Force a deopt that falls back to the runtime.
221     HValue* undefined = graph()->GetConstantUndefined();
222     IfBuilder builder(this);
223     builder.IfNot<HCompareObjectEqAndBranch, HValue*>(undefined, undefined);
224     builder.Then();
225     builder.ElseDeopt();
226     return undefined;
227   }
228
229   Stub* casted_stub() { return static_cast<Stub*>(stub()); }
230 };
231
232
233 Handle<Code> HydrogenCodeStub::GenerateLightweightMissCode(Isolate* isolate) {
234   Factory* factory = isolate->factory();
235
236   // Generate the new code.
237   MacroAssembler masm(isolate, NULL, 256);
238
239   {
240     // Update the static counter each time a new code stub is generated.
241     isolate->counters()->code_stubs()->Increment();
242
243     // Nested stubs are not allowed for leaves.
244     AllowStubCallsScope allow_scope(&masm, false);
245
246     // Generate the code for the stub.
247     masm.set_generating_stub(true);
248     NoCurrentFrameScope scope(&masm);
249     GenerateLightweightMiss(&masm);
250   }
251
252   // Create the code object.
253   CodeDesc desc;
254   masm.GetCode(&desc);
255
256   // Copy the generated code into a heap object.
257   Code::Flags flags = Code::ComputeFlags(
258       GetCodeKind(),
259       GetICState(),
260       GetExtraICState(),
261       GetStubType(),
262       GetStubFlags());
263   Handle<Code> new_object = factory->NewCode(
264       desc, flags, masm.CodeObject(), NeedsImmovableCode());
265   return new_object;
266 }
267
268
269 template <class Stub>
270 static Handle<Code> DoGenerateCode(Stub* stub) {
271   Isolate* isolate = Isolate::Current();
272   CodeStub::Major  major_key =
273       static_cast<HydrogenCodeStub*>(stub)->MajorKey();
274   CodeStubInterfaceDescriptor* descriptor =
275       isolate->code_stub_interface_descriptor(major_key);
276   if (descriptor->register_param_count_ < 0) {
277     stub->InitializeInterfaceDescriptor(isolate, descriptor);
278   }
279   // The miss case without stack parameters can use a light-weight stub to enter
280   // the runtime that is significantly faster than using the standard
281   // stub-failure deopt mechanism.
282   if (stub->IsMiss() && descriptor->stack_parameter_count_ == NULL) {
283     return stub->GenerateLightweightMissCode(isolate);
284   } else {
285     CodeStubGraphBuilder<Stub> builder(stub);
286     LChunk* chunk = OptimizeGraph(builder.CreateGraph());
287     return chunk->Codegen();
288   }
289 }
290
291
292 template <>
293 HValue* CodeStubGraphBuilder<FastCloneShallowArrayStub>::BuildCodeStub() {
294   Zone* zone = this->zone();
295   Factory* factory = isolate()->factory();
296   HValue* undefined = graph()->GetConstantUndefined();
297   AllocationSiteMode alloc_site_mode = casted_stub()->allocation_site_mode();
298   FastCloneShallowArrayStub::Mode mode = casted_stub()->mode();
299   int length = casted_stub()->length();
300
301   HInstruction* boilerplate =
302       AddInstruction(new(zone) HLoadKeyed(GetParameter(0),
303                                           GetParameter(1),
304                                           NULL,
305                                           FAST_ELEMENTS));
306
307   IfBuilder checker(this);
308   checker.IfNot<HCompareObjectEqAndBranch, HValue*>(boilerplate, undefined);
309   checker.Then();
310
311   if (mode == FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS) {
312     HValue* elements = AddLoadElements(boilerplate);
313
314     IfBuilder if_fixed_cow(this);
315     if_fixed_cow.IfCompareMap(elements, factory->fixed_cow_array_map());
316     if_fixed_cow.Then();
317     environment()->Push(BuildCloneShallowArray(context(),
318                                                boilerplate,
319                                                alloc_site_mode,
320                                                FAST_ELEMENTS,
321                                                0/*copy-on-write*/));
322     if_fixed_cow.Else();
323
324     IfBuilder if_fixed(this);
325     if_fixed.IfCompareMap(elements, factory->fixed_array_map());
326     if_fixed.Then();
327     environment()->Push(BuildCloneShallowArray(context(),
328                                                boilerplate,
329                                                alloc_site_mode,
330                                                FAST_ELEMENTS,
331                                                length));
332     if_fixed.Else();
333     environment()->Push(BuildCloneShallowArray(context(),
334                                                boilerplate,
335                                                alloc_site_mode,
336                                                FAST_DOUBLE_ELEMENTS,
337                                                length));
338   } else {
339     ElementsKind elements_kind = casted_stub()->ComputeElementsKind();
340     environment()->Push(BuildCloneShallowArray(context(),
341                                                boilerplate,
342                                                alloc_site_mode,
343                                                elements_kind,
344                                                length));
345   }
346
347   HValue* result = environment()->Pop();
348   checker.ElseDeopt();
349   return result;
350 }
351
352
353 Handle<Code> FastCloneShallowArrayStub::GenerateCode() {
354   return DoGenerateCode(this);
355 }
356
357
358 template <>
359 HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() {
360   Zone* zone = this->zone();
361   Factory* factory = isolate()->factory();
362   HValue* undefined = graph()->GetConstantUndefined();
363
364   HInstruction* boilerplate =
365       AddInstruction(new(zone) HLoadKeyed(GetParameter(0),
366                                           GetParameter(1),
367                                           NULL,
368                                           FAST_ELEMENTS));
369
370   IfBuilder checker(this);
371   checker.IfNot<HCompareObjectEqAndBranch, HValue*>(boilerplate, undefined);
372   checker.And();
373
374   int size = JSObject::kHeaderSize + casted_stub()->length() * kPointerSize;
375   HValue* boilerplate_size =
376       AddInstruction(new(zone) HInstanceSize(boilerplate));
377   HValue* size_in_words =
378       AddInstruction(new(zone) HConstant(size >> kPointerSizeLog2,
379                                          Representation::Integer32()));
380   checker.IfCompare(boilerplate_size, size_in_words, Token::EQ);
381   checker.Then();
382
383   HValue* size_in_bytes =
384       AddInstruction(new(zone) HConstant(size, Representation::Integer32()));
385   HAllocate::Flags flags = HAllocate::CAN_ALLOCATE_IN_NEW_SPACE;
386   if (FLAG_pretenure_literals) {
387     flags = static_cast<HAllocate::Flags>(
388        flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
389   }
390   HInstruction* object =
391       AddInstruction(new(zone) HAllocate(context(),
392                                          size_in_bytes,
393                                          HType::JSObject(),
394                                          flags));
395
396   for (int i = 0; i < size; i += kPointerSize) {
397     HInstruction* value =
398         AddInstruction(new(zone) HLoadNamedField(
399             boilerplate, true, Representation::Tagged(), i));
400     AddInstruction(new(zone) HStoreNamedField(object,
401                                               factory->empty_string(),
402                                               value, true,
403                                               Representation::Tagged(), i));
404   }
405
406   checker.ElseDeopt();
407   return object;
408 }
409
410
411 Handle<Code> FastCloneShallowObjectStub::GenerateCode() {
412   return DoGenerateCode(this);
413 }
414
415
416 template <>
417 HValue* CodeStubGraphBuilder<KeyedLoadFastElementStub>::BuildCodeStub() {
418   HInstruction* load = BuildUncheckedMonomorphicElementAccess(
419       GetParameter(0), GetParameter(1), NULL, NULL,
420       casted_stub()->is_js_array(), casted_stub()->elements_kind(),
421       false, NEVER_RETURN_HOLE, STANDARD_STORE, Representation::Tagged());
422   return load;
423 }
424
425
426 Handle<Code> KeyedLoadFastElementStub::GenerateCode() {
427   return DoGenerateCode(this);
428 }
429
430
431 template<>
432 HValue* CodeStubGraphBuilder<LoadFieldStub>::BuildCodeStub() {
433   Representation representation = casted_stub()->representation();
434   HInstruction* load = AddInstruction(DoBuildLoadNamedField(
435       GetParameter(0), casted_stub()->is_inobject(),
436       representation, casted_stub()->offset()));
437   return load;
438 }
439
440
441 Handle<Code> LoadFieldStub::GenerateCode() {
442   return DoGenerateCode(this);
443 }
444
445
446 template<>
447 HValue* CodeStubGraphBuilder<KeyedLoadFieldStub>::BuildCodeStub() {
448   Representation representation = casted_stub()->representation();
449   HInstruction* load = AddInstruction(DoBuildLoadNamedField(
450       GetParameter(0), casted_stub()->is_inobject(),
451       representation, casted_stub()->offset()));
452   return load;
453 }
454
455
456 Handle<Code> KeyedLoadFieldStub::GenerateCode() {
457   return DoGenerateCode(this);
458 }
459
460
461 template <>
462 HValue* CodeStubGraphBuilder<KeyedStoreFastElementStub>::BuildCodeStub() {
463   BuildUncheckedMonomorphicElementAccess(
464       GetParameter(0), GetParameter(1), GetParameter(2), NULL,
465       casted_stub()->is_js_array(), casted_stub()->elements_kind(),
466       true, NEVER_RETURN_HOLE, casted_stub()->store_mode(),
467       Representation::Tagged());
468
469   return GetParameter(2);
470 }
471
472
473 Handle<Code> KeyedStoreFastElementStub::GenerateCode() {
474   return DoGenerateCode(this);
475 }
476
477
478 template <>
479 HValue* CodeStubGraphBuilder<TransitionElementsKindStub>::BuildCodeStub() {
480   Zone* zone = this->zone();
481
482   HValue* js_array = GetParameter(0);
483   HValue* map = GetParameter(1);
484
485   info()->MarkAsSavesCallerDoubles();
486
487   AddInstruction(new(zone) HTrapAllocationMemento(js_array));
488
489   HInstruction* array_length =
490       AddInstruction(HLoadNamedField::NewArrayLength(
491             zone, js_array, js_array, HType::Smi()));
492
493   ElementsKind to_kind = casted_stub()->to_kind();
494   BuildNewSpaceArrayCheck(array_length, to_kind);
495
496   IfBuilder if_builder(this);
497
498   if_builder.IfCompare(array_length, graph()->GetConstant0(), Token::EQ);
499   if_builder.Then();
500
501   // Nothing to do, just change the map.
502
503   if_builder.Else();
504
505   HInstruction* elements = AddLoadElements(js_array);
506
507   HInstruction* elements_length =
508       AddInstruction(new(zone) HFixedArrayBaseLength(elements));
509
510   HValue* new_elements =
511       BuildAllocateAndInitializeElements(context(), to_kind, elements_length);
512
513   BuildCopyElements(context(), elements,
514                     casted_stub()->from_kind(), new_elements,
515                     to_kind, array_length, elements_length);
516
517   Factory* factory = isolate()->factory();
518
519   AddInstruction(new(zone) HStoreNamedField(js_array,
520                                             factory->elements_field_string(),
521                                             new_elements, true,
522                                             Representation::Tagged(),
523                                             JSArray::kElementsOffset));
524
525   if_builder.End();
526
527   AddInstruction(new(zone) HStoreNamedField(js_array, factory->length_string(),
528                                             map, true,
529                                             Representation::Tagged(),
530                                             JSArray::kMapOffset));
531   return js_array;
532 }
533
534
535 Handle<Code> TransitionElementsKindStub::GenerateCode() {
536   return DoGenerateCode(this);
537 }
538
539
540 template <>
541 HValue* CodeStubGraphBuilder<ArrayNoArgumentConstructorStub>::BuildCodeStub() {
542   // ----------- S t a t e -------------
543   //  -- Parameter 1 : type info cell
544   //  -- Parameter 0 : constructor
545   // -----------------------------------
546   HInstruction* array_function = BuildGetArrayFunction(context());
547   ArrayContextChecker(this,
548                       GetParameter(ArrayConstructorStubBase::kConstructor),
549                       array_function);
550   // Get the right map
551   // Should be a constant
552   JSArrayBuilder array_builder(
553       this,
554       casted_stub()->elements_kind(),
555       GetParameter(ArrayConstructorStubBase::kPropertyCell),
556       casted_stub()->mode());
557   return array_builder.AllocateEmptyArray();
558 }
559
560
561 Handle<Code> ArrayNoArgumentConstructorStub::GenerateCode() {
562   return DoGenerateCode(this);
563 }
564
565
566 template <>
567 HValue* CodeStubGraphBuilder<ArraySingleArgumentConstructorStub>::
568     BuildCodeStub() {
569   HInstruction* array_function = BuildGetArrayFunction(context());
570   ArrayContextChecker(this,
571                       GetParameter(ArrayConstructorStubBase::kConstructor),
572                       array_function);
573   // Smi check and range check on the input arg.
574   HValue* constant_one = graph()->GetConstant1();
575   HValue* constant_zero = graph()->GetConstant0();
576
577   HInstruction* elements = AddInstruction(
578       new(zone()) HArgumentsElements(false));
579   HInstruction* argument = AddInstruction(
580       new(zone()) HAccessArgumentsAt(elements, constant_one, constant_zero));
581
582   HConstant* max_alloc_length =
583       new(zone()) HConstant(JSObject::kInitialMaxFastElementArray,
584                             Representation::Tagged());
585   AddInstruction(max_alloc_length);
586   const int initial_capacity = JSArray::kPreallocatedArrayElements;
587   HConstant* initial_capacity_node =
588       new(zone()) HConstant(initial_capacity, Representation::Tagged());
589   AddInstruction(initial_capacity_node);
590
591   // Since we're forcing Integer32 representation for this HBoundsCheck,
592   // there's no need to Smi-check the index.
593   HBoundsCheck* checked_arg = AddBoundsCheck(argument, max_alloc_length,
594                                              ALLOW_SMI_KEY,
595                                              Representation::Tagged());
596   IfBuilder if_builder(this);
597   if_builder.IfCompare(checked_arg, constant_zero, Token::EQ);
598   if_builder.Then();
599   Push(initial_capacity_node);  // capacity
600   Push(constant_zero);  // length
601   if_builder.Else();
602   Push(checked_arg);  // capacity
603   Push(checked_arg);  // length
604   if_builder.End();
605
606   // Figure out total size
607   HValue* length = Pop();
608   HValue* capacity = Pop();
609
610   JSArrayBuilder array_builder(
611       this,
612       casted_stub()->elements_kind(),
613       GetParameter(ArrayConstructorStubBase::kPropertyCell),
614       casted_stub()->mode());
615   return array_builder.AllocateArray(capacity, length, true);
616 }
617
618
619 Handle<Code> ArraySingleArgumentConstructorStub::GenerateCode() {
620   return DoGenerateCode(this);
621 }
622
623
624 template <>
625 HValue* CodeStubGraphBuilder<ArrayNArgumentsConstructorStub>::BuildCodeStub() {
626   HInstruction* array_function = BuildGetArrayFunction(context());
627   ArrayContextChecker(this,
628                       GetParameter(ArrayConstructorStubBase::kConstructor),
629                       array_function);
630   ElementsKind kind = casted_stub()->elements_kind();
631   HValue* length = GetArgumentsLength();
632
633   JSArrayBuilder array_builder(
634       this,
635       kind,
636       GetParameter(ArrayConstructorStubBase::kPropertyCell),
637       casted_stub()->mode());
638
639   // We need to fill with the hole if it's a smi array in the multi-argument
640   // case because we might have to bail out while copying arguments into
641   // the array because they aren't compatible with a smi array.
642   // If it's a double array, no problem, and if it's fast then no
643   // problem either because doubles are boxed.
644   bool fill_with_hole = IsFastSmiElementsKind(kind);
645   HValue* new_object = array_builder.AllocateArray(length,
646                                                    length,
647                                                    fill_with_hole);
648   HValue* elements = array_builder.GetElementsLocation();
649   ASSERT(elements != NULL);
650
651   // Now populate the elements correctly.
652   LoopBuilder builder(this,
653                       context(),
654                       LoopBuilder::kPostIncrement);
655   HValue* start = graph()->GetConstant0();
656   HValue* key = builder.BeginBody(start, length, Token::LT);
657   HInstruction* argument_elements = AddInstruction(
658       new(zone()) HArgumentsElements(false));
659   HInstruction* argument = AddInstruction(new(zone()) HAccessArgumentsAt(
660       argument_elements, length, key));
661
662   // Checks to prevent incompatible stores
663   if (IsFastSmiElementsKind(kind)) {
664     AddInstruction(new(zone()) HCheckSmi(argument));
665   }
666
667   AddInstruction(new(zone()) HStoreKeyed(elements, key, argument, kind));
668   builder.EndBody();
669   return new_object;
670 }
671
672
673 Handle<Code> ArrayNArgumentsConstructorStub::GenerateCode() {
674   return DoGenerateCode(this);
675 }
676
677
678 template <>
679 HValue* CodeStubGraphBuilder<CompareNilICStub>::BuildCodeUninitializedStub() {
680   CompareNilICStub* stub = casted_stub();
681   HIfContinuation continuation;
682   Handle<Map> sentinel_map(graph()->isolate()->heap()->meta_map());
683   BuildCompareNil(GetParameter(0), stub->GetKind(),
684                   stub->GetTypes(), sentinel_map,
685                   RelocInfo::kNoPosition, &continuation);
686   IfBuilder if_nil(this, &continuation);
687   if_nil.Then();
688   if (continuation.IsFalseReachable()) {
689     if_nil.Else();
690     if_nil.Return(graph()->GetConstantSmi0());
691   }
692   if_nil.End();
693   return continuation.IsTrueReachable()
694       ? graph()->GetConstantSmi1()
695       : graph()->GetConstantUndefined();
696 }
697
698
699 Handle<Code> CompareNilICStub::GenerateCode() {
700   return DoGenerateCode(this);
701 }
702
703 } }  // namespace v8::internal