Home | History | Annotate | Download | only in src
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/code-stubs.h"
      6 
      7 #include "src/bailout-reason.h"
      8 #include "src/crankshaft/hydrogen.h"
      9 #include "src/crankshaft/lithium.h"
     10 #include "src/field-index.h"
     11 #include "src/ic/ic.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 
     16 
     17 static LChunk* OptimizeGraph(HGraph* graph) {
     18   DisallowHeapAllocation no_allocation;
     19   DisallowHandleAllocation no_handles;
     20   DisallowHandleDereference no_deref;
     21 
     22   DCHECK(graph != NULL);
     23   BailoutReason bailout_reason = kNoReason;
     24   if (!graph->Optimize(&bailout_reason)) {
     25     FATAL(GetBailoutReason(bailout_reason));
     26   }
     27   LChunk* chunk = LChunk::NewChunk(graph);
     28   if (chunk == NULL) {
     29     FATAL(GetBailoutReason(graph->info()->bailout_reason()));
     30   }
     31   return chunk;
     32 }
     33 
     34 
     35 class CodeStubGraphBuilderBase : public HGraphBuilder {
     36  public:
     37   explicit CodeStubGraphBuilderBase(CompilationInfo* info)
     38       : HGraphBuilder(info),
     39         arguments_length_(NULL),
     40         info_(info),
     41         descriptor_(info->code_stub()),
     42         context_(NULL) {
     43     int parameter_count = GetParameterCount();
     44     parameters_.Reset(new HParameter*[parameter_count]);
     45   }
     46   virtual bool BuildGraph();
     47 
     48  protected:
     49   virtual HValue* BuildCodeStub() = 0;
     50   int GetParameterCount() const { return descriptor_.GetParameterCount(); }
     51   int GetRegisterParameterCount() const {
     52     return descriptor_.GetRegisterParameterCount();
     53   }
     54   HParameter* GetParameter(int parameter) {
     55     DCHECK(parameter < GetParameterCount());
     56     return parameters_[parameter];
     57   }
     58   Representation GetParameterRepresentation(int parameter) {
     59     return RepresentationFromType(descriptor_.GetParameterType(parameter));
     60   }
     61   bool IsParameterCountRegister(int index) const {
     62     return descriptor_.GetRegisterParameter(index)
     63         .is(descriptor_.stack_parameter_count());
     64   }
     65   HValue* GetArgumentsLength() {
     66     // This is initialized in BuildGraph()
     67     DCHECK(arguments_length_ != NULL);
     68     return arguments_length_;
     69   }
     70   CompilationInfo* info() { return info_; }
     71   CodeStub* stub() { return info_->code_stub(); }
     72   HContext* context() { return context_; }
     73   Isolate* isolate() { return info_->isolate(); }
     74 
     75   HLoadNamedField* BuildLoadNamedField(HValue* object, FieldIndex index);
     76   void BuildStoreNamedField(HValue* object, HValue* value, FieldIndex index,
     77                             Representation representation,
     78                             bool transition_to_field);
     79 
     80   enum ArgumentClass {
     81     NONE,
     82     SINGLE,
     83     MULTIPLE
     84   };
     85 
     86   HValue* UnmappedCase(HValue* elements, HValue* key, HValue* value);
     87   HValue* EmitKeyedSloppyArguments(HValue* receiver, HValue* key,
     88                                    HValue* value);
     89 
     90   HValue* BuildArrayConstructor(ElementsKind kind,
     91                                 AllocationSiteOverrideMode override_mode,
     92                                 ArgumentClass argument_class);
     93   HValue* BuildInternalArrayConstructor(ElementsKind kind,
     94                                         ArgumentClass argument_class);
     95 
     96   // BuildCheckAndInstallOptimizedCode emits code to install the optimized
     97   // function found in the optimized code map at map_index in js_function, if
     98   // the function at map_index matches the given native_context. Builder is
     99   // left in the "Then()" state after the install.
    100   void BuildCheckAndInstallOptimizedCode(HValue* js_function,
    101                                          HValue* native_context,
    102                                          IfBuilder* builder,
    103                                          HValue* optimized_map,
    104                                          HValue* map_index);
    105   void BuildInstallOptimizedCode(HValue* js_function, HValue* native_context,
    106                                  HValue* code_object, HValue* literals);
    107   void BuildInstallCode(HValue* js_function, HValue* shared_info);
    108 
    109   HInstruction* LoadFromOptimizedCodeMap(HValue* optimized_map,
    110                                          HValue* iterator,
    111                                          int field_offset);
    112   void BuildInstallFromOptimizedCodeMap(HValue* js_function,
    113                                         HValue* shared_info,
    114                                         HValue* native_context);
    115 
    116   HValue* BuildToString(HValue* input, bool convert);
    117   HValue* BuildToPrimitive(HValue* input, HValue* input_map);
    118 
    119  private:
    120   HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder);
    121   HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder,
    122                                           ElementsKind kind);
    123 
    124   base::SmartArrayPointer<HParameter*> parameters_;
    125   HValue* arguments_length_;
    126   CompilationInfo* info_;
    127   CodeStubDescriptor descriptor_;
    128   HContext* context_;
    129 };
    130 
    131 
    132 bool CodeStubGraphBuilderBase::BuildGraph() {
    133   // Update the static counter each time a new code stub is generated.
    134   isolate()->counters()->code_stubs()->Increment();
    135 
    136   if (FLAG_trace_hydrogen_stubs) {
    137     const char* name = CodeStub::MajorName(stub()->MajorKey());
    138     PrintF("-----------------------------------------------------------\n");
    139     PrintF("Compiling stub %s using hydrogen\n", name);
    140     isolate()->GetHTracer()->TraceCompilation(info());
    141   }
    142 
    143   int param_count = GetParameterCount();
    144   int register_param_count = GetRegisterParameterCount();
    145   HEnvironment* start_environment = graph()->start_environment();
    146   HBasicBlock* next_block = CreateBasicBlock(start_environment);
    147   Goto(next_block);
    148   next_block->SetJoinId(BailoutId::StubEntry());
    149   set_current_block(next_block);
    150 
    151   bool runtime_stack_params = descriptor_.stack_parameter_count().is_valid();
    152   HInstruction* stack_parameter_count = NULL;
    153   for (int i = 0; i < param_count; ++i) {
    154     Representation r = GetParameterRepresentation(i);
    155     HParameter* param;
    156     if (i >= register_param_count) {
    157       param = Add<HParameter>(i - register_param_count,
    158                               HParameter::STACK_PARAMETER, r);
    159     } else {
    160       param = Add<HParameter>(i, HParameter::REGISTER_PARAMETER, r);
    161       start_environment->Bind(i, param);
    162     }
    163     parameters_[i] = param;
    164     if (i < register_param_count && IsParameterCountRegister(i)) {
    165       param->set_type(HType::Smi());
    166       stack_parameter_count = param;
    167       arguments_length_ = stack_parameter_count;
    168     }
    169   }
    170 
    171   DCHECK(!runtime_stack_params || arguments_length_ != NULL);
    172   if (!runtime_stack_params) {
    173     stack_parameter_count =
    174         Add<HConstant>(param_count - register_param_count - 1);
    175     // graph()->GetConstantMinus1();
    176     arguments_length_ = graph()->GetConstant0();
    177   }
    178 
    179   context_ = Add<HContext>();
    180   start_environment->BindContext(context_);
    181 
    182   Add<HSimulate>(BailoutId::StubEntry());
    183 
    184   NoObservableSideEffectsScope no_effects(this);
    185 
    186   HValue* return_value = BuildCodeStub();
    187 
    188   // We might have extra expressions to pop from the stack in addition to the
    189   // arguments above.
    190   HInstruction* stack_pop_count = stack_parameter_count;
    191   if (descriptor_.function_mode() == JS_FUNCTION_STUB_MODE) {
    192     if (!stack_parameter_count->IsConstant() &&
    193         descriptor_.hint_stack_parameter_count() < 0) {
    194       HInstruction* constant_one = graph()->GetConstant1();
    195       stack_pop_count = AddUncasted<HAdd>(stack_parameter_count, constant_one);
    196       stack_pop_count->ClearFlag(HValue::kCanOverflow);
    197       // TODO(mvstanton): verify that stack_parameter_count+1 really fits in a
    198       // smi.
    199     } else {
    200       int count = descriptor_.hint_stack_parameter_count();
    201       stack_pop_count = Add<HConstant>(count);
    202     }
    203   }
    204 
    205   if (current_block() != NULL) {
    206     HReturn* hreturn_instruction = New<HReturn>(return_value,
    207                                                 stack_pop_count);
    208     FinishCurrentBlock(hreturn_instruction);
    209   }
    210   return true;
    211 }
    212 
    213 
    214 template <class Stub>
    215 class CodeStubGraphBuilder: public CodeStubGraphBuilderBase {
    216  public:
    217   explicit CodeStubGraphBuilder(CompilationInfo* info)
    218       : CodeStubGraphBuilderBase(info) {}
    219 
    220  protected:
    221   virtual HValue* BuildCodeStub() {
    222     if (casted_stub()->IsUninitialized()) {
    223       return BuildCodeUninitializedStub();
    224     } else {
    225       return BuildCodeInitializedStub();
    226     }
    227   }
    228 
    229   virtual HValue* BuildCodeInitializedStub() {
    230     UNIMPLEMENTED();
    231     return NULL;
    232   }
    233 
    234   virtual HValue* BuildCodeUninitializedStub() {
    235     // Force a deopt that falls back to the runtime.
    236     HValue* undefined = graph()->GetConstantUndefined();
    237     IfBuilder builder(this);
    238     builder.IfNot<HCompareObjectEqAndBranch, HValue*>(undefined, undefined);
    239     builder.Then();
    240     builder.ElseDeopt(Deoptimizer::kForcedDeoptToRuntime);
    241     return undefined;
    242   }
    243 
    244   Stub* casted_stub() { return static_cast<Stub*>(stub()); }
    245 };
    246 
    247 
    248 Handle<Code> HydrogenCodeStub::GenerateLightweightMissCode(
    249     ExternalReference miss) {
    250   Factory* factory = isolate()->factory();
    251 
    252   // Generate the new code.
    253   MacroAssembler masm(isolate(), NULL, 256, CodeObjectRequired::kYes);
    254 
    255   {
    256     // Update the static counter each time a new code stub is generated.
    257     isolate()->counters()->code_stubs()->Increment();
    258 
    259     // Generate the code for the stub.
    260     masm.set_generating_stub(true);
    261     // TODO(yangguo): remove this once we can serialize IC stubs.
    262     masm.enable_serializer();
    263     NoCurrentFrameScope scope(&masm);
    264     GenerateLightweightMiss(&masm, miss);
    265   }
    266 
    267   // Create the code object.
    268   CodeDesc desc;
    269   masm.GetCode(&desc);
    270 
    271   // Copy the generated code into a heap object.
    272   Code::Flags flags = Code::ComputeFlags(
    273       GetCodeKind(),
    274       GetICState(),
    275       GetExtraICState(),
    276       GetStubType());
    277   Handle<Code> new_object = factory->NewCode(
    278       desc, flags, masm.CodeObject(), NeedsImmovableCode());
    279   return new_object;
    280 }
    281 
    282 
    283 template <class Stub>
    284 static Handle<Code> DoGenerateCode(Stub* stub) {
    285   Isolate* isolate = stub->isolate();
    286   CodeStubDescriptor descriptor(stub);
    287 
    288   // If we are uninitialized we can use a light-weight stub to enter
    289   // the runtime that is significantly faster than using the standard
    290   // stub-failure deopt mechanism.
    291   if (stub->IsUninitialized() && descriptor.has_miss_handler()) {
    292     DCHECK(!descriptor.stack_parameter_count().is_valid());
    293     return stub->GenerateLightweightMissCode(descriptor.miss_handler());
    294   }
    295   base::ElapsedTimer timer;
    296   if (FLAG_profile_hydrogen_code_stub_compilation) {
    297     timer.Start();
    298   }
    299   Zone zone;
    300   CompilationInfo info(stub, isolate, &zone);
    301   CodeStubGraphBuilder<Stub> builder(&info);
    302   LChunk* chunk = OptimizeGraph(builder.CreateGraph());
    303   Handle<Code> code = chunk->Codegen();
    304   if (FLAG_profile_hydrogen_code_stub_compilation) {
    305     OFStream os(stdout);
    306     os << "[Lazy compilation of " << stub << " took "
    307        << timer.Elapsed().InMillisecondsF() << " ms]" << std::endl;
    308   }
    309   return code;
    310 }
    311 
    312 
    313 template <>
    314 HValue* CodeStubGraphBuilder<NumberToStringStub>::BuildCodeStub() {
    315   info()->MarkAsSavesCallerDoubles();
    316   HValue* number = GetParameter(NumberToStringStub::kNumber);
    317   return BuildNumberToString(number, Type::Number(zone()));
    318 }
    319 
    320 
    321 Handle<Code> NumberToStringStub::GenerateCode() {
    322   return DoGenerateCode(this);
    323 }
    324 
    325 
    326 // Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
    327 template <>
    328 HValue* CodeStubGraphBuilder<TypeofStub>::BuildCodeStub() {
    329   Factory* factory = isolate()->factory();
    330   HConstant* number_string = Add<HConstant>(factory->number_string());
    331   HValue* object = GetParameter(TypeofStub::kObject);
    332 
    333   IfBuilder is_smi(this);
    334   HValue* smi_check = is_smi.If<HIsSmiAndBranch>(object);
    335   is_smi.Then();
    336   { Push(number_string); }
    337   is_smi.Else();
    338   {
    339     IfBuilder is_number(this);
    340     is_number.If<HCompareMap>(object, isolate()->factory()->heap_number_map());
    341     is_number.Then();
    342     { Push(number_string); }
    343     is_number.Else();
    344     {
    345       HValue* map = AddLoadMap(object, smi_check);
    346       HValue* instance_type = Add<HLoadNamedField>(
    347           map, nullptr, HObjectAccess::ForMapInstanceType());
    348       IfBuilder is_string(this);
    349       is_string.If<HCompareNumericAndBranch>(
    350           instance_type, Add<HConstant>(FIRST_NONSTRING_TYPE), Token::LT);
    351       is_string.Then();
    352       { Push(Add<HConstant>(factory->string_string())); }
    353       is_string.Else();
    354       {
    355         HConstant* object_string = Add<HConstant>(factory->object_string());
    356         IfBuilder is_oddball(this);
    357         is_oddball.If<HCompareNumericAndBranch>(
    358             instance_type, Add<HConstant>(ODDBALL_TYPE), Token::EQ);
    359         is_oddball.Then();
    360         {
    361           Push(Add<HLoadNamedField>(object, nullptr,
    362                                     HObjectAccess::ForOddballTypeOf()));
    363         }
    364         is_oddball.Else();
    365         {
    366           IfBuilder is_symbol(this);
    367           is_symbol.If<HCompareNumericAndBranch>(
    368               instance_type, Add<HConstant>(SYMBOL_TYPE), Token::EQ);
    369           is_symbol.Then();
    370           { Push(Add<HConstant>(factory->symbol_string())); }
    371           is_symbol.Else();
    372           {
    373             HValue* bit_field = Add<HLoadNamedField>(
    374                 map, nullptr, HObjectAccess::ForMapBitField());
    375             HValue* bit_field_masked = AddUncasted<HBitwise>(
    376                 Token::BIT_AND, bit_field,
    377                 Add<HConstant>((1 << Map::kIsCallable) |
    378                                (1 << Map::kIsUndetectable)));
    379             IfBuilder is_function(this);
    380             is_function.If<HCompareNumericAndBranch>(
    381                 bit_field_masked, Add<HConstant>(1 << Map::kIsCallable),
    382                 Token::EQ);
    383             is_function.Then();
    384             { Push(Add<HConstant>(factory->function_string())); }
    385             is_function.Else();
    386             {
    387 #define SIMD128_BUILDER_OPEN(TYPE, Type, type, lane_count, lane_type) \
    388   IfBuilder is_##type(this);                                          \
    389   is_##type.If<HCompareObjectEqAndBranch>(                            \
    390       map, Add<HConstant>(factory->type##_map()));                    \
    391   is_##type.Then();                                                   \
    392   { Push(Add<HConstant>(factory->type##_string())); }                 \
    393   is_##type.Else(); {
    394               SIMD128_TYPES(SIMD128_BUILDER_OPEN)
    395 #undef SIMD128_BUILDER_OPEN
    396               // Is it an undetectable object?
    397               IfBuilder is_undetectable(this);
    398               is_undetectable.If<HCompareNumericAndBranch>(
    399                   bit_field_masked, graph()->GetConstant0(), Token::NE);
    400               is_undetectable.Then();
    401               {
    402                 // typeof an undetectable object is 'undefined'.
    403                 Push(Add<HConstant>(factory->undefined_string()));
    404               }
    405               is_undetectable.Else();
    406               {
    407                 // For any kind of object not handled above, the spec rule for
    408                 // host objects gives that it is okay to return "object".
    409                 Push(object_string);
    410               }
    411 #define SIMD128_BUILDER_CLOSE(TYPE, Type, type, lane_count, lane_type) }
    412               SIMD128_TYPES(SIMD128_BUILDER_CLOSE)
    413 #undef SIMD128_BUILDER_CLOSE
    414             }
    415             is_function.End();
    416           }
    417           is_symbol.End();
    418         }
    419         is_oddball.End();
    420       }
    421       is_string.End();
    422     }
    423     is_number.End();
    424   }
    425   is_smi.End();
    426 
    427   return environment()->Pop();
    428 }
    429 
    430 
    431 Handle<Code> TypeofStub::GenerateCode() { return DoGenerateCode(this); }
    432 
    433 
    434 template <>
    435 HValue* CodeStubGraphBuilder<FastCloneRegExpStub>::BuildCodeStub() {
    436   HValue* closure = GetParameter(0);
    437   HValue* literal_index = GetParameter(1);
    438 
    439   // This stub is very performance sensitive, the generated code must be tuned
    440   // so that it doesn't build and eager frame.
    441   info()->MarkMustNotHaveEagerFrame();
    442 
    443   HValue* literals_array = Add<HLoadNamedField>(
    444       closure, nullptr, HObjectAccess::ForLiteralsPointer());
    445   HInstruction* boilerplate = Add<HLoadKeyed>(
    446       literals_array, literal_index, nullptr, nullptr, FAST_ELEMENTS,
    447       NEVER_RETURN_HOLE, LiteralsArray::kOffsetToFirstLiteral - kHeapObjectTag);
    448 
    449   IfBuilder if_notundefined(this);
    450   if_notundefined.IfNot<HCompareObjectEqAndBranch>(
    451       boilerplate, graph()->GetConstantUndefined());
    452   if_notundefined.Then();
    453   {
    454     int result_size =
    455         JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
    456     HValue* result =
    457         Add<HAllocate>(Add<HConstant>(result_size), HType::JSObject(),
    458                        NOT_TENURED, JS_REGEXP_TYPE);
    459     Add<HStoreNamedField>(
    460         result, HObjectAccess::ForMap(),
    461         Add<HLoadNamedField>(boilerplate, nullptr, HObjectAccess::ForMap()));
    462     Add<HStoreNamedField>(
    463         result, HObjectAccess::ForPropertiesPointer(),
    464         Add<HLoadNamedField>(boilerplate, nullptr,
    465                              HObjectAccess::ForPropertiesPointer()));
    466     Add<HStoreNamedField>(
    467         result, HObjectAccess::ForElementsPointer(),
    468         Add<HLoadNamedField>(boilerplate, nullptr,
    469                              HObjectAccess::ForElementsPointer()));
    470     for (int offset = JSObject::kHeaderSize; offset < result_size;
    471          offset += kPointerSize) {
    472       HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(offset);
    473       Add<HStoreNamedField>(result, access,
    474                             Add<HLoadNamedField>(boilerplate, nullptr, access));
    475     }
    476     Push(result);
    477   }
    478   if_notundefined.ElseDeopt(Deoptimizer::kUninitializedBoilerplateInFastClone);
    479   if_notundefined.End();
    480 
    481   return Pop();
    482 }
    483 
    484 
    485 Handle<Code> FastCloneRegExpStub::GenerateCode() {
    486   return DoGenerateCode(this);
    487 }
    488 
    489 
    490 template <>
    491 HValue* CodeStubGraphBuilder<FastCloneShallowArrayStub>::BuildCodeStub() {
    492   Factory* factory = isolate()->factory();
    493   HValue* undefined = graph()->GetConstantUndefined();
    494   AllocationSiteMode alloc_site_mode = casted_stub()->allocation_site_mode();
    495   HValue* closure = GetParameter(0);
    496   HValue* literal_index = GetParameter(1);
    497 
    498   // This stub is very performance sensitive, the generated code must be tuned
    499   // so that it doesn't build and eager frame.
    500   info()->MarkMustNotHaveEagerFrame();
    501 
    502   HValue* literals_array = Add<HLoadNamedField>(
    503       closure, nullptr, HObjectAccess::ForLiteralsPointer());
    504 
    505   HInstruction* allocation_site = Add<HLoadKeyed>(
    506       literals_array, literal_index, nullptr, nullptr, FAST_ELEMENTS,
    507       NEVER_RETURN_HOLE, LiteralsArray::kOffsetToFirstLiteral - kHeapObjectTag);
    508   IfBuilder checker(this);
    509   checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site,
    510                                                     undefined);
    511   checker.Then();
    512 
    513   HObjectAccess access = HObjectAccess::ForAllocationSiteOffset(
    514       AllocationSite::kTransitionInfoOffset);
    515   HInstruction* boilerplate =
    516       Add<HLoadNamedField>(allocation_site, nullptr, access);
    517   HValue* elements = AddLoadElements(boilerplate);
    518   HValue* capacity = AddLoadFixedArrayLength(elements);
    519   IfBuilder zero_capacity(this);
    520   zero_capacity.If<HCompareNumericAndBranch>(capacity, graph()->GetConstant0(),
    521                                            Token::EQ);
    522   zero_capacity.Then();
    523   Push(BuildCloneShallowArrayEmpty(boilerplate,
    524                                    allocation_site,
    525                                    alloc_site_mode));
    526   zero_capacity.Else();
    527   IfBuilder if_fixed_cow(this);
    528   if_fixed_cow.If<HCompareMap>(elements, factory->fixed_cow_array_map());
    529   if_fixed_cow.Then();
    530   Push(BuildCloneShallowArrayCow(boilerplate,
    531                                  allocation_site,
    532                                  alloc_site_mode,
    533                                  FAST_ELEMENTS));
    534   if_fixed_cow.Else();
    535   IfBuilder if_fixed(this);
    536   if_fixed.If<HCompareMap>(elements, factory->fixed_array_map());
    537   if_fixed.Then();
    538   Push(BuildCloneShallowArrayNonEmpty(boilerplate,
    539                                       allocation_site,
    540                                       alloc_site_mode,
    541                                       FAST_ELEMENTS));
    542 
    543   if_fixed.Else();
    544   Push(BuildCloneShallowArrayNonEmpty(boilerplate,
    545                                       allocation_site,
    546                                       alloc_site_mode,
    547                                       FAST_DOUBLE_ELEMENTS));
    548   if_fixed.End();
    549   if_fixed_cow.End();
    550   zero_capacity.End();
    551 
    552   checker.ElseDeopt(Deoptimizer::kUninitializedBoilerplateLiterals);
    553   checker.End();
    554 
    555   return environment()->Pop();
    556 }
    557 
    558 
    559 Handle<Code> FastCloneShallowArrayStub::GenerateCode() {
    560   return DoGenerateCode(this);
    561 }
    562 
    563 
    564 template <>
    565 HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() {
    566   HValue* undefined = graph()->GetConstantUndefined();
    567   HValue* closure = GetParameter(0);
    568   HValue* literal_index = GetParameter(1);
    569 
    570   HValue* literals_array = Add<HLoadNamedField>(
    571       closure, nullptr, HObjectAccess::ForLiteralsPointer());
    572 
    573   HInstruction* allocation_site = Add<HLoadKeyed>(
    574       literals_array, literal_index, nullptr, nullptr, FAST_ELEMENTS,
    575       NEVER_RETURN_HOLE, LiteralsArray::kOffsetToFirstLiteral - kHeapObjectTag);
    576 
    577   IfBuilder checker(this);
    578   checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site,
    579                                                     undefined);
    580   checker.And();
    581 
    582   HObjectAccess access = HObjectAccess::ForAllocationSiteOffset(
    583       AllocationSite::kTransitionInfoOffset);
    584   HInstruction* boilerplate =
    585       Add<HLoadNamedField>(allocation_site, nullptr, access);
    586 
    587   int length = casted_stub()->length();
    588   if (length == 0) {
    589     // Empty objects have some slack added to them.
    590     length = JSObject::kInitialGlobalObjectUnusedPropertiesCount;
    591   }
    592   int size = JSObject::kHeaderSize + length * kPointerSize;
    593   int object_size = size;
    594   if (FLAG_allocation_site_pretenuring) {
    595     size += AllocationMemento::kSize;
    596   }
    597 
    598   HValue* boilerplate_map =
    599       Add<HLoadNamedField>(boilerplate, nullptr, HObjectAccess::ForMap());
    600   HValue* boilerplate_size = Add<HLoadNamedField>(
    601       boilerplate_map, nullptr, HObjectAccess::ForMapInstanceSize());
    602   HValue* size_in_words = Add<HConstant>(object_size >> kPointerSizeLog2);
    603   checker.If<HCompareNumericAndBranch>(boilerplate_size,
    604                                        size_in_words, Token::EQ);
    605   checker.Then();
    606 
    607   HValue* size_in_bytes = Add<HConstant>(size);
    608 
    609   HInstruction* object = Add<HAllocate>(size_in_bytes, HType::JSObject(),
    610       NOT_TENURED, JS_OBJECT_TYPE);
    611 
    612   for (int i = 0; i < object_size; i += kPointerSize) {
    613     HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(i);
    614     Add<HStoreNamedField>(object, access,
    615                           Add<HLoadNamedField>(boilerplate, nullptr, access));
    616   }
    617 
    618   DCHECK(FLAG_allocation_site_pretenuring || (size == object_size));
    619   if (FLAG_allocation_site_pretenuring) {
    620     BuildCreateAllocationMemento(
    621         object, Add<HConstant>(object_size), allocation_site);
    622   }
    623 
    624   environment()->Push(object);
    625   checker.ElseDeopt(Deoptimizer::kUninitializedBoilerplateInFastClone);
    626   checker.End();
    627 
    628   return environment()->Pop();
    629 }
    630 
    631 
    632 Handle<Code> FastCloneShallowObjectStub::GenerateCode() {
    633   return DoGenerateCode(this);
    634 }
    635 
    636 
    637 template <>
    638 HValue* CodeStubGraphBuilder<CreateAllocationSiteStub>::BuildCodeStub() {
    639   // This stub is performance sensitive, the generated code must be tuned
    640   // so that it doesn't build an eager frame.
    641   info()->MarkMustNotHaveEagerFrame();
    642 
    643   HValue* size = Add<HConstant>(AllocationSite::kSize);
    644   HInstruction* object = Add<HAllocate>(size, HType::JSObject(), TENURED,
    645       JS_OBJECT_TYPE);
    646 
    647   // Store the map
    648   Handle<Map> allocation_site_map = isolate()->factory()->allocation_site_map();
    649   AddStoreMapConstant(object, allocation_site_map);
    650 
    651   // Store the payload (smi elements kind)
    652   HValue* initial_elements_kind = Add<HConstant>(GetInitialFastElementsKind());
    653   Add<HStoreNamedField>(object,
    654                         HObjectAccess::ForAllocationSiteOffset(
    655                             AllocationSite::kTransitionInfoOffset),
    656                         initial_elements_kind);
    657 
    658   // Unlike literals, constructed arrays don't have nested sites
    659   Add<HStoreNamedField>(object,
    660                         HObjectAccess::ForAllocationSiteOffset(
    661                             AllocationSite::kNestedSiteOffset),
    662                         graph()->GetConstant0());
    663 
    664   // Pretenuring calculation field.
    665   Add<HStoreNamedField>(object,
    666                         HObjectAccess::ForAllocationSiteOffset(
    667                             AllocationSite::kPretenureDataOffset),
    668                         graph()->GetConstant0());
    669 
    670   // Pretenuring memento creation count field.
    671   Add<HStoreNamedField>(object,
    672                         HObjectAccess::ForAllocationSiteOffset(
    673                             AllocationSite::kPretenureCreateCountOffset),
    674                         graph()->GetConstant0());
    675 
    676   // Store an empty fixed array for the code dependency.
    677   HConstant* empty_fixed_array =
    678     Add<HConstant>(isolate()->factory()->empty_fixed_array());
    679   Add<HStoreNamedField>(
    680       object,
    681       HObjectAccess::ForAllocationSiteOffset(
    682           AllocationSite::kDependentCodeOffset),
    683       empty_fixed_array);
    684 
    685   // Link the object to the allocation site list
    686   HValue* site_list = Add<HConstant>(
    687       ExternalReference::allocation_sites_list_address(isolate()));
    688   HValue* site = Add<HLoadNamedField>(site_list, nullptr,
    689                                       HObjectAccess::ForAllocationSiteList());
    690   // TODO(mvstanton): This is a store to a weak pointer, which we may want to
    691   // mark as such in order to skip the write barrier, once we have a unified
    692   // system for weakness. For now we decided to keep it like this because having
    693   // an initial write barrier backed store makes this pointer strong until the
    694   // next GC, and allocation sites are designed to survive several GCs anyway.
    695   Add<HStoreNamedField>(
    696       object,
    697       HObjectAccess::ForAllocationSiteOffset(AllocationSite::kWeakNextOffset),
    698       site);
    699   Add<HStoreNamedField>(site_list, HObjectAccess::ForAllocationSiteList(),
    700                         object);
    701 
    702   HInstruction* feedback_vector = GetParameter(0);
    703   HInstruction* slot = GetParameter(1);
    704   Add<HStoreKeyed>(feedback_vector, slot, object, nullptr, FAST_ELEMENTS,
    705                    INITIALIZING_STORE);
    706   return feedback_vector;
    707 }
    708 
    709 
    710 Handle<Code> CreateAllocationSiteStub::GenerateCode() {
    711   return DoGenerateCode(this);
    712 }
    713 
    714 
    715 template <>
    716 HValue* CodeStubGraphBuilder<CreateWeakCellStub>::BuildCodeStub() {
    717   // This stub is performance sensitive, the generated code must be tuned
    718   // so that it doesn't build an eager frame.
    719   info()->MarkMustNotHaveEagerFrame();
    720 
    721   HValue* size = Add<HConstant>(WeakCell::kSize);
    722   HInstruction* object =
    723       Add<HAllocate>(size, HType::JSObject(), TENURED, JS_OBJECT_TYPE);
    724 
    725   Handle<Map> weak_cell_map = isolate()->factory()->weak_cell_map();
    726   AddStoreMapConstant(object, weak_cell_map);
    727 
    728   HInstruction* value = GetParameter(CreateWeakCellDescriptor::kValueIndex);
    729   Add<HStoreNamedField>(object, HObjectAccess::ForWeakCellValue(), value);
    730   Add<HStoreNamedField>(object, HObjectAccess::ForWeakCellNext(),
    731                         graph()->GetConstantHole());
    732 
    733   HInstruction* feedback_vector =
    734       GetParameter(CreateWeakCellDescriptor::kVectorIndex);
    735   HInstruction* slot = GetParameter(CreateWeakCellDescriptor::kSlotIndex);
    736   Add<HStoreKeyed>(feedback_vector, slot, object, nullptr, FAST_ELEMENTS,
    737                    INITIALIZING_STORE);
    738   return graph()->GetConstant0();
    739 }
    740 
    741 
    742 Handle<Code> CreateWeakCellStub::GenerateCode() { return DoGenerateCode(this); }
    743 
    744 
    745 template <>
    746 HValue* CodeStubGraphBuilder<LoadScriptContextFieldStub>::BuildCodeStub() {
    747   int context_index = casted_stub()->context_index();
    748   int slot_index = casted_stub()->slot_index();
    749 
    750   HValue* script_context = BuildGetScriptContext(context_index);
    751   return Add<HLoadNamedField>(script_context, nullptr,
    752                               HObjectAccess::ForContextSlot(slot_index));
    753 }
    754 
    755 
    756 Handle<Code> LoadScriptContextFieldStub::GenerateCode() {
    757   return DoGenerateCode(this);
    758 }
    759 
    760 
    761 template <>
    762 HValue* CodeStubGraphBuilder<StoreScriptContextFieldStub>::BuildCodeStub() {
    763   int context_index = casted_stub()->context_index();
    764   int slot_index = casted_stub()->slot_index();
    765 
    766   HValue* script_context = BuildGetScriptContext(context_index);
    767   Add<HStoreNamedField>(script_context,
    768                         HObjectAccess::ForContextSlot(slot_index),
    769                         GetParameter(2), STORE_TO_INITIALIZED_ENTRY);
    770   return GetParameter(2);
    771 }
    772 
    773 
    774 Handle<Code> StoreScriptContextFieldStub::GenerateCode() {
    775   return DoGenerateCode(this);
    776 }
    777 
    778 
    779 template <>
    780 HValue* CodeStubGraphBuilder<GrowArrayElementsStub>::BuildCodeStub() {
    781   ElementsKind kind = casted_stub()->elements_kind();
    782   if (IsFastDoubleElementsKind(kind)) {
    783     info()->MarkAsSavesCallerDoubles();
    784   }
    785 
    786   HValue* object = GetParameter(GrowArrayElementsDescriptor::kObjectIndex);
    787   HValue* key = GetParameter(GrowArrayElementsDescriptor::kKeyIndex);
    788 
    789   HValue* elements = AddLoadElements(object);
    790   HValue* current_capacity = Add<HLoadNamedField>(
    791       elements, nullptr, HObjectAccess::ForFixedArrayLength());
    792 
    793   HValue* length =
    794       casted_stub()->is_js_array()
    795           ? Add<HLoadNamedField>(object, static_cast<HValue*>(NULL),
    796                                  HObjectAccess::ForArrayLength(kind))
    797           : current_capacity;
    798 
    799   return BuildCheckAndGrowElementsCapacity(object, elements, kind, length,
    800                                            current_capacity, key);
    801 }
    802 
    803 
    804 Handle<Code> GrowArrayElementsStub::GenerateCode() {
    805   return DoGenerateCode(this);
    806 }
    807 
    808 
    809 template <>
    810 HValue* CodeStubGraphBuilder<LoadFastElementStub>::BuildCodeStub() {
    811   LoadKeyedHoleMode hole_mode = casted_stub()->convert_hole_to_undefined()
    812                                     ? CONVERT_HOLE_TO_UNDEFINED
    813                                     : NEVER_RETURN_HOLE;
    814 
    815   HInstruction* load = BuildUncheckedMonomorphicElementAccess(
    816       GetParameter(LoadDescriptor::kReceiverIndex),
    817       GetParameter(LoadDescriptor::kNameIndex), NULL,
    818       casted_stub()->is_js_array(), casted_stub()->elements_kind(), LOAD,
    819       hole_mode, STANDARD_STORE);
    820   return load;
    821 }
    822 
    823 
    824 Handle<Code> LoadFastElementStub::GenerateCode() {
    825   return DoGenerateCode(this);
    826 }
    827 
    828 
    829 HLoadNamedField* CodeStubGraphBuilderBase::BuildLoadNamedField(
    830     HValue* object, FieldIndex index) {
    831   Representation representation = index.is_double()
    832       ? Representation::Double()
    833       : Representation::Tagged();
    834   int offset = index.offset();
    835   HObjectAccess access = index.is_inobject()
    836       ? HObjectAccess::ForObservableJSObjectOffset(offset, representation)
    837       : HObjectAccess::ForBackingStoreOffset(offset, representation);
    838   if (index.is_double() &&
    839       (!FLAG_unbox_double_fields || !index.is_inobject())) {
    840     // Load the heap number.
    841     object = Add<HLoadNamedField>(
    842         object, nullptr, access.WithRepresentation(Representation::Tagged()));
    843     // Load the double value from it.
    844     access = HObjectAccess::ForHeapNumberValue();
    845   }
    846   return Add<HLoadNamedField>(object, nullptr, access);
    847 }
    848 
    849 
    850 template<>
    851 HValue* CodeStubGraphBuilder<LoadFieldStub>::BuildCodeStub() {
    852   return BuildLoadNamedField(GetParameter(0), casted_stub()->index());
    853 }
    854 
    855 
    856 Handle<Code> LoadFieldStub::GenerateCode() {
    857   return DoGenerateCode(this);
    858 }
    859 
    860 
    861 template <>
    862 HValue* CodeStubGraphBuilder<ArrayBufferViewLoadFieldStub>::BuildCodeStub() {
    863   return BuildArrayBufferViewFieldAccessor(GetParameter(0), nullptr,
    864                                            casted_stub()->index());
    865 }
    866 
    867 
    868 Handle<Code> ArrayBufferViewLoadFieldStub::GenerateCode() {
    869   return DoGenerateCode(this);
    870 }
    871 
    872 
    873 template <>
    874 HValue* CodeStubGraphBuilder<LoadConstantStub>::BuildCodeStub() {
    875   HValue* map = AddLoadMap(GetParameter(0), NULL);
    876   HObjectAccess descriptors_access = HObjectAccess::ForObservableJSObjectOffset(
    877       Map::kDescriptorsOffset, Representation::Tagged());
    878   HValue* descriptors = Add<HLoadNamedField>(map, nullptr, descriptors_access);
    879   HObjectAccess value_access = HObjectAccess::ForObservableJSObjectOffset(
    880       DescriptorArray::GetValueOffset(casted_stub()->constant_index()));
    881   return Add<HLoadNamedField>(descriptors, nullptr, value_access);
    882 }
    883 
    884 
    885 Handle<Code> LoadConstantStub::GenerateCode() { return DoGenerateCode(this); }
    886 
    887 
    888 HValue* CodeStubGraphBuilderBase::UnmappedCase(HValue* elements, HValue* key,
    889                                                HValue* value) {
    890   HValue* result = NULL;
    891   HInstruction* backing_store =
    892       Add<HLoadKeyed>(elements, graph()->GetConstant1(), nullptr, nullptr,
    893                       FAST_ELEMENTS, ALLOW_RETURN_HOLE);
    894   Add<HCheckMaps>(backing_store, isolate()->factory()->fixed_array_map());
    895   HValue* backing_store_length = Add<HLoadNamedField>(
    896       backing_store, nullptr, HObjectAccess::ForFixedArrayLength());
    897   IfBuilder in_unmapped_range(this);
    898   in_unmapped_range.If<HCompareNumericAndBranch>(key, backing_store_length,
    899                                                  Token::LT);
    900   in_unmapped_range.Then();
    901   {
    902     if (value == NULL) {
    903       result = Add<HLoadKeyed>(backing_store, key, nullptr, nullptr,
    904                                FAST_HOLEY_ELEMENTS, NEVER_RETURN_HOLE);
    905     } else {
    906       Add<HStoreKeyed>(backing_store, key, value, nullptr, FAST_HOLEY_ELEMENTS);
    907     }
    908   }
    909   in_unmapped_range.ElseDeopt(Deoptimizer::kOutsideOfRange);
    910   in_unmapped_range.End();
    911   return result;
    912 }
    913 
    914 
    915 HValue* CodeStubGraphBuilderBase::EmitKeyedSloppyArguments(HValue* receiver,
    916                                                            HValue* key,
    917                                                            HValue* value) {
    918   // Mapped arguments are actual arguments. Unmapped arguments are values added
    919   // to the arguments object after it was created for the call. Mapped arguments
    920   // are stored in the context at indexes given by elements[key + 2]. Unmapped
    921   // arguments are stored as regular indexed properties in the arguments array,
    922   // held at elements[1]. See NewSloppyArguments() in runtime.cc for a detailed
    923   // look at argument object construction.
    924   //
    925   // The sloppy arguments elements array has a special format:
    926   //
    927   // 0: context
    928   // 1: unmapped arguments array
    929   // 2: mapped_index0,
    930   // 3: mapped_index1,
    931   // ...
    932   //
    933   // length is 2 + min(number_of_actual_arguments, number_of_formal_arguments).
    934   // If key + 2 >= elements.length then attempt to look in the unmapped
    935   // arguments array (given by elements[1]) and return the value at key, missing
    936   // to the runtime if the unmapped arguments array is not a fixed array or if
    937   // key >= unmapped_arguments_array.length.
    938   //
    939   // Otherwise, t = elements[key + 2]. If t is the hole, then look up the value
    940   // in the unmapped arguments array, as described above. Otherwise, t is a Smi
    941   // index into the context array given at elements[0]. Return the value at
    942   // context[t].
    943 
    944   bool is_load = value == NULL;
    945 
    946   key = AddUncasted<HForceRepresentation>(key, Representation::Smi());
    947   IfBuilder positive_smi(this);
    948   positive_smi.If<HCompareNumericAndBranch>(key, graph()->GetConstant0(),
    949                                             Token::LT);
    950   positive_smi.ThenDeopt(Deoptimizer::kKeyIsNegative);
    951   positive_smi.End();
    952 
    953   HValue* constant_two = Add<HConstant>(2);
    954   HValue* elements = AddLoadElements(receiver, nullptr);
    955   HValue* elements_length = Add<HLoadNamedField>(
    956       elements, nullptr, HObjectAccess::ForFixedArrayLength());
    957   HValue* adjusted_length = AddUncasted<HSub>(elements_length, constant_two);
    958   IfBuilder in_range(this);
    959   in_range.If<HCompareNumericAndBranch>(key, adjusted_length, Token::LT);
    960   in_range.Then();
    961   {
    962     HValue* index = AddUncasted<HAdd>(key, constant_two);
    963     HInstruction* mapped_index =
    964         Add<HLoadKeyed>(elements, index, nullptr, nullptr, FAST_HOLEY_ELEMENTS,
    965                         ALLOW_RETURN_HOLE);
    966 
    967     IfBuilder is_valid(this);
    968     is_valid.IfNot<HCompareObjectEqAndBranch>(mapped_index,
    969                                               graph()->GetConstantHole());
    970     is_valid.Then();
    971     {
    972       // TODO(mvstanton): I'd like to assert from this point, that if the
    973       // mapped_index is not the hole that it is indeed, a smi. An unnecessary
    974       // smi check is being emitted.
    975       HValue* the_context = Add<HLoadKeyed>(elements, graph()->GetConstant0(),
    976                                             nullptr, nullptr, FAST_ELEMENTS);
    977       STATIC_ASSERT(Context::kHeaderSize == FixedArray::kHeaderSize);
    978       if (is_load) {
    979         HValue* result =
    980             Add<HLoadKeyed>(the_context, mapped_index, nullptr, nullptr,
    981                             FAST_ELEMENTS, ALLOW_RETURN_HOLE);
    982         environment()->Push(result);
    983       } else {
    984         DCHECK(value != NULL);
    985         Add<HStoreKeyed>(the_context, mapped_index, value, nullptr,
    986                          FAST_ELEMENTS);
    987         environment()->Push(value);
    988       }
    989     }
    990     is_valid.Else();
    991     {
    992       HValue* result = UnmappedCase(elements, key, value);
    993       environment()->Push(is_load ? result : value);
    994     }
    995     is_valid.End();
    996   }
    997   in_range.Else();
    998   {
    999     HValue* result = UnmappedCase(elements, key, value);
   1000     environment()->Push(is_load ? result : value);
   1001   }
   1002   in_range.End();
   1003 
   1004   return environment()->Pop();
   1005 }
   1006 
   1007 
   1008 template <>
   1009 HValue* CodeStubGraphBuilder<KeyedLoadSloppyArgumentsStub>::BuildCodeStub() {
   1010   HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex);
   1011   HValue* key = GetParameter(LoadDescriptor::kNameIndex);
   1012 
   1013   return EmitKeyedSloppyArguments(receiver, key, NULL);
   1014 }
   1015 
   1016 
   1017 Handle<Code> KeyedLoadSloppyArgumentsStub::GenerateCode() {
   1018   return DoGenerateCode(this);
   1019 }
   1020 
   1021 
   1022 template <>
   1023 HValue* CodeStubGraphBuilder<KeyedStoreSloppyArgumentsStub>::BuildCodeStub() {
   1024   HValue* receiver = GetParameter(StoreDescriptor::kReceiverIndex);
   1025   HValue* key = GetParameter(StoreDescriptor::kNameIndex);
   1026   HValue* value = GetParameter(StoreDescriptor::kValueIndex);
   1027 
   1028   return EmitKeyedSloppyArguments(receiver, key, value);
   1029 }
   1030 
   1031 
   1032 Handle<Code> KeyedStoreSloppyArgumentsStub::GenerateCode() {
   1033   return DoGenerateCode(this);
   1034 }
   1035 
   1036 
   1037 void CodeStubGraphBuilderBase::BuildStoreNamedField(
   1038     HValue* object, HValue* value, FieldIndex index,
   1039     Representation representation, bool transition_to_field) {
   1040   DCHECK(!index.is_double() || representation.IsDouble());
   1041   int offset = index.offset();
   1042   HObjectAccess access =
   1043       index.is_inobject()
   1044           ? HObjectAccess::ForObservableJSObjectOffset(offset, representation)
   1045           : HObjectAccess::ForBackingStoreOffset(offset, representation);
   1046 
   1047   if (representation.IsDouble()) {
   1048     if (!FLAG_unbox_double_fields || !index.is_inobject()) {
   1049       HObjectAccess heap_number_access =
   1050           access.WithRepresentation(Representation::Tagged());
   1051       if (transition_to_field) {
   1052         // The store requires a mutable HeapNumber to be allocated.
   1053         NoObservableSideEffectsScope no_side_effects(this);
   1054         HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
   1055 
   1056         // TODO(hpayer): Allocation site pretenuring support.
   1057         HInstruction* heap_number =
   1058             Add<HAllocate>(heap_number_size, HType::HeapObject(), NOT_TENURED,
   1059                            MUTABLE_HEAP_NUMBER_TYPE);
   1060         AddStoreMapConstant(heap_number,
   1061                             isolate()->factory()->mutable_heap_number_map());
   1062         Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
   1063                               value);
   1064         // Store the new mutable heap number into the object.
   1065         access = heap_number_access;
   1066         value = heap_number;
   1067       } else {
   1068         // Load the heap number.
   1069         object = Add<HLoadNamedField>(object, nullptr, heap_number_access);
   1070         // Store the double value into it.
   1071         access = HObjectAccess::ForHeapNumberValue();
   1072       }
   1073     }
   1074   } else if (representation.IsHeapObject()) {
   1075     BuildCheckHeapObject(value);
   1076   }
   1077 
   1078   Add<HStoreNamedField>(object, access, value, INITIALIZING_STORE);
   1079 }
   1080 
   1081 
   1082 template <>
   1083 HValue* CodeStubGraphBuilder<StoreFieldStub>::BuildCodeStub() {
   1084   BuildStoreNamedField(GetParameter(0), GetParameter(2), casted_stub()->index(),
   1085                        casted_stub()->representation(), false);
   1086   return GetParameter(2);
   1087 }
   1088 
   1089 
   1090 Handle<Code> StoreFieldStub::GenerateCode() { return DoGenerateCode(this); }
   1091 
   1092 
   1093 template <>
   1094 HValue* CodeStubGraphBuilder<StoreTransitionStub>::BuildCodeStub() {
   1095   HValue* object = GetParameter(StoreTransitionHelper::ReceiverIndex());
   1096 
   1097   switch (casted_stub()->store_mode()) {
   1098     case StoreTransitionStub::ExtendStorageAndStoreMapAndValue: {
   1099       HValue* properties = Add<HLoadNamedField>(
   1100           object, nullptr, HObjectAccess::ForPropertiesPointer());
   1101       HValue* length = AddLoadFixedArrayLength(properties);
   1102       HValue* delta =
   1103           Add<HConstant>(static_cast<int32_t>(JSObject::kFieldsAdded));
   1104       HValue* new_capacity = AddUncasted<HAdd>(length, delta);
   1105 
   1106       // Grow properties array.
   1107       ElementsKind kind = FAST_ELEMENTS;
   1108       Add<HBoundsCheck>(new_capacity,
   1109                         Add<HConstant>((Page::kMaxRegularHeapObjectSize -
   1110                                         FixedArray::kHeaderSize) >>
   1111                                        ElementsKindToShiftSize(kind)));
   1112 
   1113       // Reuse this code for properties backing store allocation.
   1114       HValue* new_properties =
   1115           BuildAllocateAndInitializeArray(kind, new_capacity);
   1116 
   1117       BuildCopyProperties(properties, new_properties, length, new_capacity);
   1118 
   1119       Add<HStoreNamedField>(object, HObjectAccess::ForPropertiesPointer(),
   1120                             new_properties);
   1121     }
   1122     // Fall through.
   1123     case StoreTransitionStub::StoreMapAndValue:
   1124       // Store the new value into the "extended" object.
   1125       BuildStoreNamedField(
   1126           object, GetParameter(StoreTransitionHelper::ValueIndex()),
   1127           casted_stub()->index(), casted_stub()->representation(), true);
   1128     // Fall through.
   1129 
   1130     case StoreTransitionStub::StoreMapOnly:
   1131       // And finally update the map.
   1132       Add<HStoreNamedField>(object, HObjectAccess::ForMap(),
   1133                             GetParameter(StoreTransitionHelper::MapIndex()));
   1134       break;
   1135   }
   1136   return GetParameter(StoreTransitionHelper::ValueIndex());
   1137 }
   1138 
   1139 
   1140 Handle<Code> StoreTransitionStub::GenerateCode() {
   1141   return DoGenerateCode(this);
   1142 }
   1143 
   1144 
   1145 template <>
   1146 HValue* CodeStubGraphBuilder<StoreFastElementStub>::BuildCodeStub() {
   1147   BuildUncheckedMonomorphicElementAccess(
   1148       GetParameter(StoreDescriptor::kReceiverIndex),
   1149       GetParameter(StoreDescriptor::kNameIndex),
   1150       GetParameter(StoreDescriptor::kValueIndex), casted_stub()->is_js_array(),
   1151       casted_stub()->elements_kind(), STORE, NEVER_RETURN_HOLE,
   1152       casted_stub()->store_mode());
   1153 
   1154   return GetParameter(2);
   1155 }
   1156 
   1157 
   1158 Handle<Code> StoreFastElementStub::GenerateCode() {
   1159   return DoGenerateCode(this);
   1160 }
   1161 
   1162 
   1163 template <>
   1164 HValue* CodeStubGraphBuilder<TransitionElementsKindStub>::BuildCodeStub() {
   1165   info()->MarkAsSavesCallerDoubles();
   1166 
   1167   BuildTransitionElementsKind(GetParameter(0),
   1168                               GetParameter(1),
   1169                               casted_stub()->from_kind(),
   1170                               casted_stub()->to_kind(),
   1171                               casted_stub()->is_js_array());
   1172 
   1173   return GetParameter(0);
   1174 }
   1175 
   1176 
   1177 Handle<Code> TransitionElementsKindStub::GenerateCode() {
   1178   return DoGenerateCode(this);
   1179 }
   1180 
   1181 
   1182 template <>
   1183 HValue* CodeStubGraphBuilder<AllocateHeapNumberStub>::BuildCodeStub() {
   1184   HValue* result =
   1185       Add<HAllocate>(Add<HConstant>(HeapNumber::kSize), HType::HeapNumber(),
   1186                      NOT_TENURED, HEAP_NUMBER_TYPE);
   1187   AddStoreMapConstant(result, isolate()->factory()->heap_number_map());
   1188   return result;
   1189 }
   1190 
   1191 
   1192 Handle<Code> AllocateHeapNumberStub::GenerateCode() {
   1193   return DoGenerateCode(this);
   1194 }
   1195 
   1196 
   1197 template <>
   1198 HValue* CodeStubGraphBuilder<AllocateMutableHeapNumberStub>::BuildCodeStub() {
   1199   HValue* result =
   1200       Add<HAllocate>(Add<HConstant>(HeapNumber::kSize), HType::HeapObject(),
   1201                      NOT_TENURED, MUTABLE_HEAP_NUMBER_TYPE);
   1202   AddStoreMapConstant(result, isolate()->factory()->mutable_heap_number_map());
   1203   return result;
   1204 }
   1205 
   1206 
   1207 Handle<Code> AllocateMutableHeapNumberStub::GenerateCode() {
   1208   return DoGenerateCode(this);
   1209 }
   1210 
   1211 
   1212 template <>
   1213 HValue* CodeStubGraphBuilder<AllocateInNewSpaceStub>::BuildCodeStub() {
   1214   HValue* result = Add<HAllocate>(GetParameter(0), HType::Tagged(), NOT_TENURED,
   1215                                   JS_OBJECT_TYPE);
   1216   return result;
   1217 }
   1218 
   1219 
   1220 Handle<Code> AllocateInNewSpaceStub::GenerateCode() {
   1221   return DoGenerateCode(this);
   1222 }
   1223 
   1224 
   1225 HValue* CodeStubGraphBuilderBase::BuildArrayConstructor(
   1226     ElementsKind kind,
   1227     AllocationSiteOverrideMode override_mode,
   1228     ArgumentClass argument_class) {
   1229   HValue* constructor = GetParameter(ArrayConstructorStubBase::kConstructor);
   1230   HValue* alloc_site = GetParameter(ArrayConstructorStubBase::kAllocationSite);
   1231   JSArrayBuilder array_builder(this, kind, alloc_site, constructor,
   1232                                override_mode);
   1233   HValue* result = NULL;
   1234   switch (argument_class) {
   1235     case NONE:
   1236       // This stub is very performance sensitive, the generated code must be
   1237       // tuned so that it doesn't build and eager frame.
   1238       info()->MarkMustNotHaveEagerFrame();
   1239       result = array_builder.AllocateEmptyArray();
   1240       break;
   1241     case SINGLE:
   1242       result = BuildArraySingleArgumentConstructor(&array_builder);
   1243       break;
   1244     case MULTIPLE:
   1245       result = BuildArrayNArgumentsConstructor(&array_builder, kind);
   1246       break;
   1247   }
   1248 
   1249   return result;
   1250 }
   1251 
   1252 
   1253 HValue* CodeStubGraphBuilderBase::BuildInternalArrayConstructor(
   1254     ElementsKind kind, ArgumentClass argument_class) {
   1255   HValue* constructor = GetParameter(
   1256       InternalArrayConstructorStubBase::kConstructor);
   1257   JSArrayBuilder array_builder(this, kind, constructor);
   1258 
   1259   HValue* result = NULL;
   1260   switch (argument_class) {
   1261     case NONE:
   1262       // This stub is very performance sensitive, the generated code must be
   1263       // tuned so that it doesn't build and eager frame.
   1264       info()->MarkMustNotHaveEagerFrame();
   1265       result = array_builder.AllocateEmptyArray();
   1266       break;
   1267     case SINGLE:
   1268       result = BuildArraySingleArgumentConstructor(&array_builder);
   1269       break;
   1270     case MULTIPLE:
   1271       result = BuildArrayNArgumentsConstructor(&array_builder, kind);
   1272       break;
   1273   }
   1274   return result;
   1275 }
   1276 
   1277 
   1278 HValue* CodeStubGraphBuilderBase::BuildArraySingleArgumentConstructor(
   1279     JSArrayBuilder* array_builder) {
   1280   // Smi check and range check on the input arg.
   1281   HValue* constant_one = graph()->GetConstant1();
   1282   HValue* constant_zero = graph()->GetConstant0();
   1283 
   1284   HInstruction* elements = Add<HArgumentsElements>(false);
   1285   HInstruction* argument = Add<HAccessArgumentsAt>(
   1286       elements, constant_one, constant_zero);
   1287 
   1288   return BuildAllocateArrayFromLength(array_builder, argument);
   1289 }
   1290 
   1291 
   1292 HValue* CodeStubGraphBuilderBase::BuildArrayNArgumentsConstructor(
   1293     JSArrayBuilder* array_builder, ElementsKind kind) {
   1294   // Insert a bounds check because the number of arguments might exceed
   1295   // the kInitialMaxFastElementArray limit. This cannot happen for code
   1296   // that was parsed, but calling via Array.apply(thisArg, [...]) might
   1297   // trigger it.
   1298   HValue* length = GetArgumentsLength();
   1299   HConstant* max_alloc_length =
   1300       Add<HConstant>(JSArray::kInitialMaxFastElementArray);
   1301   HValue* checked_length = Add<HBoundsCheck>(length, max_alloc_length);
   1302 
   1303   // We need to fill with the hole if it's a smi array in the multi-argument
   1304   // case because we might have to bail out while copying arguments into
   1305   // the array because they aren't compatible with a smi array.
   1306   // If it's a double array, no problem, and if it's fast then no
   1307   // problem either because doubles are boxed.
   1308   //
   1309   // TODO(mvstanton): consider an instruction to memset fill the array
   1310   // with zero in this case instead.
   1311   JSArrayBuilder::FillMode fill_mode = IsFastSmiElementsKind(kind)
   1312       ? JSArrayBuilder::FILL_WITH_HOLE
   1313       : JSArrayBuilder::DONT_FILL_WITH_HOLE;
   1314   HValue* new_object = array_builder->AllocateArray(checked_length,
   1315                                                     max_alloc_length,
   1316                                                     checked_length,
   1317                                                     fill_mode);
   1318   HValue* elements = array_builder->GetElementsLocation();
   1319   DCHECK(elements != NULL);
   1320 
   1321   // Now populate the elements correctly.
   1322   LoopBuilder builder(this,
   1323                       context(),
   1324                       LoopBuilder::kPostIncrement);
   1325   HValue* start = graph()->GetConstant0();
   1326   HValue* key = builder.BeginBody(start, checked_length, Token::LT);
   1327   HInstruction* argument_elements = Add<HArgumentsElements>(false);
   1328   HInstruction* argument = Add<HAccessArgumentsAt>(
   1329       argument_elements, checked_length, key);
   1330 
   1331   Add<HStoreKeyed>(elements, key, argument, nullptr, kind);
   1332   builder.EndBody();
   1333   return new_object;
   1334 }
   1335 
   1336 
   1337 template <>
   1338 HValue* CodeStubGraphBuilder<ArrayNoArgumentConstructorStub>::BuildCodeStub() {
   1339   ElementsKind kind = casted_stub()->elements_kind();
   1340   AllocationSiteOverrideMode override_mode = casted_stub()->override_mode();
   1341   return BuildArrayConstructor(kind, override_mode, NONE);
   1342 }
   1343 
   1344 
   1345 Handle<Code> ArrayNoArgumentConstructorStub::GenerateCode() {
   1346   return DoGenerateCode(this);
   1347 }
   1348 
   1349 
   1350 template <>
   1351 HValue* CodeStubGraphBuilder<ArraySingleArgumentConstructorStub>::
   1352     BuildCodeStub() {
   1353   ElementsKind kind = casted_stub()->elements_kind();
   1354   AllocationSiteOverrideMode override_mode = casted_stub()->override_mode();
   1355   return BuildArrayConstructor(kind, override_mode, SINGLE);
   1356 }
   1357 
   1358 
   1359 Handle<Code> ArraySingleArgumentConstructorStub::GenerateCode() {
   1360   return DoGenerateCode(this);
   1361 }
   1362 
   1363 
   1364 template <>
   1365 HValue* CodeStubGraphBuilder<ArrayNArgumentsConstructorStub>::BuildCodeStub() {
   1366   ElementsKind kind = casted_stub()->elements_kind();
   1367   AllocationSiteOverrideMode override_mode = casted_stub()->override_mode();
   1368   return BuildArrayConstructor(kind, override_mode, MULTIPLE);
   1369 }
   1370 
   1371 
   1372 Handle<Code> ArrayNArgumentsConstructorStub::GenerateCode() {
   1373   return DoGenerateCode(this);
   1374 }
   1375 
   1376 
   1377 template <>
   1378 HValue* CodeStubGraphBuilder<InternalArrayNoArgumentConstructorStub>::
   1379     BuildCodeStub() {
   1380   ElementsKind kind = casted_stub()->elements_kind();
   1381   return BuildInternalArrayConstructor(kind, NONE);
   1382 }
   1383 
   1384 
   1385 Handle<Code> InternalArrayNoArgumentConstructorStub::GenerateCode() {
   1386   return DoGenerateCode(this);
   1387 }
   1388 
   1389 
   1390 template <>
   1391 HValue* CodeStubGraphBuilder<InternalArraySingleArgumentConstructorStub>::
   1392     BuildCodeStub() {
   1393   ElementsKind kind = casted_stub()->elements_kind();
   1394   return BuildInternalArrayConstructor(kind, SINGLE);
   1395 }
   1396 
   1397 
   1398 Handle<Code> InternalArraySingleArgumentConstructorStub::GenerateCode() {
   1399   return DoGenerateCode(this);
   1400 }
   1401 
   1402 
   1403 template <>
   1404 HValue* CodeStubGraphBuilder<InternalArrayNArgumentsConstructorStub>::
   1405     BuildCodeStub() {
   1406   ElementsKind kind = casted_stub()->elements_kind();
   1407   return BuildInternalArrayConstructor(kind, MULTIPLE);
   1408 }
   1409 
   1410 
   1411 Handle<Code> InternalArrayNArgumentsConstructorStub::GenerateCode() {
   1412   return DoGenerateCode(this);
   1413 }
   1414 
   1415 
   1416 template <>
   1417 HValue* CodeStubGraphBuilder<CompareNilICStub>::BuildCodeInitializedStub() {
   1418   Isolate* isolate = graph()->isolate();
   1419   CompareNilICStub* stub = casted_stub();
   1420   HIfContinuation continuation;
   1421   Handle<Map> sentinel_map(isolate->heap()->meta_map());
   1422   Type* type = stub->GetType(zone(), sentinel_map);
   1423   BuildCompareNil(GetParameter(0), type, &continuation, kEmbedMapsViaWeakCells);
   1424   IfBuilder if_nil(this, &continuation);
   1425   if_nil.Then();
   1426   if (continuation.IsFalseReachable()) {
   1427     if_nil.Else();
   1428     if_nil.Return(graph()->GetConstantFalse());
   1429   }
   1430   if_nil.End();
   1431   return continuation.IsTrueReachable() ? graph()->GetConstantTrue()
   1432                                         : graph()->GetConstantUndefined();
   1433 }
   1434 
   1435 
   1436 Handle<Code> CompareNilICStub::GenerateCode() {
   1437   return DoGenerateCode(this);
   1438 }
   1439 
   1440 
   1441 template <>
   1442 HValue* CodeStubGraphBuilder<BinaryOpICStub>::BuildCodeInitializedStub() {
   1443   BinaryOpICState state = casted_stub()->state();
   1444 
   1445   HValue* left = GetParameter(BinaryOpICStub::kLeft);
   1446   HValue* right = GetParameter(BinaryOpICStub::kRight);
   1447 
   1448   Type* left_type = state.GetLeftType();
   1449   Type* right_type = state.GetRightType();
   1450   Type* result_type = state.GetResultType();
   1451 
   1452   DCHECK(!left_type->Is(Type::None()) && !right_type->Is(Type::None()) &&
   1453          (state.HasSideEffects() || !result_type->Is(Type::None())));
   1454 
   1455   HValue* result = NULL;
   1456   HAllocationMode allocation_mode(NOT_TENURED);
   1457   if (state.op() == Token::ADD &&
   1458       (left_type->Maybe(Type::String()) || right_type->Maybe(Type::String())) &&
   1459       !left_type->Is(Type::String()) && !right_type->Is(Type::String())) {
   1460     // For the generic add stub a fast case for string addition is performance
   1461     // critical.
   1462     if (left_type->Maybe(Type::String())) {
   1463       IfBuilder if_leftisstring(this);
   1464       if_leftisstring.If<HIsStringAndBranch>(left);
   1465       if_leftisstring.Then();
   1466       {
   1467         Push(BuildBinaryOperation(state.op(), left, right, Type::String(zone()),
   1468                                   right_type, result_type,
   1469                                   state.fixed_right_arg(), allocation_mode,
   1470                                   state.strength()));
   1471       }
   1472       if_leftisstring.Else();
   1473       {
   1474         Push(BuildBinaryOperation(
   1475             state.op(), left, right, left_type, right_type, result_type,
   1476             state.fixed_right_arg(), allocation_mode, state.strength()));
   1477       }
   1478       if_leftisstring.End();
   1479       result = Pop();
   1480     } else {
   1481       IfBuilder if_rightisstring(this);
   1482       if_rightisstring.If<HIsStringAndBranch>(right);
   1483       if_rightisstring.Then();
   1484       {
   1485         Push(BuildBinaryOperation(state.op(), left, right, left_type,
   1486                                   Type::String(zone()), result_type,
   1487                                   state.fixed_right_arg(), allocation_mode,
   1488                                   state.strength()));
   1489       }
   1490       if_rightisstring.Else();
   1491       {
   1492         Push(BuildBinaryOperation(
   1493             state.op(), left, right, left_type, right_type, result_type,
   1494             state.fixed_right_arg(), allocation_mode, state.strength()));
   1495       }
   1496       if_rightisstring.End();
   1497       result = Pop();
   1498     }
   1499   } else {
   1500     result = BuildBinaryOperation(
   1501         state.op(), left, right, left_type, right_type, result_type,
   1502         state.fixed_right_arg(), allocation_mode, state.strength());
   1503   }
   1504 
   1505   // If we encounter a generic argument, the number conversion is
   1506   // observable, thus we cannot afford to bail out after the fact.
   1507   if (!state.HasSideEffects()) {
   1508     result = EnforceNumberType(result, result_type);
   1509   }
   1510 
   1511   return result;
   1512 }
   1513 
   1514 
   1515 Handle<Code> BinaryOpICStub::GenerateCode() {
   1516   return DoGenerateCode(this);
   1517 }
   1518 
   1519 
   1520 template <>
   1521 HValue* CodeStubGraphBuilder<BinaryOpWithAllocationSiteStub>::BuildCodeStub() {
   1522   BinaryOpICState state = casted_stub()->state();
   1523 
   1524   HValue* allocation_site = GetParameter(
   1525       BinaryOpWithAllocationSiteStub::kAllocationSite);
   1526   HValue* left = GetParameter(BinaryOpWithAllocationSiteStub::kLeft);
   1527   HValue* right = GetParameter(BinaryOpWithAllocationSiteStub::kRight);
   1528 
   1529   Type* left_type = state.GetLeftType();
   1530   Type* right_type = state.GetRightType();
   1531   Type* result_type = state.GetResultType();
   1532   HAllocationMode allocation_mode(allocation_site);
   1533 
   1534   return BuildBinaryOperation(state.op(), left, right, left_type, right_type,
   1535                               result_type, state.fixed_right_arg(),
   1536                               allocation_mode, state.strength());
   1537 }
   1538 
   1539 
   1540 Handle<Code> BinaryOpWithAllocationSiteStub::GenerateCode() {
   1541   return DoGenerateCode(this);
   1542 }
   1543 
   1544 
   1545 HValue* CodeStubGraphBuilderBase::BuildToString(HValue* input, bool convert) {
   1546   if (!convert) return BuildCheckString(input);
   1547   IfBuilder if_inputissmi(this);
   1548   HValue* inputissmi = if_inputissmi.If<HIsSmiAndBranch>(input);
   1549   if_inputissmi.Then();
   1550   {
   1551     // Convert the input smi to a string.
   1552     Push(BuildNumberToString(input, Type::SignedSmall()));
   1553   }
   1554   if_inputissmi.Else();
   1555   {
   1556     HValue* input_map =
   1557         Add<HLoadNamedField>(input, inputissmi, HObjectAccess::ForMap());
   1558     HValue* input_instance_type = Add<HLoadNamedField>(
   1559         input_map, inputissmi, HObjectAccess::ForMapInstanceType());
   1560     IfBuilder if_inputisstring(this);
   1561     if_inputisstring.If<HCompareNumericAndBranch>(
   1562         input_instance_type, Add<HConstant>(FIRST_NONSTRING_TYPE), Token::LT);
   1563     if_inputisstring.Then();
   1564     {
   1565       // The input is already a string.
   1566       Push(input);
   1567     }
   1568     if_inputisstring.Else();
   1569     {
   1570       // Convert to primitive first (if necessary), see
   1571       // ES6 section 12.7.3 The Addition operator.
   1572       IfBuilder if_inputisprimitive(this);
   1573       STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE);
   1574       if_inputisprimitive.If<HCompareNumericAndBranch>(
   1575           input_instance_type, Add<HConstant>(LAST_PRIMITIVE_TYPE), Token::LTE);
   1576       if_inputisprimitive.Then();
   1577       {
   1578         // The input is already a primitive.
   1579         Push(input);
   1580       }
   1581       if_inputisprimitive.Else();
   1582       {
   1583         // Convert the input to a primitive.
   1584         Push(BuildToPrimitive(input, input_map));
   1585       }
   1586       if_inputisprimitive.End();
   1587       // Convert the primitive to a string value.
   1588       ToStringDescriptor descriptor(isolate());
   1589       ToStringStub stub(isolate());
   1590       HValue* values[] = {context(), Pop()};
   1591       Push(AddUncasted<HCallWithDescriptor>(
   1592           Add<HConstant>(stub.GetCode()), 0, descriptor,
   1593           Vector<HValue*>(values, arraysize(values))));
   1594     }
   1595     if_inputisstring.End();
   1596   }
   1597   if_inputissmi.End();
   1598   return Pop();
   1599 }
   1600 
   1601 
   1602 HValue* CodeStubGraphBuilderBase::BuildToPrimitive(HValue* input,
   1603                                                    HValue* input_map) {
   1604   // Get the native context of the caller.
   1605   HValue* native_context = BuildGetNativeContext();
   1606 
   1607   // Determine the initial map of the %ObjectPrototype%.
   1608   HValue* object_function_prototype_map =
   1609       Add<HLoadNamedField>(native_context, nullptr,
   1610                            HObjectAccess::ForContextSlot(
   1611                                Context::OBJECT_FUNCTION_PROTOTYPE_MAP_INDEX));
   1612 
   1613   // Determine the initial map of the %StringPrototype%.
   1614   HValue* string_function_prototype_map =
   1615       Add<HLoadNamedField>(native_context, nullptr,
   1616                            HObjectAccess::ForContextSlot(
   1617                                Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
   1618 
   1619   // Determine the initial map of the String function.
   1620   HValue* string_function = Add<HLoadNamedField>(
   1621       native_context, nullptr,
   1622       HObjectAccess::ForContextSlot(Context::STRING_FUNCTION_INDEX));
   1623   HValue* string_function_initial_map = Add<HLoadNamedField>(
   1624       string_function, nullptr, HObjectAccess::ForPrototypeOrInitialMap());
   1625 
   1626   // Determine the map of the [[Prototype]] of {input}.
   1627   HValue* input_prototype =
   1628       Add<HLoadNamedField>(input_map, nullptr, HObjectAccess::ForPrototype());
   1629   HValue* input_prototype_map =
   1630       Add<HLoadNamedField>(input_prototype, nullptr, HObjectAccess::ForMap());
   1631 
   1632   // For string wrappers (JSValue instances with [[StringData]] internal
   1633   // fields), we can shortcirciut the ToPrimitive if
   1634   //
   1635   //  (a) the {input} map matches the initial map of the String function,
   1636   //  (b) the {input} [[Prototype]] is the unmodified %StringPrototype% (i.e.
   1637   //      no one monkey-patched toString, @@toPrimitive or valueOf), and
   1638   //  (c) the %ObjectPrototype% (i.e. the [[Prototype]] of the
   1639   //      %StringPrototype%) is also unmodified, that is no one sneaked a
   1640   //      @@toPrimitive into the %ObjectPrototype%.
   1641   //
   1642   // If all these assumptions hold, we can just take the [[StringData]] value
   1643   // and return it.
   1644   // TODO(bmeurer): This just repairs a regression introduced by removing the
   1645   // weird (and broken) intrinsic %_IsStringWrapperSafeForDefaultValue, which
   1646   // was intendend to something similar to this, although less efficient and
   1647   // wrong in the presence of @@toPrimitive. Long-term we might want to move
   1648   // into the direction of having a ToPrimitiveStub that can do common cases
   1649   // while staying in JavaScript land (i.e. not going to C++).
   1650   IfBuilder if_inputisstringwrapper(this);
   1651   if_inputisstringwrapper.If<HCompareObjectEqAndBranch>(
   1652       input_map, string_function_initial_map);
   1653   if_inputisstringwrapper.And();
   1654   if_inputisstringwrapper.If<HCompareObjectEqAndBranch>(
   1655       input_prototype_map, string_function_prototype_map);
   1656   if_inputisstringwrapper.And();
   1657   if_inputisstringwrapper.If<HCompareObjectEqAndBranch>(
   1658       Add<HLoadNamedField>(Add<HLoadNamedField>(input_prototype_map, nullptr,
   1659                                                 HObjectAccess::ForPrototype()),
   1660                            nullptr, HObjectAccess::ForMap()),
   1661       object_function_prototype_map);
   1662   if_inputisstringwrapper.Then();
   1663   {
   1664     Push(BuildLoadNamedField(
   1665         input, FieldIndex::ForInObjectOffset(JSValue::kValueOffset)));
   1666   }
   1667   if_inputisstringwrapper.Else();
   1668   {
   1669     // TODO(bmeurer): Add support for fast ToPrimitive conversion using
   1670     // a dedicated ToPrimitiveStub.
   1671     Add<HPushArguments>(input);
   1672     Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kToPrimitive), 1));
   1673   }
   1674   if_inputisstringwrapper.End();
   1675   return Pop();
   1676 }
   1677 
   1678 
   1679 template <>
   1680 HValue* CodeStubGraphBuilder<StringAddStub>::BuildCodeInitializedStub() {
   1681   StringAddStub* stub = casted_stub();
   1682   StringAddFlags flags = stub->flags();
   1683   PretenureFlag pretenure_flag = stub->pretenure_flag();
   1684 
   1685   HValue* left = GetParameter(StringAddStub::kLeft);
   1686   HValue* right = GetParameter(StringAddStub::kRight);
   1687 
   1688   // Make sure that both arguments are strings if not known in advance.
   1689   if ((flags & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
   1690     left =
   1691         BuildToString(left, (flags & STRING_ADD_CONVERT) == STRING_ADD_CONVERT);
   1692   }
   1693   if ((flags & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
   1694     right = BuildToString(right,
   1695                           (flags & STRING_ADD_CONVERT) == STRING_ADD_CONVERT);
   1696   }
   1697 
   1698   return BuildStringAdd(left, right, HAllocationMode(pretenure_flag));
   1699 }
   1700 
   1701 
   1702 Handle<Code> StringAddStub::GenerateCode() {
   1703   return DoGenerateCode(this);
   1704 }
   1705 
   1706 
   1707 template <>
   1708 HValue* CodeStubGraphBuilder<ToBooleanStub>::BuildCodeInitializedStub() {
   1709   ToBooleanStub* stub = casted_stub();
   1710   IfBuilder if_true(this);
   1711   if_true.If<HBranch>(GetParameter(0), stub->types());
   1712   if_true.Then();
   1713   if_true.Return(graph()->GetConstantTrue());
   1714   if_true.Else();
   1715   if_true.End();
   1716   return graph()->GetConstantFalse();
   1717 }
   1718 
   1719 
   1720 Handle<Code> ToBooleanStub::GenerateCode() {
   1721   return DoGenerateCode(this);
   1722 }
   1723 
   1724 
   1725 template <>
   1726 HValue* CodeStubGraphBuilder<StoreGlobalStub>::BuildCodeInitializedStub() {
   1727   StoreGlobalStub* stub = casted_stub();
   1728   HParameter* value = GetParameter(StoreDescriptor::kValueIndex);
   1729   if (stub->check_global()) {
   1730     // Check that the map of the global has not changed: use a placeholder map
   1731     // that will be replaced later with the global object's map.
   1732     HParameter* proxy = GetParameter(StoreDescriptor::kReceiverIndex);
   1733     HValue* proxy_map =
   1734         Add<HLoadNamedField>(proxy, nullptr, HObjectAccess::ForMap());
   1735     HValue* global =
   1736         Add<HLoadNamedField>(proxy_map, nullptr, HObjectAccess::ForPrototype());
   1737     HValue* map_cell = Add<HConstant>(isolate()->factory()->NewWeakCell(
   1738         StoreGlobalStub::global_map_placeholder(isolate())));
   1739     HValue* expected_map = Add<HLoadNamedField>(
   1740         map_cell, nullptr, HObjectAccess::ForWeakCellValue());
   1741     HValue* map =
   1742         Add<HLoadNamedField>(global, nullptr, HObjectAccess::ForMap());
   1743     IfBuilder map_check(this);
   1744     map_check.IfNot<HCompareObjectEqAndBranch>(expected_map, map);
   1745     map_check.ThenDeopt(Deoptimizer::kUnknownMap);
   1746     map_check.End();
   1747   }
   1748 
   1749   HValue* weak_cell = Add<HConstant>(isolate()->factory()->NewWeakCell(
   1750       StoreGlobalStub::property_cell_placeholder(isolate())));
   1751   HValue* cell = Add<HLoadNamedField>(weak_cell, nullptr,
   1752                                       HObjectAccess::ForWeakCellValue());
   1753   Add<HCheckHeapObject>(cell);
   1754   HObjectAccess access = HObjectAccess::ForPropertyCellValue();
   1755   // Load the payload of the global parameter cell. A hole indicates that the
   1756   // cell has been invalidated and that the store must be handled by the
   1757   // runtime.
   1758   HValue* cell_contents = Add<HLoadNamedField>(cell, nullptr, access);
   1759 
   1760   auto cell_type = stub->cell_type();
   1761   if (cell_type == PropertyCellType::kConstant ||
   1762       cell_type == PropertyCellType::kUndefined) {
   1763     // This is always valid for all states a cell can be in.
   1764     IfBuilder builder(this);
   1765     builder.If<HCompareObjectEqAndBranch>(cell_contents, value);
   1766     builder.Then();
   1767     builder.ElseDeopt(
   1768         Deoptimizer::kUnexpectedCellContentsInConstantGlobalStore);
   1769     builder.End();
   1770   } else {
   1771     IfBuilder builder(this);
   1772     HValue* hole_value = graph()->GetConstantHole();
   1773     builder.If<HCompareObjectEqAndBranch>(cell_contents, hole_value);
   1774     builder.Then();
   1775     builder.Deopt(Deoptimizer::kUnexpectedCellContentsInGlobalStore);
   1776     builder.Else();
   1777     // When dealing with constant types, the type may be allowed to change, as
   1778     // long as optimized code remains valid.
   1779     if (cell_type == PropertyCellType::kConstantType) {
   1780       switch (stub->constant_type()) {
   1781         case PropertyCellConstantType::kSmi:
   1782           access = access.WithRepresentation(Representation::Smi());
   1783           break;
   1784         case PropertyCellConstantType::kStableMap: {
   1785           // It is sufficient here to check that the value and cell contents
   1786           // have identical maps, no matter if they are stable or not or if they
   1787           // are the maps that were originally in the cell or not. If optimized
   1788           // code will deopt when a cell has a unstable map and if it has a
   1789           // dependency on a stable map, it will deopt if the map destabilizes.
   1790           Add<HCheckHeapObject>(value);
   1791           Add<HCheckHeapObject>(cell_contents);
   1792           HValue* expected_map = Add<HLoadNamedField>(cell_contents, nullptr,
   1793                                                       HObjectAccess::ForMap());
   1794           HValue* map =
   1795               Add<HLoadNamedField>(value, nullptr, HObjectAccess::ForMap());
   1796           IfBuilder map_check(this);
   1797           map_check.IfNot<HCompareObjectEqAndBranch>(expected_map, map);
   1798           map_check.ThenDeopt(Deoptimizer::kUnknownMap);
   1799           map_check.End();
   1800           access = access.WithRepresentation(Representation::HeapObject());
   1801           break;
   1802         }
   1803       }
   1804     }
   1805     Add<HStoreNamedField>(cell, access, value);
   1806     builder.End();
   1807   }
   1808 
   1809   return value;
   1810 }
   1811 
   1812 
   1813 Handle<Code> StoreGlobalStub::GenerateCode() {
   1814   return DoGenerateCode(this);
   1815 }
   1816 
   1817 
   1818 template <>
   1819 HValue* CodeStubGraphBuilder<ElementsTransitionAndStoreStub>::BuildCodeStub() {
   1820   HValue* object = GetParameter(StoreTransitionHelper::ReceiverIndex());
   1821   HValue* key = GetParameter(StoreTransitionHelper::NameIndex());
   1822   HValue* value = GetParameter(StoreTransitionHelper::ValueIndex());
   1823   HValue* map = GetParameter(StoreTransitionHelper::MapIndex());
   1824 
   1825   if (FLAG_trace_elements_transitions) {
   1826     // Tracing elements transitions is the job of the runtime.
   1827     Add<HDeoptimize>(Deoptimizer::kTracingElementsTransitions,
   1828                      Deoptimizer::EAGER);
   1829   } else {
   1830     info()->MarkAsSavesCallerDoubles();
   1831 
   1832     BuildTransitionElementsKind(object, map,
   1833                                 casted_stub()->from_kind(),
   1834                                 casted_stub()->to_kind(),
   1835                                 casted_stub()->is_jsarray());
   1836 
   1837     BuildUncheckedMonomorphicElementAccess(object, key, value,
   1838                                            casted_stub()->is_jsarray(),
   1839                                            casted_stub()->to_kind(),
   1840                                            STORE, ALLOW_RETURN_HOLE,
   1841                                            casted_stub()->store_mode());
   1842   }
   1843 
   1844   return value;
   1845 }
   1846 
   1847 
   1848 Handle<Code> ElementsTransitionAndStoreStub::GenerateCode() {
   1849   return DoGenerateCode(this);
   1850 }
   1851 
   1852 
   1853 template <>
   1854 HValue* CodeStubGraphBuilder<ToObjectStub>::BuildCodeStub() {
   1855   HValue* receiver = GetParameter(ToObjectDescriptor::kReceiverIndex);
   1856   return BuildToObject(receiver);
   1857 }
   1858 
   1859 
   1860 Handle<Code> ToObjectStub::GenerateCode() { return DoGenerateCode(this); }
   1861 
   1862 
   1863 void CodeStubGraphBuilderBase::BuildCheckAndInstallOptimizedCode(
   1864     HValue* js_function,
   1865     HValue* native_context,
   1866     IfBuilder* builder,
   1867     HValue* optimized_map,
   1868     HValue* map_index) {
   1869   HValue* osr_ast_id_none = Add<HConstant>(BailoutId::None().ToInt());
   1870   HValue* context_slot = LoadFromOptimizedCodeMap(
   1871       optimized_map, map_index, SharedFunctionInfo::kContextOffset);
   1872   context_slot = Add<HLoadNamedField>(context_slot, nullptr,
   1873                                       HObjectAccess::ForWeakCellValue());
   1874   HValue* osr_ast_slot = LoadFromOptimizedCodeMap(
   1875       optimized_map, map_index, SharedFunctionInfo::kOsrAstIdOffset);
   1876   HValue* code_object = LoadFromOptimizedCodeMap(
   1877       optimized_map, map_index, SharedFunctionInfo::kCachedCodeOffset);
   1878   code_object = Add<HLoadNamedField>(code_object, nullptr,
   1879                                      HObjectAccess::ForWeakCellValue());
   1880   builder->If<HCompareObjectEqAndBranch>(native_context,
   1881                                          context_slot);
   1882   builder->AndIf<HCompareObjectEqAndBranch>(osr_ast_slot, osr_ast_id_none);
   1883   builder->And();
   1884   builder->IfNot<HCompareObjectEqAndBranch>(code_object,
   1885                                             graph()->GetConstant0());
   1886   builder->Then();
   1887   HValue* literals = LoadFromOptimizedCodeMap(optimized_map,
   1888       map_index, SharedFunctionInfo::kLiteralsOffset);
   1889   literals = Add<HLoadNamedField>(literals, nullptr,
   1890                                   HObjectAccess::ForWeakCellValue());
   1891   IfBuilder maybe_deopt(this);
   1892   maybe_deopt.If<HCompareObjectEqAndBranch>(literals, graph()->GetConstant0());
   1893   maybe_deopt.ThenDeopt(Deoptimizer::kLiteralsWereDisposed);
   1894   maybe_deopt.End();
   1895 
   1896   BuildInstallOptimizedCode(js_function, native_context, code_object, literals);
   1897 
   1898   // The builder continues in the "then" after this function.
   1899 }
   1900 
   1901 
   1902 void CodeStubGraphBuilderBase::BuildInstallOptimizedCode(HValue* js_function,
   1903                                                          HValue* native_context,
   1904                                                          HValue* code_object,
   1905                                                          HValue* literals) {
   1906   Counters* counters = isolate()->counters();
   1907   AddIncrementCounter(counters->fast_new_closure_install_optimized());
   1908 
   1909   // TODO(fschneider): Idea: store proper code pointers in the optimized code
   1910   // map and either unmangle them on marking or do nothing as the whole map is
   1911   // discarded on major GC anyway.
   1912   Add<HStoreCodeEntry>(js_function, code_object);
   1913   Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(),
   1914                         literals);
   1915 
   1916   // Now link a function into a list of optimized functions.
   1917   HValue* optimized_functions_list = Add<HLoadNamedField>(
   1918       native_context, nullptr,
   1919       HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST));
   1920   Add<HStoreNamedField>(js_function,
   1921                         HObjectAccess::ForNextFunctionLinkPointer(),
   1922                         optimized_functions_list);
   1923 
   1924   // This store is the only one that should have a write barrier.
   1925   Add<HStoreNamedField>(native_context,
   1926            HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST),
   1927            js_function);
   1928 }
   1929 
   1930 
   1931 void CodeStubGraphBuilderBase::BuildInstallCode(HValue* js_function,
   1932                                                 HValue* shared_info) {
   1933   Add<HStoreNamedField>(js_function,
   1934                         HObjectAccess::ForNextFunctionLinkPointer(),
   1935                         graph()->GetConstantUndefined());
   1936   HValue* code_object = Add<HLoadNamedField>(shared_info, nullptr,
   1937                                              HObjectAccess::ForCodeOffset());
   1938   Add<HStoreCodeEntry>(js_function, code_object);
   1939 }
   1940 
   1941 
   1942 HInstruction* CodeStubGraphBuilderBase::LoadFromOptimizedCodeMap(
   1943     HValue* optimized_map,
   1944     HValue* iterator,
   1945     int field_offset) {
   1946   // By making sure to express these loads in the form [<hvalue> + constant]
   1947   // the keyed load can be hoisted.
   1948   DCHECK(field_offset >= 0 && field_offset < SharedFunctionInfo::kEntryLength);
   1949   HValue* field_slot = iterator;
   1950   if (field_offset > 0) {
   1951     HValue* field_offset_value = Add<HConstant>(field_offset);
   1952     field_slot = AddUncasted<HAdd>(iterator, field_offset_value);
   1953   }
   1954   HInstruction* field_entry = Add<HLoadKeyed>(optimized_map, field_slot,
   1955                                               nullptr, nullptr, FAST_ELEMENTS);
   1956   return field_entry;
   1957 }
   1958 
   1959 
   1960 void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap(
   1961     HValue* js_function,
   1962     HValue* shared_info,
   1963     HValue* native_context) {
   1964   Counters* counters = isolate()->counters();
   1965   Factory* factory = isolate()->factory();
   1966   IfBuilder is_optimized(this);
   1967   HInstruction* optimized_map = Add<HLoadNamedField>(
   1968       shared_info, nullptr, HObjectAccess::ForOptimizedCodeMap());
   1969   HValue* null_constant = Add<HConstant>(0);
   1970   is_optimized.If<HCompareObjectEqAndBranch>(optimized_map, null_constant);
   1971   is_optimized.Then();
   1972   {
   1973     BuildInstallCode(js_function, shared_info);
   1974   }
   1975   is_optimized.Else();
   1976   {
   1977     AddIncrementCounter(counters->fast_new_closure_try_optimized());
   1978     // The {optimized_map} points to fixed array of 4-element entries:
   1979     //   (native context, optimized code, literals, ast-id).
   1980     // Iterate through the {optimized_map} backwards. After the loop, if no
   1981     // matching optimized code was found, install unoptimized code.
   1982     //   for(i = map.length() - SharedFunctionInfo::kEntryLength;
   1983     //       i >= SharedFunctionInfo::kEntriesStart;
   1984     //       i -= SharedFunctionInfo::kEntryLength) { ... }
   1985     HValue* first_entry_index =
   1986         Add<HConstant>(SharedFunctionInfo::kEntriesStart);
   1987     HValue* shared_function_entry_length =
   1988         Add<HConstant>(SharedFunctionInfo::kEntryLength);
   1989     LoopBuilder loop_builder(this, context(), LoopBuilder::kPostDecrement,
   1990                              shared_function_entry_length);
   1991     HValue* array_length = Add<HLoadNamedField>(
   1992         optimized_map, nullptr, HObjectAccess::ForFixedArrayLength());
   1993     HValue* start_pos =
   1994         AddUncasted<HSub>(array_length, shared_function_entry_length);
   1995     HValue* slot_iterator =
   1996         loop_builder.BeginBody(start_pos, first_entry_index, Token::GTE);
   1997     {
   1998       IfBuilder done_check(this);
   1999       BuildCheckAndInstallOptimizedCode(js_function, native_context,
   2000                                         &done_check, optimized_map,
   2001                                         slot_iterator);
   2002       // Fall out of the loop
   2003       loop_builder.Break();
   2004     }
   2005     loop_builder.EndBody();
   2006 
   2007     // If {slot_iterator} is less than the first entry index, then we failed to
   2008     // find a context-dependent code and try context-independent code next.
   2009     IfBuilder no_optimized_code_check(this);
   2010     no_optimized_code_check.If<HCompareNumericAndBranch>(
   2011         slot_iterator, first_entry_index, Token::LT);
   2012     no_optimized_code_check.Then();
   2013     {
   2014       IfBuilder shared_code_check(this);
   2015       HValue* shared_code =
   2016           Add<HLoadNamedField>(optimized_map, nullptr,
   2017                                HObjectAccess::ForOptimizedCodeMapSharedCode());
   2018       shared_code = Add<HLoadNamedField>(shared_code, nullptr,
   2019                                          HObjectAccess::ForWeakCellValue());
   2020       shared_code_check.IfNot<HCompareObjectEqAndBranch>(
   2021           shared_code, graph()->GetConstant0());
   2022       shared_code_check.Then();
   2023       {
   2024         // Store the context-independent optimized code.
   2025         HValue* literals = Add<HConstant>(factory->empty_fixed_array());
   2026         BuildInstallOptimizedCode(js_function, native_context, shared_code,
   2027                                   literals);
   2028       }
   2029       shared_code_check.Else();
   2030       {
   2031         // Store the unoptimized code.
   2032         BuildInstallCode(js_function, shared_info);
   2033       }
   2034     }
   2035   }
   2036 }
   2037 
   2038 
   2039 template<>
   2040 HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() {
   2041   Counters* counters = isolate()->counters();
   2042   Factory* factory = isolate()->factory();
   2043   HInstruction* empty_fixed_array =
   2044       Add<HConstant>(factory->empty_fixed_array());
   2045   HValue* shared_info = GetParameter(0);
   2046 
   2047   AddIncrementCounter(counters->fast_new_closure_total());
   2048 
   2049   // Create a new closure from the given function info in new space
   2050   HValue* size = Add<HConstant>(JSFunction::kSize);
   2051   HInstruction* js_function =
   2052       Add<HAllocate>(size, HType::JSObject(), NOT_TENURED, JS_FUNCTION_TYPE);
   2053 
   2054   int map_index = Context::FunctionMapIndex(casted_stub()->language_mode(),
   2055                                             casted_stub()->kind());
   2056 
   2057   // Compute the function map in the current native context and set that
   2058   // as the map of the allocated object.
   2059   HInstruction* native_context = BuildGetNativeContext();
   2060   HInstruction* map_slot_value = Add<HLoadNamedField>(
   2061       native_context, nullptr, HObjectAccess::ForContextSlot(map_index));
   2062   Add<HStoreNamedField>(js_function, HObjectAccess::ForMap(), map_slot_value);
   2063 
   2064   // Initialize the rest of the function.
   2065   Add<HStoreNamedField>(js_function, HObjectAccess::ForPropertiesPointer(),
   2066                         empty_fixed_array);
   2067   Add<HStoreNamedField>(js_function, HObjectAccess::ForElementsPointer(),
   2068                         empty_fixed_array);
   2069   Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(),
   2070                         empty_fixed_array);
   2071   Add<HStoreNamedField>(js_function, HObjectAccess::ForPrototypeOrInitialMap(),
   2072                         graph()->GetConstantHole());
   2073   Add<HStoreNamedField>(
   2074       js_function, HObjectAccess::ForSharedFunctionInfoPointer(), shared_info);
   2075   Add<HStoreNamedField>(js_function, HObjectAccess::ForFunctionContextPointer(),
   2076                         context());
   2077 
   2078   // Initialize the code pointer in the function to be the one found in the
   2079   // shared function info object. But first check if there is an optimized
   2080   // version for our context.
   2081   BuildInstallFromOptimizedCodeMap(js_function, shared_info, native_context);
   2082 
   2083   return js_function;
   2084 }
   2085 
   2086 
   2087 Handle<Code> FastNewClosureStub::GenerateCode() {
   2088   return DoGenerateCode(this);
   2089 }
   2090 
   2091 
   2092 template<>
   2093 HValue* CodeStubGraphBuilder<FastNewContextStub>::BuildCodeStub() {
   2094   int length = casted_stub()->slots() + Context::MIN_CONTEXT_SLOTS;
   2095 
   2096   // Get the function.
   2097   HParameter* function = GetParameter(FastNewContextStub::kFunction);
   2098 
   2099   // Allocate the context in new space.
   2100   HAllocate* function_context = Add<HAllocate>(
   2101       Add<HConstant>(length * kPointerSize + FixedArray::kHeaderSize),
   2102       HType::HeapObject(), NOT_TENURED, FIXED_ARRAY_TYPE);
   2103 
   2104   // Set up the object header.
   2105   AddStoreMapConstant(function_context,
   2106                       isolate()->factory()->function_context_map());
   2107   Add<HStoreNamedField>(function_context,
   2108                         HObjectAccess::ForFixedArrayLength(),
   2109                         Add<HConstant>(length));
   2110 
   2111   // Set up the fixed slots.
   2112   Add<HStoreNamedField>(function_context,
   2113                         HObjectAccess::ForContextSlot(Context::CLOSURE_INDEX),
   2114                         function);
   2115   Add<HStoreNamedField>(function_context,
   2116                         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX),
   2117                         context());
   2118   Add<HStoreNamedField>(function_context,
   2119                         HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX),
   2120                         graph()->GetConstantHole());
   2121 
   2122   // Copy the native context from the previous context.
   2123   HValue* native_context = Add<HLoadNamedField>(
   2124       context(), nullptr,
   2125       HObjectAccess::ForContextSlot(Context::NATIVE_CONTEXT_INDEX));
   2126   Add<HStoreNamedField>(function_context, HObjectAccess::ForContextSlot(
   2127                                               Context::NATIVE_CONTEXT_INDEX),
   2128                         native_context);
   2129 
   2130   // Initialize the rest of the slots to undefined.
   2131   for (int i = Context::MIN_CONTEXT_SLOTS; i < length; ++i) {
   2132     Add<HStoreNamedField>(function_context,
   2133                           HObjectAccess::ForContextSlot(i),
   2134                           graph()->GetConstantUndefined());
   2135   }
   2136 
   2137   return function_context;
   2138 }
   2139 
   2140 
   2141 Handle<Code> FastNewContextStub::GenerateCode() {
   2142   return DoGenerateCode(this);
   2143 }
   2144 
   2145 
   2146 template <>
   2147 HValue* CodeStubGraphBuilder<LoadDictionaryElementStub>::BuildCodeStub() {
   2148   HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex);
   2149   HValue* key = GetParameter(LoadDescriptor::kNameIndex);
   2150 
   2151   Add<HCheckSmi>(key);
   2152 
   2153   HValue* elements = AddLoadElements(receiver);
   2154 
   2155   HValue* hash = BuildElementIndexHash(key);
   2156 
   2157   return BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash,
   2158                                              casted_stub()->language_mode());
   2159 }
   2160 
   2161 
   2162 Handle<Code> LoadDictionaryElementStub::GenerateCode() {
   2163   return DoGenerateCode(this);
   2164 }
   2165 
   2166 
   2167 template<>
   2168 HValue* CodeStubGraphBuilder<RegExpConstructResultStub>::BuildCodeStub() {
   2169   // Determine the parameters.
   2170   HValue* length = GetParameter(RegExpConstructResultStub::kLength);
   2171   HValue* index = GetParameter(RegExpConstructResultStub::kIndex);
   2172   HValue* input = GetParameter(RegExpConstructResultStub::kInput);
   2173 
   2174   info()->MarkMustNotHaveEagerFrame();
   2175 
   2176   return BuildRegExpConstructResult(length, index, input);
   2177 }
   2178 
   2179 
   2180 Handle<Code> RegExpConstructResultStub::GenerateCode() {
   2181   return DoGenerateCode(this);
   2182 }
   2183 
   2184 
   2185 template <>
   2186 class CodeStubGraphBuilder<KeyedLoadGenericStub>
   2187     : public CodeStubGraphBuilderBase {
   2188  public:
   2189   explicit CodeStubGraphBuilder(CompilationInfo* info)
   2190       : CodeStubGraphBuilderBase(info) {}
   2191 
   2192  protected:
   2193   virtual HValue* BuildCodeStub();
   2194 
   2195   void BuildElementsKindLimitCheck(HGraphBuilder::IfBuilder* if_builder,
   2196                                    HValue* bit_field2,
   2197                                    ElementsKind kind);
   2198 
   2199   void BuildFastElementLoad(HGraphBuilder::IfBuilder* if_builder,
   2200                             HValue* receiver,
   2201                             HValue* key,
   2202                             HValue* instance_type,
   2203                             HValue* bit_field2,
   2204                             ElementsKind kind);
   2205 
   2206   KeyedLoadGenericStub* casted_stub() {
   2207     return static_cast<KeyedLoadGenericStub*>(stub());
   2208   }
   2209 };
   2210 
   2211 
   2212 void CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildElementsKindLimitCheck(
   2213     HGraphBuilder::IfBuilder* if_builder, HValue* bit_field2,
   2214     ElementsKind kind) {
   2215   ElementsKind next_kind = static_cast<ElementsKind>(kind + 1);
   2216   HValue* kind_limit = Add<HConstant>(
   2217       static_cast<int>(Map::ElementsKindBits::encode(next_kind)));
   2218 
   2219   if_builder->If<HCompareNumericAndBranch>(bit_field2, kind_limit, Token::LT);
   2220   if_builder->Then();
   2221 }
   2222 
   2223 
   2224 void CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildFastElementLoad(
   2225     HGraphBuilder::IfBuilder* if_builder, HValue* receiver, HValue* key,
   2226     HValue* instance_type, HValue* bit_field2, ElementsKind kind) {
   2227   BuildElementsKindLimitCheck(if_builder, bit_field2, kind);
   2228 
   2229   IfBuilder js_array_check(this);
   2230   js_array_check.If<HCompareNumericAndBranch>(
   2231       instance_type, Add<HConstant>(JS_ARRAY_TYPE), Token::EQ);
   2232   js_array_check.Then();
   2233   Push(BuildUncheckedMonomorphicElementAccess(receiver, key, NULL,
   2234                                               true, kind,
   2235                                               LOAD, NEVER_RETURN_HOLE,
   2236                                               STANDARD_STORE));
   2237   js_array_check.Else();
   2238   Push(BuildUncheckedMonomorphicElementAccess(receiver, key, NULL,
   2239                                               false, kind,
   2240                                               LOAD, NEVER_RETURN_HOLE,
   2241                                               STANDARD_STORE));
   2242   js_array_check.End();
   2243 }
   2244 
   2245 
   2246 HValue* CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildCodeStub() {
   2247   HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex);
   2248   HValue* key = GetParameter(LoadDescriptor::kNameIndex);
   2249   // Split into a smi/integer case and unique string case.
   2250   HIfContinuation index_name_split_continuation(graph()->CreateBasicBlock(),
   2251                                                 graph()->CreateBasicBlock());
   2252 
   2253   BuildKeyedIndexCheck(key, &index_name_split_continuation);
   2254 
   2255   IfBuilder index_name_split(this, &index_name_split_continuation);
   2256   index_name_split.Then();
   2257   {
   2258     // Key is an index (number)
   2259     key = Pop();
   2260 
   2261     int bit_field_mask = (1 << Map::kIsAccessCheckNeeded) |
   2262       (1 << Map::kHasIndexedInterceptor);
   2263     BuildJSObjectCheck(receiver, bit_field_mask);
   2264 
   2265     HValue* map =
   2266         Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
   2267 
   2268     HValue* instance_type =
   2269         Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
   2270 
   2271     HValue* bit_field2 =
   2272         Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2());
   2273 
   2274     IfBuilder kind_if(this);
   2275     BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
   2276                          FAST_HOLEY_ELEMENTS);
   2277 
   2278     kind_if.Else();
   2279     {
   2280       BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
   2281                            FAST_HOLEY_DOUBLE_ELEMENTS);
   2282     }
   2283     kind_if.Else();
   2284 
   2285     // The DICTIONARY_ELEMENTS check generates a "kind_if.Then"
   2286     BuildElementsKindLimitCheck(&kind_if, bit_field2, DICTIONARY_ELEMENTS);
   2287     {
   2288       HValue* elements = AddLoadElements(receiver);
   2289 
   2290       HValue* hash = BuildElementIndexHash(key);
   2291 
   2292       Push(BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash,
   2293                                                casted_stub()->language_mode()));
   2294     }
   2295     kind_if.Else();
   2296 
   2297     // The SLOW_SLOPPY_ARGUMENTS_ELEMENTS check generates a "kind_if.Then"
   2298     STATIC_ASSERT(FAST_SLOPPY_ARGUMENTS_ELEMENTS <
   2299                   SLOW_SLOPPY_ARGUMENTS_ELEMENTS);
   2300     BuildElementsKindLimitCheck(&kind_if, bit_field2,
   2301                                 SLOW_SLOPPY_ARGUMENTS_ELEMENTS);
   2302     // Non-strict elements are not handled.
   2303     Add<HDeoptimize>(Deoptimizer::kNonStrictElementsInKeyedLoadGenericStub,
   2304                      Deoptimizer::EAGER);
   2305     Push(graph()->GetConstant0());
   2306 
   2307     kind_if.ElseDeopt(
   2308         Deoptimizer::kElementsKindUnhandledInKeyedLoadGenericStub);
   2309 
   2310     kind_if.End();
   2311   }
   2312   index_name_split.Else();
   2313   {
   2314     // Key is a unique string.
   2315     key = Pop();
   2316 
   2317     int bit_field_mask = (1 << Map::kIsAccessCheckNeeded) |
   2318         (1 << Map::kHasNamedInterceptor);
   2319     BuildJSObjectCheck(receiver, bit_field_mask);
   2320 
   2321     HIfContinuation continuation;
   2322     BuildTestForDictionaryProperties(receiver, &continuation);
   2323     IfBuilder if_dict_properties(this, &continuation);
   2324     if_dict_properties.Then();
   2325     {
   2326       //  Key is string, properties are dictionary mode
   2327       BuildNonGlobalObjectCheck(receiver);
   2328 
   2329       HValue* properties = Add<HLoadNamedField>(
   2330           receiver, nullptr, HObjectAccess::ForPropertiesPointer());
   2331 
   2332       HValue* hash =
   2333           Add<HLoadNamedField>(key, nullptr, HObjectAccess::ForNameHashField());
   2334 
   2335       hash = AddUncasted<HShr>(hash, Add<HConstant>(Name::kHashShift));
   2336 
   2337       HValue* value = BuildUncheckedDictionaryElementLoad(
   2338           receiver, properties, key, hash, casted_stub()->language_mode());
   2339       Push(value);
   2340     }
   2341     if_dict_properties.Else();
   2342     {
   2343       // TODO(dcarney): don't use keyed lookup cache, but convert to use
   2344       // megamorphic stub cache.
   2345       UNREACHABLE();
   2346       //  Key is string, properties are fast mode
   2347       HValue* hash = BuildKeyedLookupCacheHash(receiver, key);
   2348 
   2349       ExternalReference cache_keys_ref =
   2350           ExternalReference::keyed_lookup_cache_keys(isolate());
   2351       HValue* cache_keys = Add<HConstant>(cache_keys_ref);
   2352 
   2353       HValue* map =
   2354           Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
   2355       HValue* base_index = AddUncasted<HMul>(hash, Add<HConstant>(2));
   2356       base_index->ClearFlag(HValue::kCanOverflow);
   2357 
   2358       HIfContinuation inline_or_runtime_continuation(
   2359           graph()->CreateBasicBlock(), graph()->CreateBasicBlock());
   2360       {
   2361         IfBuilder lookup_ifs[KeyedLookupCache::kEntriesPerBucket];
   2362         for (int probe = 0; probe < KeyedLookupCache::kEntriesPerBucket;
   2363              ++probe) {
   2364           IfBuilder* lookup_if = &lookup_ifs[probe];
   2365           lookup_if->Initialize(this);
   2366           int probe_base = probe * KeyedLookupCache::kEntryLength;
   2367           HValue* map_index = AddUncasted<HAdd>(
   2368               base_index,
   2369               Add<HConstant>(probe_base + KeyedLookupCache::kMapIndex));
   2370           map_index->ClearFlag(HValue::kCanOverflow);
   2371           HValue* key_index = AddUncasted<HAdd>(
   2372               base_index,
   2373               Add<HConstant>(probe_base + KeyedLookupCache::kKeyIndex));
   2374           key_index->ClearFlag(HValue::kCanOverflow);
   2375           HValue* map_to_check =
   2376               Add<HLoadKeyed>(cache_keys, map_index, nullptr, nullptr,
   2377                               FAST_ELEMENTS, NEVER_RETURN_HOLE, 0);
   2378           lookup_if->If<HCompareObjectEqAndBranch>(map_to_check, map);
   2379           lookup_if->And();
   2380           HValue* key_to_check =
   2381               Add<HLoadKeyed>(cache_keys, key_index, nullptr, nullptr,
   2382                               FAST_ELEMENTS, NEVER_RETURN_HOLE, 0);
   2383           lookup_if->If<HCompareObjectEqAndBranch>(key_to_check, key);
   2384           lookup_if->Then();
   2385           {
   2386             ExternalReference cache_field_offsets_ref =
   2387                 ExternalReference::keyed_lookup_cache_field_offsets(isolate());
   2388             HValue* cache_field_offsets =
   2389                 Add<HConstant>(cache_field_offsets_ref);
   2390             HValue* index = AddUncasted<HAdd>(hash, Add<HConstant>(probe));
   2391             index->ClearFlag(HValue::kCanOverflow);
   2392             HValue* property_index =
   2393                 Add<HLoadKeyed>(cache_field_offsets, index, nullptr, cache_keys,
   2394                                 INT32_ELEMENTS, NEVER_RETURN_HOLE, 0);
   2395             Push(property_index);
   2396           }
   2397           lookup_if->Else();
   2398         }
   2399         for (int i = 0; i < KeyedLookupCache::kEntriesPerBucket; ++i) {
   2400           lookup_ifs[i].JoinContinuation(&inline_or_runtime_continuation);
   2401         }
   2402       }
   2403 
   2404       IfBuilder inline_or_runtime(this, &inline_or_runtime_continuation);
   2405       inline_or_runtime.Then();
   2406       {
   2407         // Found a cached index, load property inline.
   2408         Push(Add<HLoadFieldByIndex>(receiver, Pop()));
   2409       }
   2410       inline_or_runtime.Else();
   2411       {
   2412         // KeyedLookupCache miss; call runtime.
   2413         Add<HPushArguments>(receiver, key);
   2414         Push(Add<HCallRuntime>(
   2415             Runtime::FunctionForId(is_strong(casted_stub()->language_mode())
   2416                                        ? Runtime::kKeyedGetPropertyStrong
   2417                                        : Runtime::kKeyedGetProperty),
   2418             2));
   2419       }
   2420       inline_or_runtime.End();
   2421     }
   2422     if_dict_properties.End();
   2423   }
   2424   index_name_split.End();
   2425 
   2426   return Pop();
   2427 }
   2428 
   2429 
   2430 Handle<Code> KeyedLoadGenericStub::GenerateCode() {
   2431   return DoGenerateCode(this);
   2432 }
   2433 
   2434 }  // namespace internal
   2435 }  // namespace v8
   2436