1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/code-stubs.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include <memory> 8f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/bailout-reason.h" 10f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/code-factory.h" 11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/crankshaft/hydrogen.h" 12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/crankshaft/lithium.h" 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/field-index.h" 14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/ic/ic.h" 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic LChunk* OptimizeGraph(HGraph* graph) { 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DisallowHeapAllocation no_allocation; 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DisallowHandleAllocation no_handles; 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DisallowHandleDereference no_deref; 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(graph != NULL); 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BailoutReason bailout_reason = kNoReason; 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!graph->Optimize(&bailout_reason)) { 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FATAL(GetBailoutReason(bailout_reason)); 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LChunk* chunk = LChunk::NewChunk(graph); 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (chunk == NULL) { 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FATAL(GetBailoutReason(graph->info()->bailout_reason())); 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return chunk; 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass CodeStubGraphBuilderBase : public HGraphBuilder { 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 40109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch explicit CodeStubGraphBuilderBase(CompilationInfo* info, CodeStub* code_stub) 41f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch : HGraphBuilder(info, code_stub->GetCallInterfaceDescriptor(), false), 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch arguments_length_(NULL), 43958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier info_(info), 44109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch code_stub_(code_stub), 45109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch descriptor_(code_stub), 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context_(NULL) { 47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int parameter_count = GetParameterCount(); 48f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch parameters_.reset(new HParameter*[parameter_count]); 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual bool BuildGraph(); 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch protected: 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual HValue* BuildCodeStub() = 0; 54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int GetParameterCount() const { return descriptor_.GetParameterCount(); } 55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int GetRegisterParameterCount() const { 56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return descriptor_.GetRegisterParameterCount(); 57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HParameter* GetParameter(int parameter) { 59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(parameter < GetParameterCount()); 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return parameters_[parameter]; 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Representation GetParameterRepresentation(int parameter) { 63f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return RepresentationFromMachineType( 64f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch descriptor_.GetParameterType(parameter)); 65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool IsParameterCountRegister(int index) const { 67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return descriptor_.GetRegisterParameter(index) 68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch .is(descriptor_.stack_parameter_count()); 69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HValue* GetArgumentsLength() { 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is initialized in BuildGraph() 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(arguments_length_ != NULL); 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return arguments_length_; 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 75958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CompilationInfo* info() { return info_; } 76109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CodeStub* stub() { return code_stub_; } 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HContext* context() { return context_; } 78958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Isolate* isolate() { return info_->isolate(); } 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HLoadNamedField* BuildLoadNamedField(HValue* object, FieldIndex index); 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void BuildStoreNamedField(HValue* object, HValue* value, FieldIndex index, 82958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Representation representation, 83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool transition_to_field); 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* BuildPushElement(HValue* object, HValue* argc, 863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* argument_elements, ElementsKind kind); 873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HValue* BuildToString(HValue* input, bool convert); 89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HValue* BuildToPrimitive(HValue* input, HValue* input_map); 90958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 92f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch std::unique_ptr<HParameter* []> parameters_; 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HValue* arguments_length_; 94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CompilationInfo* info_; 95109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CodeStub* code_stub_; 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeStubDescriptor descriptor_; 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HContext* context_; 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool CodeStubGraphBuilderBase::BuildGraph() { 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the static counter each time a new code stub is generated. 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->counters()->code_stubs()->Increment(); 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_trace_hydrogen_stubs) { 106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const char* name = CodeStub::MajorName(stub()->MajorKey()); 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("-----------------------------------------------------------\n"); 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("Compiling stub %s using hydrogen\n", name); 109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier isolate()->GetHTracer()->TraceCompilation(info()); 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int param_count = GetParameterCount(); 113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int register_param_count = GetRegisterParameterCount(); 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HEnvironment* start_environment = graph()->start_environment(); 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HBasicBlock* next_block = CreateBasicBlock(start_environment); 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Goto(next_block); 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_block->SetJoinId(BailoutId::StubEntry()); 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch set_current_block(next_block); 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool runtime_stack_params = descriptor_.stack_parameter_count().is_valid(); 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HInstruction* stack_parameter_count = NULL; 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < param_count; ++i) { 123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Representation r = GetParameterRepresentation(i); 124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HParameter* param; 125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (i >= register_param_count) { 126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch param = Add<HParameter>(i - register_param_count, 127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HParameter::STACK_PARAMETER, r); 128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch param = Add<HParameter>(i, HParameter::REGISTER_PARAMETER, r); 130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 131f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch start_environment->Bind(i, param); 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parameters_[i] = param; 133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (i < register_param_count && IsParameterCountRegister(i)) { 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch param->set_type(HType::Smi()); 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stack_parameter_count = param; 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch arguments_length_ = stack_parameter_count; 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!runtime_stack_params || arguments_length_ != NULL); 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!runtime_stack_params) { 142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch stack_parameter_count = 143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Add<HConstant>(param_count - register_param_count - 1); 144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // graph()->GetConstantMinus1(); 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch arguments_length_ = graph()->GetConstant0(); 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context_ = Add<HContext>(); 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch start_environment->BindContext(context_); 150109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch start_environment->Bind(param_count, context_); 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Add<HSimulate>(BailoutId::StubEntry()); 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NoObservableSideEffectsScope no_effects(this); 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HValue* return_value = BuildCodeStub(); 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We might have extra expressions to pop from the stack in addition to the 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // arguments above. 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HInstruction* stack_pop_count = stack_parameter_count; 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (descriptor_.function_mode() == JS_FUNCTION_STUB_MODE) { 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!stack_parameter_count->IsConstant() && 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch descriptor_.hint_stack_parameter_count() < 0) { 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HInstruction* constant_one = graph()->GetConstant1(); 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stack_pop_count = AddUncasted<HAdd>(stack_parameter_count, constant_one); 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stack_pop_count->ClearFlag(HValue::kCanOverflow); 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(mvstanton): verify that stack_parameter_count+1 really fits in a 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // smi. 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int count = descriptor_.hint_stack_parameter_count(); 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stack_pop_count = Add<HConstant>(count); 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (current_block() != NULL) { 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HReturn* hreturn_instruction = New<HReturn>(return_value, 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stack_pop_count); 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FinishCurrentBlock(hreturn_instruction); 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <class Stub> 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass CodeStubGraphBuilder: public CodeStubGraphBuilderBase { 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 187109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch explicit CodeStubGraphBuilder(CompilationInfo* info, CodeStub* stub) 188109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch : CodeStubGraphBuilderBase(info, stub) {} 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 190f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch typedef typename Stub::Descriptor Descriptor; 191f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch protected: 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual HValue* BuildCodeStub() { 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (casted_stub()->IsUninitialized()) { 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return BuildCodeUninitializedStub(); 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return BuildCodeInitializedStub(); 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual HValue* BuildCodeInitializedStub() { 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNIMPLEMENTED(); 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return NULL; 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual HValue* BuildCodeUninitializedStub() { 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Force a deopt that falls back to the runtime. 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HValue* undefined = graph()->GetConstantUndefined(); 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IfBuilder builder(this); 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch builder.IfNot<HCompareObjectEqAndBranch, HValue*>(undefined, undefined); 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch builder.Then(); 212f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch builder.ElseDeopt(DeoptimizeReason::kForcedDeoptToRuntime); 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return undefined; 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Stub* casted_stub() { return static_cast<Stub*>(stub()); } 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> HydrogenCodeStub::GenerateLightweightMissCode( 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference miss) { 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Factory* factory = isolate()->factory(); 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generate the new code. 225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MacroAssembler masm(isolate(), NULL, 256, CodeObjectRequired::kYes); 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the static counter each time a new code stub is generated. 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->counters()->code_stubs()->Increment(); 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generate the code for the stub. 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm.set_generating_stub(true); 233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // TODO(yangguo): remove this once we can serialize IC stubs. 234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm.enable_serializer(); 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NoCurrentFrameScope scope(&masm); 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateLightweightMiss(&masm, miss); 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Create the code object. 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeDesc desc; 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm.GetCode(&desc); 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy the generated code into a heap object. 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> new_object = factory->NewCode( 245109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch desc, GetCodeFlags(), masm.CodeObject(), NeedsImmovableCode()); 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return new_object; 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 249f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochHandle<Code> HydrogenCodeStub::GenerateRuntimeTailCall( 250f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CodeStubDescriptor* descriptor) { 251f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch const char* name = CodeStub::MajorName(MajorKey()); 252c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Zone zone(isolate()->allocator(), ZONE_NAME); 253f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CallInterfaceDescriptor interface_descriptor(GetCallInterfaceDescriptor()); 254f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CodeStubAssembler assembler(isolate(), &zone, interface_descriptor, 255f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GetCodeFlags(), name); 256f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int total_params = interface_descriptor.GetStackParameterCount() + 257f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch interface_descriptor.GetRegisterParameterCount(); 258f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch switch (total_params) { 259f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case 0: 260f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch assembler.TailCallRuntime(descriptor->miss_handler_id(), 261f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch assembler.Parameter(0)); 262f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 263f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case 1: 264f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch assembler.TailCallRuntime(descriptor->miss_handler_id(), 265f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch assembler.Parameter(1), assembler.Parameter(0)); 266f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 267f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case 2: 268f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch assembler.TailCallRuntime(descriptor->miss_handler_id(), 269f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch assembler.Parameter(2), assembler.Parameter(0), 270f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch assembler.Parameter(1)); 271f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 272f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case 3: 273f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch assembler.TailCallRuntime(descriptor->miss_handler_id(), 274f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch assembler.Parameter(3), assembler.Parameter(0), 275f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch assembler.Parameter(1), assembler.Parameter(2)); 276f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 277f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case 4: 278f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch assembler.TailCallRuntime(descriptor->miss_handler_id(), 279f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch assembler.Parameter(4), assembler.Parameter(0), 280f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch assembler.Parameter(1), assembler.Parameter(2), 281f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch assembler.Parameter(3)); 282f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 283f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch default: 284f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNIMPLEMENTED(); 285f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 286f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 287f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return assembler.GenerateCode(); 288f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <class Stub> 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic Handle<Code> DoGenerateCode(Stub* stub) { 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = stub->isolate(); 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeStubDescriptor descriptor(stub); 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 295f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (FLAG_minimal && descriptor.has_miss_handler()) { 296f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return stub->GenerateRuntimeTailCall(&descriptor); 297f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 298f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we are uninitialized we can use a light-weight stub to enter 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the runtime that is significantly faster than using the standard 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // stub-failure deopt mechanism. 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (stub->IsUninitialized() && descriptor.has_miss_handler()) { 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!descriptor.stack_parameter_count().is_valid()); 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return stub->GenerateLightweightMissCode(descriptor.miss_handler()); 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base::ElapsedTimer timer; 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_profile_hydrogen_code_stub_compilation) { 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch timer.Start(); 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 310c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Zone zone(isolate->allocator(), ZONE_NAME); 311bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch CompilationInfo info(CStrVector(CodeStub::MajorName(stub->MajorKey())), 312bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch isolate, &zone, stub->GetCodeFlags()); 313109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Parameter count is number of stack parameters. 314109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int parameter_count = descriptor.GetStackParameterCount(); 315109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (descriptor.function_mode() == NOT_JS_FUNCTION_STUB_MODE) { 316109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch parameter_count--; 317109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 318109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch info.set_parameter_count(parameter_count); 319109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CodeStubGraphBuilder<Stub> builder(&info, stub); 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LChunk* chunk = OptimizeGraph(builder.CreateGraph()); 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> code = chunk->Codegen(); 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_profile_hydrogen_code_stub_compilation) { 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OFStream os(stdout); 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os << "[Lazy compilation of " << stub << " took " 325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier << timer.Elapsed().InMillisecondsF() << " ms]" << std::endl; 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return code; 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochHValue* CodeStubGraphBuilderBase::BuildPushElement(HValue* object, HValue* argc, 3323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* argument_elements, 3333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch ElementsKind kind) { 3343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Precheck whether all elements fit into the array. 3353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (!IsFastObjectElementsKind(kind)) { 3363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); 3373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* start = graph()->GetConstant0(); 3383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* key = builder.BeginBody(start, argc, Token::LT); 3393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 3403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HInstruction* argument = 3413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Add<HAccessArgumentsAt>(argument_elements, argc, key); 3423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch IfBuilder can_store(this); 3433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch can_store.IfNot<HIsSmiAndBranch>(argument); 3443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch if (IsFastDoubleElementsKind(kind)) { 3453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch can_store.And(); 3463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch can_store.IfNot<HCompareMap>(argument, 3473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch isolate()->factory()->heap_number_map()); 3483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 349f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch can_store.ThenDeopt(DeoptimizeReason::kFastPathFailed); 3503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch can_store.End(); 3513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 3523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch builder.EndBody(); 3533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 3543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 3553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* length = Add<HLoadNamedField>(object, nullptr, 3563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HObjectAccess::ForArrayLength(kind)); 3573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* new_length = AddUncasted<HAdd>(length, argc); 3583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* max_key = AddUncasted<HSub>(new_length, graph()->GetConstant1()); 3593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 3603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* elements = Add<HLoadNamedField>(object, nullptr, 3613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HObjectAccess::ForElementsPointer()); 3623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch elements = BuildCheckForCapacityGrow(object, elements, kind, length, max_key, 3633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch true, STORE); 3643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 3653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); 3663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* start = graph()->GetConstant0(); 3673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* key = builder.BeginBody(start, argc, Token::LT); 3683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 3693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* argument = Add<HAccessArgumentsAt>(argument_elements, argc, key); 3703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* index = AddUncasted<HAdd>(key, length); 3713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch AddElementAccess(elements, index, argument, object, nullptr, kind, STORE); 3723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 3733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch builder.EndBody(); 3743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch return new_length; 3753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch} 3763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 3773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochtemplate <> 3783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochHValue* CodeStubGraphBuilder<FastArrayPushStub>::BuildCodeStub() { 3793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // TODO(verwaest): Fix deoptimizer messages. 3803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* argc = GetArgumentsLength(); 381f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 3823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HInstruction* argument_elements = Add<HArgumentsElements>(false, false); 3833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HInstruction* object = Add<HAccessArgumentsAt>(argument_elements, argc, 3843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch graph()->GetConstantMinus1()); 3853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch BuildCheckHeapObject(object); 3863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap()); 3873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Add<HCheckInstanceType>(object, HCheckInstanceType::IS_JS_ARRAY); 3883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 3893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Disallow pushing onto prototypes. It might be the JSArray prototype. 3903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Disallow pushing onto non-extensible objects. 3913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 3923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* bit_field2 = 3933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2()); 3943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* mask = 3953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Add<HConstant>(static_cast<int>(Map::IsPrototypeMapBits::kMask) | 3963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch (1 << Map::kIsExtensible)); 3973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* bits = AddUncasted<HBitwise>(Token::BIT_AND, bit_field2, mask); 3983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch IfBuilder check(this); 3993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch check.If<HCompareNumericAndBranch>( 4003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch bits, Add<HConstant>(1 << Map::kIsExtensible), Token::NE); 401f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch check.ThenDeopt(DeoptimizeReason::kFastPathFailed); 4023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch check.End(); 4033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 4043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 4053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Disallow pushing onto arrays in dictionary named property mode. We need to 4063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // figure out whether the length property is still writable. 4073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 4083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* bit_field3 = 4093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3()); 4103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* mask = Add<HConstant>(static_cast<int>(Map::DictionaryMap::kMask)); 4113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, bit_field3, mask); 4123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch IfBuilder check(this); 4133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch check.If<HCompareNumericAndBranch>(bit, mask, Token::EQ); 414f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch check.ThenDeopt(DeoptimizeReason::kFastPathFailed); 4153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch check.End(); 4163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 4173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 4183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Check whether the length property is writable. The length property is the 4193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // only default named property on arrays. It's nonconfigurable, hence is 4203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // guaranteed to stay the first property. 4213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 4223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* descriptors = 4233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapDescriptors()); 4243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* details = Add<HLoadKeyed>( 4253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch descriptors, Add<HConstant>(DescriptorArray::ToDetailsIndex(0)), 4263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch nullptr, nullptr, FAST_SMI_ELEMENTS); 4273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* mask = 4283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Add<HConstant>(READ_ONLY << PropertyDetails::AttributesField::kShift); 4293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, details, mask); 4303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch IfBuilder readonly(this); 4313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch readonly.If<HCompareNumericAndBranch>(bit, mask, Token::EQ); 432f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch readonly.ThenDeopt(DeoptimizeReason::kFastPathFailed); 4333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch readonly.End(); 4343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 4353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 4363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* null = Add<HLoadRoot>(Heap::kNullValueRootIndex); 4373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* empty = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex); 4383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch environment()->Push(map); 4393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch LoopBuilder check_prototypes(this); 4403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch check_prototypes.BeginBody(1); 4413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 4423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* parent_map = environment()->Pop(); 4433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* prototype = Add<HLoadNamedField>(parent_map, nullptr, 4443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HObjectAccess::ForPrototype()); 4453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 4463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch IfBuilder is_null(this); 4473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch is_null.If<HCompareObjectEqAndBranch>(prototype, null); 4483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch is_null.Then(); 4493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch check_prototypes.Break(); 4503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch is_null.End(); 4513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 4523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* prototype_map = 4533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Add<HLoadNamedField>(prototype, nullptr, HObjectAccess::ForMap()); 4543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* instance_type = Add<HLoadNamedField>( 4553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch prototype_map, nullptr, HObjectAccess::ForMapInstanceType()); 4563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch IfBuilder check_instance_type(this); 4573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch check_instance_type.If<HCompareNumericAndBranch>( 4583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch instance_type, Add<HConstant>(LAST_CUSTOM_ELEMENTS_RECEIVER), 4593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Token::LTE); 460f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch check_instance_type.ThenDeopt(DeoptimizeReason::kFastPathFailed); 4613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch check_instance_type.End(); 4623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 4633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* elements = Add<HLoadNamedField>( 4643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch prototype, nullptr, HObjectAccess::ForElementsPointer()); 4653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch IfBuilder no_elements(this); 4663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch no_elements.IfNot<HCompareObjectEqAndBranch>(elements, empty); 467f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch no_elements.ThenDeopt(DeoptimizeReason::kFastPathFailed); 4683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch no_elements.End(); 4693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 4703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch environment()->Push(prototype_map); 4713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 4723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch check_prototypes.EndBody(); 4733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 4743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* bit_field2 = 4753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2()); 4763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* kind = BuildDecodeField<Map::ElementsKindBits>(bit_field2); 4773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 4783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Below we only check the upper bound of the relevant ranges to include both 4793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // holey and non-holey versions. We check them in order smi, object, double 4803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // since smi < object < double. 4813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch STATIC_ASSERT(FAST_SMI_ELEMENTS < FAST_HOLEY_SMI_ELEMENTS); 4823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS < FAST_HOLEY_ELEMENTS); 4833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch STATIC_ASSERT(FAST_ELEMENTS < FAST_HOLEY_ELEMENTS); 4843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch STATIC_ASSERT(FAST_HOLEY_ELEMENTS < FAST_HOLEY_DOUBLE_ELEMENTS); 4853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FAST_HOLEY_DOUBLE_ELEMENTS); 4863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch IfBuilder has_smi_elements(this); 4873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch has_smi_elements.If<HCompareNumericAndBranch>( 4883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch kind, Add<HConstant>(FAST_HOLEY_SMI_ELEMENTS), Token::LTE); 4893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch has_smi_elements.Then(); 4903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 4913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* new_length = BuildPushElement(object, argc, argument_elements, 4923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch FAST_HOLEY_SMI_ELEMENTS); 4933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch environment()->Push(new_length); 4943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 4953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch has_smi_elements.Else(); 4963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 4973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch IfBuilder has_object_elements(this); 4983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch has_object_elements.If<HCompareNumericAndBranch>( 4993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch kind, Add<HConstant>(FAST_HOLEY_ELEMENTS), Token::LTE); 5003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch has_object_elements.Then(); 5013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 5023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* new_length = BuildPushElement(object, argc, argument_elements, 5033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch FAST_HOLEY_ELEMENTS); 5043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch environment()->Push(new_length); 5053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 5063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch has_object_elements.Else(); 5073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 5083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch IfBuilder has_double_elements(this); 5093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch has_double_elements.If<HCompareNumericAndBranch>( 5103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch kind, Add<HConstant>(FAST_HOLEY_DOUBLE_ELEMENTS), Token::LTE); 5113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch has_double_elements.Then(); 5123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 5133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch HValue* new_length = BuildPushElement(object, argc, argument_elements, 5143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch FAST_HOLEY_DOUBLE_ELEMENTS); 5153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch environment()->Push(new_length); 5163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 517f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch has_double_elements.ElseDeopt(DeoptimizeReason::kFastPathFailed); 5183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch has_double_elements.End(); 5193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 5203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch has_object_elements.End(); 5213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 5223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch has_smi_elements.End(); 5233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 5243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch return environment()->Pop(); 5253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch} 5263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 5273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochHandle<Code> FastArrayPushStub::GenerateCode() { return DoGenerateCode(this); } 528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <> 53013e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochHValue* CodeStubGraphBuilder<FastFunctionBindStub>::BuildCodeStub() { 53113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // TODO(verwaest): Fix deoptimizer messages. 53213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* argc = GetArgumentsLength(); 53313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HInstruction* argument_elements = Add<HArgumentsElements>(false, false); 53413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HInstruction* object = Add<HAccessArgumentsAt>(argument_elements, argc, 53513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch graph()->GetConstantMinus1()); 53613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch BuildCheckHeapObject(object); 53713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap()); 53813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Add<HCheckInstanceType>(object, HCheckInstanceType::IS_JS_FUNCTION); 53913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 54013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Disallow binding of slow-mode functions. We need to figure out whether the 54113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // length and name property are in the original state. 54213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 54313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* bit_field3 = 54413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3()); 54513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* mask = Add<HConstant>(static_cast<int>(Map::DictionaryMap::kMask)); 54613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, bit_field3, mask); 54713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch IfBuilder check(this); 54813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch check.If<HCompareNumericAndBranch>(bit, mask, Token::EQ); 549f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch check.ThenDeopt(DeoptimizeReason::kFastPathFailed); 55013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch check.End(); 55113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 55213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 55313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Check whether the length and name properties are still present as 55413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // AccessorInfo objects. In that case, their value can be recomputed even if 55513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // the actual value on the object changes. 55613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 55713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* descriptors = 55813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapDescriptors()); 55913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 56013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* descriptors_length = Add<HLoadNamedField>( 56113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch descriptors, nullptr, HObjectAccess::ForFixedArrayLength()); 56213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch IfBuilder range(this); 56313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch range.If<HCompareNumericAndBranch>(descriptors_length, 56413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch graph()->GetConstant1(), Token::LTE); 565f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch range.ThenDeopt(DeoptimizeReason::kFastPathFailed); 56613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch range.End(); 56713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 56813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Verify .length. 56913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch const int length_index = JSFunction::kLengthDescriptorIndex; 57013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* maybe_length = Add<HLoadKeyed>( 57113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch descriptors, Add<HConstant>(DescriptorArray::ToKeyIndex(length_index)), 57213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch nullptr, nullptr, FAST_ELEMENTS); 57313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Unique<Name> length_string = Unique<Name>::CreateUninitialized( 57413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch isolate()->factory()->length_string()); 57513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Add<HCheckValue>(maybe_length, length_string, false); 57613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 57713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* maybe_length_accessor = Add<HLoadKeyed>( 57813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch descriptors, 57913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Add<HConstant>(DescriptorArray::ToValueIndex(length_index)), nullptr, 58013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch nullptr, FAST_ELEMENTS); 58113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch BuildCheckHeapObject(maybe_length_accessor); 58213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Add<HCheckMaps>(maybe_length_accessor, 58313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch isolate()->factory()->accessor_info_map()); 58413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 58513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Verify .name. 58613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch const int name_index = JSFunction::kNameDescriptorIndex; 58713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* maybe_name = Add<HLoadKeyed>( 58813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch descriptors, Add<HConstant>(DescriptorArray::ToKeyIndex(name_index)), 58913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch nullptr, nullptr, FAST_ELEMENTS); 59013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Unique<Name> name_string = 59113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Unique<Name>::CreateUninitialized(isolate()->factory()->name_string()); 59213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Add<HCheckValue>(maybe_name, name_string, false); 59313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 59413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* maybe_name_accessor = Add<HLoadKeyed>( 59513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch descriptors, Add<HConstant>(DescriptorArray::ToValueIndex(name_index)), 59613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch nullptr, nullptr, FAST_ELEMENTS); 59713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch BuildCheckHeapObject(maybe_name_accessor); 59813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Add<HCheckMaps>(maybe_name_accessor, 59913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch isolate()->factory()->accessor_info_map()); 60013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 60113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 60213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Choose the right bound function map based on whether the target is 60313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // constructable. 60413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 60513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* bit_field = 60613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField()); 60713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* mask = Add<HConstant>(static_cast<int>(1 << Map::kIsConstructor)); 60813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* bits = AddUncasted<HBitwise>(Token::BIT_AND, bit_field, mask); 60913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 61013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* native_context = BuildGetNativeContext(); 61113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch IfBuilder is_constructor(this); 61213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch is_constructor.If<HCompareNumericAndBranch>(bits, mask, Token::EQ); 61313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch is_constructor.Then(); 61413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 61513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* map = Add<HLoadNamedField>( 61613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch native_context, nullptr, 61713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HObjectAccess::ForContextSlot( 61813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Context::BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX)); 61913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch environment()->Push(map); 62013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 62113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch is_constructor.Else(); 62213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 62313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* map = Add<HLoadNamedField>( 62413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch native_context, nullptr, 62513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HObjectAccess::ForContextSlot( 62613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Context::BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX)); 62713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch environment()->Push(map); 62813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 62913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch is_constructor.End(); 63013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 63113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* bound_function_map = environment()->Pop(); 63213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 63313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Verify that __proto__ matches that of a the target bound function. 63413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 63513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* prototype = 63613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForPrototype()); 63713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* expected_prototype = Add<HLoadNamedField>( 63813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch bound_function_map, nullptr, HObjectAccess::ForPrototype()); 63913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch IfBuilder equal_prototype(this); 64013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch equal_prototype.IfNot<HCompareObjectEqAndBranch>(prototype, 64113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch expected_prototype); 642f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch equal_prototype.ThenDeopt(DeoptimizeReason::kFastPathFailed); 64313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch equal_prototype.End(); 64413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 64513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 64613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Allocate the arguments array. 64713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch IfBuilder empty_args(this); 64813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch empty_args.If<HCompareNumericAndBranch>(argc, graph()->GetConstant1(), 64913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Token::LTE); 65013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch empty_args.Then(); 65113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { environment()->Push(Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex)); } 65213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch empty_args.Else(); 65313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 65413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* elements_length = AddUncasted<HSub>(argc, graph()->GetConstant1()); 65513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* elements = 65613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch BuildAllocateAndInitializeArray(FAST_ELEMENTS, elements_length); 65713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 65813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); 65913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* start = graph()->GetConstant1(); 66013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* key = builder.BeginBody(start, argc, Token::LT); 66113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 66213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* argument = Add<HAccessArgumentsAt>(argument_elements, argc, key); 66313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* index = AddUncasted<HSub>(key, graph()->GetConstant1()); 66413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch AddElementAccess(elements, index, argument, elements, nullptr, 66513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch FAST_ELEMENTS, STORE); 66613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 66713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch builder.EndBody(); 66813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch environment()->Push(elements); 66913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 67013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch empty_args.End(); 67113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* elements = environment()->Pop(); 67213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 67313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Find the 'this' to bind. 67413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch IfBuilder no_receiver(this); 67513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch no_receiver.If<HCompareNumericAndBranch>(argc, graph()->GetConstant0(), 67613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Token::EQ); 67713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch no_receiver.Then(); 67813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { environment()->Push(Add<HLoadRoot>(Heap::kUndefinedValueRootIndex)); } 67913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch no_receiver.Else(); 68013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 68113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch environment()->Push(Add<HAccessArgumentsAt>(argument_elements, argc, 68213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch graph()->GetConstant0())); 68313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 68413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch no_receiver.End(); 68513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* receiver = environment()->Pop(); 68613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 68713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Allocate the resulting bound function. 68813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* size = Add<HConstant>(JSBoundFunction::kSize); 68913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* bound_function = 69013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Add<HAllocate>(size, HType::JSObject(), NOT_TENURED, 69113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch JS_BOUND_FUNCTION_TYPE, graph()->GetConstant0()); 69213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Add<HStoreNamedField>(bound_function, HObjectAccess::ForMap(), 69313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch bound_function_map); 69413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex); 69513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Add<HStoreNamedField>(bound_function, HObjectAccess::ForPropertiesPointer(), 69613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch empty_fixed_array); 69713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Add<HStoreNamedField>(bound_function, HObjectAccess::ForElementsPointer(), 69813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch empty_fixed_array); 69913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Add<HStoreNamedField>(bound_function, HObjectAccess::ForBoundTargetFunction(), 70013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch object); 70113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 70213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Add<HStoreNamedField>(bound_function, HObjectAccess::ForBoundThis(), 70313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch receiver); 70413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Add<HStoreNamedField>(bound_function, HObjectAccess::ForBoundArguments(), 70513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch elements); 70613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 70713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return bound_function; 70813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 70913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 71013e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochHandle<Code> FastFunctionBindStub::GenerateCode() { 71113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return DoGenerateCode(this); 71213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 71313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 71413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtemplate <> 715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHValue* CodeStubGraphBuilder<LoadFastElementStub>::BuildCodeStub() { 716014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LoadKeyedHoleMode hole_mode = casted_stub()->convert_hole_to_undefined() 717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ? CONVERT_HOLE_TO_UNDEFINED 718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch : NEVER_RETURN_HOLE; 719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HInstruction* load = BuildUncheckedMonomorphicElementAccess( 721f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GetParameter(Descriptor::kReceiver), GetParameter(Descriptor::kName), 722f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch NULL, casted_stub()->is_js_array(), casted_stub()->elements_kind(), LOAD, 723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch hole_mode, STANDARD_STORE); 724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return load; 725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> LoadFastElementStub::GenerateCode() { 729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return DoGenerateCode(this); 730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHLoadNamedField* CodeStubGraphBuilderBase::BuildLoadNamedField( 734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HValue* object, FieldIndex index) { 735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Representation representation = index.is_double() 736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? Representation::Double() 737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : Representation::Tagged(); 738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = index.offset(); 739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HObjectAccess access = index.is_inobject() 740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? HObjectAccess::ForObservableJSObjectOffset(offset, representation) 741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : HObjectAccess::ForBackingStoreOffset(offset, representation); 742958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (index.is_double() && 743958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier (!FLAG_unbox_double_fields || !index.is_inobject())) { 744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the heap number. 745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch object = Add<HLoadNamedField>( 746958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier object, nullptr, access.WithRepresentation(Representation::Tagged())); 747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the double value from it. 748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch access = HObjectAccess::ForHeapNumberValue(); 749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 750958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return Add<HLoadNamedField>(object, nullptr, access); 751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<> 755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHValue* CodeStubGraphBuilder<LoadFieldStub>::BuildCodeStub() { 756f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return BuildLoadNamedField(GetParameter(Descriptor::kReceiver), 757f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch casted_stub()->index()); 758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> LoadFieldStub::GenerateCode() { 762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return DoGenerateCode(this); 763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <> 767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHValue* CodeStubGraphBuilder<LoadConstantStub>::BuildCodeStub() { 768f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch HValue* map = AddLoadMap(GetParameter(Descriptor::kReceiver), NULL); 769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HObjectAccess descriptors_access = HObjectAccess::ForObservableJSObjectOffset( 770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Map::kDescriptorsOffset, Representation::Tagged()); 771958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier HValue* descriptors = Add<HLoadNamedField>(map, nullptr, descriptors_access); 772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HObjectAccess value_access = HObjectAccess::ForObservableJSObjectOffset( 773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DescriptorArray::GetValueOffset(casted_stub()->constant_index())); 774958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return Add<HLoadNamedField>(descriptors, nullptr, value_access); 775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> LoadConstantStub::GenerateCode() { return DoGenerateCode(this); } 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CodeStubGraphBuilderBase::BuildStoreNamedField( 782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HValue* object, HValue* value, FieldIndex index, 783958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Representation representation, bool transition_to_field) { 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!index.is_double() || representation.IsDouble()); 785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = index.offset(); 786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HObjectAccess access = 787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch index.is_inobject() 788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? HObjectAccess::ForObservableJSObjectOffset(offset, representation) 789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : HObjectAccess::ForBackingStoreOffset(offset, representation); 790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (representation.IsDouble()) { 792958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!FLAG_unbox_double_fields || !index.is_inobject()) { 793958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier HObjectAccess heap_number_access = 794958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier access.WithRepresentation(Representation::Tagged()); 795958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (transition_to_field) { 796958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The store requires a mutable HeapNumber to be allocated. 797958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NoObservableSideEffectsScope no_side_effects(this); 798958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); 799958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 800958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // TODO(hpayer): Allocation site pretenuring support. 801958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier HInstruction* heap_number = 802958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Add<HAllocate>(heap_number_size, HType::HeapObject(), NOT_TENURED, 803bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch MUTABLE_HEAP_NUMBER_TYPE, graph()->GetConstant0()); 804958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AddStoreMapConstant(heap_number, 805958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier isolate()->factory()->mutable_heap_number_map()); 806958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(), 807958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier value); 808958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Store the new mutable heap number into the object. 809958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier access = heap_number_access; 810958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier value = heap_number; 811958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 812958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Load the heap number. 813958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier object = Add<HLoadNamedField>(object, nullptr, heap_number_access); 814958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Store the double value into it. 815958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier access = HObjectAccess::ForHeapNumberValue(); 816958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 817958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (representation.IsHeapObject()) { 819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BuildCheckHeapObject(value); 820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Add<HStoreNamedField>(object, access, value, INITIALIZING_STORE); 823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <> 827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHValue* CodeStubGraphBuilder<TransitionElementsKindStub>::BuildCodeStub() { 82813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch ElementsKind const from_kind = casted_stub()->from_kind(); 82913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch ElementsKind const to_kind = casted_stub()->to_kind(); 830f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch HValue* const object = GetParameter(Descriptor::kObject); 831f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch HValue* const map = GetParameter(Descriptor::kMap); 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 83313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // The {object} is known to be a JSObject (otherwise it wouldn't have elements 83413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // anyways). 83513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch object->set_type(HType::JSObject()); 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 83713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch info()->MarkAsSavesCallerDoubles(); 838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 83913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK_IMPLIES(IsFastHoleyElementsKind(from_kind), 84013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch IsFastHoleyElementsKind(to_kind)); 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 84213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) { 84313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Add<HTrapAllocationMemento>(object); 844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 84613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (!IsSimpleMapChangeTransition(from_kind, to_kind)) { 84713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HInstruction* elements = AddLoadElements(object); 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 84913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch IfBuilder if_objecthaselements(this); 85013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if_objecthaselements.IfNot<HCompareObjectEqAndBranch>( 85113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch elements, Add<HConstant>(isolate()->factory()->empty_fixed_array())); 85213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if_objecthaselements.Then(); 85313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 85413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Determine the elements capacity. 85513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HInstruction* elements_length = AddLoadFixedArrayLength(elements); 856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 85713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Determine the effective (array) length. 85813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch IfBuilder if_objectisarray(this); 85913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if_objectisarray.If<HHasInstanceTypeAndBranch>(object, JS_ARRAY_TYPE); 86013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if_objectisarray.Then(); 86113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 86213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // The {object} is a JSArray, load the special "length" property. 86313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Push(Add<HLoadNamedField>(object, nullptr, 86413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HObjectAccess::ForArrayLength(from_kind))); 86513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 86613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if_objectisarray.Else(); 86713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 86813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // The {object} is some other JSObject. 86913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Push(elements_length); 87013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 87113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if_objectisarray.End(); 87213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch HValue* length = Pop(); 873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 87413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch BuildGrowElementsCapacity(object, elements, from_kind, to_kind, length, 87513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch elements_length); 87613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 87713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if_objecthaselements.End(); 878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 88013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); 881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 88213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return object; 883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 88613e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochHandle<Code> TransitionElementsKindStub::GenerateCode() { 887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return DoGenerateCode(this); 888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <> 891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHValue* CodeStubGraphBuilder<BinaryOpICStub>::BuildCodeInitializedStub() { 892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BinaryOpICState state = casted_stub()->state(); 893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 894f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch HValue* left = GetParameter(Descriptor::kLeft); 895f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch HValue* right = GetParameter(Descriptor::kRight); 896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 897f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch AstType* left_type = state.GetLeftType(); 898f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch AstType* right_type = state.GetRightType(); 899f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch AstType* result_type = state.GetResultType(); 900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 901f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK(!left_type->Is(AstType::None()) && !right_type->Is(AstType::None()) && 902f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch (state.HasSideEffects() || !result_type->Is(AstType::None()))); 903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HValue* result = NULL; 905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HAllocationMode allocation_mode(NOT_TENURED); 906f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (state.op() == Token::ADD && (left_type->Maybe(AstType::String()) || 907f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch right_type->Maybe(AstType::String())) && 908f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch !left_type->Is(AstType::String()) && !right_type->Is(AstType::String())) { 909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For the generic add stub a fast case for string addition is performance 910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // critical. 911f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (left_type->Maybe(AstType::String())) { 912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IfBuilder if_leftisstring(this); 913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if_leftisstring.If<HIsStringAndBranch>(left); 914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if_leftisstring.Then(); 915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 916f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Push(BuildBinaryOperation(state.op(), left, right, AstType::String(), 917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch right_type, result_type, 918109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch state.fixed_right_arg(), allocation_mode)); 919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if_leftisstring.Else(); 921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 922109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Push(BuildBinaryOperation(state.op(), left, right, left_type, 923109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch right_type, result_type, 924109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch state.fixed_right_arg(), allocation_mode)); 925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if_leftisstring.End(); 927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result = Pop(); 928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IfBuilder if_rightisstring(this); 930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if_rightisstring.If<HIsStringAndBranch>(right); 931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if_rightisstring.Then(); 932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(BuildBinaryOperation(state.op(), left, right, left_type, 934f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch AstType::String(), result_type, 935109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch state.fixed_right_arg(), allocation_mode)); 936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if_rightisstring.Else(); 938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 939109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Push(BuildBinaryOperation(state.op(), left, right, left_type, 940109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch right_type, result_type, 941109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch state.fixed_right_arg(), allocation_mode)); 942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if_rightisstring.End(); 944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result = Pop(); 945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 947109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch result = BuildBinaryOperation(state.op(), left, right, left_type, 948109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch right_type, result_type, 949109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch state.fixed_right_arg(), allocation_mode); 950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we encounter a generic argument, the number conversion is 953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // observable, thus we cannot afford to bail out after the fact. 954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!state.HasSideEffects()) { 955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result = EnforceNumberType(result, result_type); 956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result; 959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> BinaryOpICStub::GenerateCode() { 963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return DoGenerateCode(this); 964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <> 968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHValue* CodeStubGraphBuilder<BinaryOpWithAllocationSiteStub>::BuildCodeStub() { 969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BinaryOpICState state = casted_stub()->state(); 970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 971f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch HValue* allocation_site = GetParameter(Descriptor::kAllocationSite); 972f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch HValue* left = GetParameter(Descriptor::kLeft); 973f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch HValue* right = GetParameter(Descriptor::kRight); 974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 975f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch AstType* left_type = state.GetLeftType(); 976f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch AstType* right_type = state.GetRightType(); 977f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch AstType* result_type = state.GetResultType(); 978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HAllocationMode allocation_mode(allocation_site); 979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return BuildBinaryOperation(state.op(), left, right, left_type, right_type, 981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch result_type, state.fixed_right_arg(), 982109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch allocation_mode); 983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> BinaryOpWithAllocationSiteStub::GenerateCode() { 987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return DoGenerateCode(this); 988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochHValue* CodeStubGraphBuilderBase::BuildToString(HValue* input, bool convert) { 992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!convert) return BuildCheckString(input); 993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch IfBuilder if_inputissmi(this); 994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HValue* inputissmi = if_inputissmi.If<HIsSmiAndBranch>(input); 995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_inputissmi.Then(); 996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Convert the input smi to a string. 998f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Push(BuildNumberToString(input, AstType::SignedSmall())); 999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_inputissmi.Else(); 1001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HValue* input_map = 1003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Add<HLoadNamedField>(input, inputissmi, HObjectAccess::ForMap()); 1004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HValue* input_instance_type = Add<HLoadNamedField>( 1005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch input_map, inputissmi, HObjectAccess::ForMapInstanceType()); 1006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch IfBuilder if_inputisstring(this); 1007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_inputisstring.If<HCompareNumericAndBranch>( 1008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch input_instance_type, Add<HConstant>(FIRST_NONSTRING_TYPE), Token::LT); 1009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_inputisstring.Then(); 1010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The input is already a string. 1012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(input); 1013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_inputisstring.Else(); 1015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Convert to primitive first (if necessary), see 1017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ES6 section 12.7.3 The Addition operator. 1018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch IfBuilder if_inputisprimitive(this); 1019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE); 1020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_inputisprimitive.If<HCompareNumericAndBranch>( 1021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch input_instance_type, Add<HConstant>(LAST_PRIMITIVE_TYPE), Token::LTE); 1022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_inputisprimitive.Then(); 1023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The input is already a primitive. 1025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(input); 1026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_inputisprimitive.Else(); 1028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Convert the input to a primitive. 1030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(BuildToPrimitive(input, input_map)); 1031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1032014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_inputisprimitive.End(); 1033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Convert the primitive to a string value. 1034c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch HValue* values[] = {Pop()}; 1035f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Callable toString = CodeFactory::ToString(isolate()); 1036f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Push(AddUncasted<HCallWithDescriptor>(Add<HConstant>(toString.code()), 0, 1037f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch toString.descriptor(), 1038bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch ArrayVector(values))); 1039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_inputisstring.End(); 1041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_inputissmi.End(); 1043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return Pop(); 1044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochHValue* CodeStubGraphBuilderBase::BuildToPrimitive(HValue* input, 1048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HValue* input_map) { 1049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Get the native context of the caller. 1050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HValue* native_context = BuildGetNativeContext(); 1051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Determine the initial map of the %ObjectPrototype%. 1053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HValue* object_function_prototype_map = 1054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Add<HLoadNamedField>(native_context, nullptr, 1055014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HObjectAccess::ForContextSlot( 1056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Context::OBJECT_FUNCTION_PROTOTYPE_MAP_INDEX)); 1057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Determine the initial map of the %StringPrototype%. 1059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HValue* string_function_prototype_map = 1060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Add<HLoadNamedField>(native_context, nullptr, 1061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HObjectAccess::ForContextSlot( 1062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); 1063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Determine the initial map of the String function. 1065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HValue* string_function = Add<HLoadNamedField>( 1066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch native_context, nullptr, 1067014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HObjectAccess::ForContextSlot(Context::STRING_FUNCTION_INDEX)); 1068014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HValue* string_function_initial_map = Add<HLoadNamedField>( 1069014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch string_function, nullptr, HObjectAccess::ForPrototypeOrInitialMap()); 1070014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1071014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Determine the map of the [[Prototype]] of {input}. 1072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HValue* input_prototype = 1073014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Add<HLoadNamedField>(input_map, nullptr, HObjectAccess::ForPrototype()); 1074014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HValue* input_prototype_map = 1075014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Add<HLoadNamedField>(input_prototype, nullptr, HObjectAccess::ForMap()); 1076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1077014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // For string wrappers (JSValue instances with [[StringData]] internal 1078014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // fields), we can shortcirciut the ToPrimitive if 1079014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1080014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // (a) the {input} map matches the initial map of the String function, 1081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // (b) the {input} [[Prototype]] is the unmodified %StringPrototype% (i.e. 1082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // no one monkey-patched toString, @@toPrimitive or valueOf), and 1083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // (c) the %ObjectPrototype% (i.e. the [[Prototype]] of the 1084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // %StringPrototype%) is also unmodified, that is no one sneaked a 1085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // @@toPrimitive into the %ObjectPrototype%. 1086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If all these assumptions hold, we can just take the [[StringData]] value 1088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // and return it. 1089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // TODO(bmeurer): This just repairs a regression introduced by removing the 1090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // weird (and broken) intrinsic %_IsStringWrapperSafeForDefaultValue, which 1091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // was intendend to something similar to this, although less efficient and 1092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // wrong in the presence of @@toPrimitive. Long-term we might want to move 1093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // into the direction of having a ToPrimitiveStub that can do common cases 1094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // while staying in JavaScript land (i.e. not going to C++). 1095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch IfBuilder if_inputisstringwrapper(this); 1096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_inputisstringwrapper.If<HCompareObjectEqAndBranch>( 1097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch input_map, string_function_initial_map); 1098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_inputisstringwrapper.And(); 1099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_inputisstringwrapper.If<HCompareObjectEqAndBranch>( 1100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch input_prototype_map, string_function_prototype_map); 1101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_inputisstringwrapper.And(); 1102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_inputisstringwrapper.If<HCompareObjectEqAndBranch>( 1103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Add<HLoadNamedField>(Add<HLoadNamedField>(input_prototype_map, nullptr, 1104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HObjectAccess::ForPrototype()), 1105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch nullptr, HObjectAccess::ForMap()), 1106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch object_function_prototype_map); 1107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_inputisstringwrapper.Then(); 1108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(BuildLoadNamedField( 1110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch input, FieldIndex::ForInObjectOffset(JSValue::kValueOffset))); 1111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_inputisstringwrapper.Else(); 1113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // TODO(bmeurer): Add support for fast ToPrimitive conversion using 1115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // a dedicated ToPrimitiveStub. 1116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Add<HPushArguments>(input); 1117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kToPrimitive), 1)); 1118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_inputisstringwrapper.End(); 1120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return Pop(); 1121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <> 11243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochHValue* CodeStubGraphBuilder<ToBooleanICStub>::BuildCodeInitializedStub() { 11253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch ToBooleanICStub* stub = casted_stub(); 1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IfBuilder if_true(this); 1127c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if_true.If<HBranch>(GetParameter(Descriptor::kArgument), stub->hints()); 1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if_true.Then(); 1129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if_true.Return(graph()->GetConstantTrue()); 1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if_true.Else(); 1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if_true.End(); 1132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return graph()->GetConstantFalse(); 1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 11353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochHandle<Code> ToBooleanICStub::GenerateCode() { return DoGenerateCode(this); } 1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <> 1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHValue* CodeStubGraphBuilder<LoadDictionaryElementStub>::BuildCodeStub() { 1139f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch HValue* receiver = GetParameter(Descriptor::kReceiver); 1140f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch HValue* key = GetParameter(Descriptor::kName); 1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Add<HCheckSmi>(key); 1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HValue* elements = AddLoadElements(receiver); 1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HValue* hash = BuildElementIndexHash(key); 1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1148109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch return BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash); 1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> LoadDictionaryElementStub::GenerateCode() { 1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return DoGenerateCode(this); 1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 1157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 1158