handler-compiler.cc revision 958fae7ec3f466955f8e5b50fa5b8d38b9e91675
1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2014 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 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/call-optimization.h" 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/handler-compiler.h" 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic-inl.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> PropertyHandlerCompiler::Find(Handle<Name> name, 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> stub_holder, 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::Kind kind, 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CacheHolderFlag cache_holder, 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::StubType type) { 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder); 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* probe = stub_holder->FindInCodeCache(*name, flags); 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (probe->IsCode()) return handle(Code::cast(probe)); 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Handle<Code>::null(); 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::ComputeLoadNonexistent( 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name, Handle<HeapType> type) { 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = name->GetIsolate(); 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> receiver_map = IC::TypeToMap(*type, isolate); 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (receiver_map->prototype()->IsNull()) { 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(jkummerow/verwaest): If there is no prototype and the property 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is nonexistent, introduce a builtin to handle this (fast properties 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -> return undefined, dictionary properties -> do negative lookup). 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Handle<Code>(); 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CacheHolderFlag flag; 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> stub_holder_map = 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IC::GetHandlerCacheHolder(*type, false, isolate, &flag); 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If no dictionary mode objects are present in the prototype chain, the load 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // nonexistent IC stub can be shared for all names for a given map and we use 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the empty string for the map cache in that case. If there are dictionary 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // mode objects involved, we need to do negative lookups in the stub and 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // therefore the stub will be specific to the name. 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> cache_name = 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch receiver_map->is_dictionary_map() 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? name 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : Handle<Name>::cast(isolate->factory()->nonexistent_symbol()); 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> current_map = stub_holder_map; 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> last(JSObject::cast(receiver_map->prototype())); 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (true) { 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (current_map->is_dictionary_map()) cache_name = name; 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (current_map->prototype()->IsNull()) break; 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch last = handle(JSObject::cast(current_map->prototype())); 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current_map = handle(last->map()); 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compile the stub that is either shared for all names or 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // name specific if there are global objects involved. 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> handler = PropertyHandlerCompiler::Find( 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cache_name, stub_holder_map, Code::LOAD_IC, flag, Code::FAST); 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!handler.is_null()) return handler; 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NamedLoadHandlerCompiler compiler(isolate, type, last, flag); 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch handler = compiler.CompileLoadNonexistent(cache_name); 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Map::UpdateCodeCache(stub_holder_map, cache_name, handler); 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return handler; 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> PropertyHandlerCompiler::GetCode(Code::Kind kind, 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::StubType type, 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name) { 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder()); 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> code = GetCodeWithFlags(flags, name); 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, *code, *name)); 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return code; 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PropertyHandlerCompiler::set_type_for_object(Handle<Object> object) { 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch type_ = IC::CurrentTypeOf(object, isolate()); 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm()) 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister NamedLoadHandlerCompiler::FrontendHeader(Register object_reg, 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name, 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* miss) { 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrototypeCheckType check_type = CHECK_ALL_MAPS; 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int function_index = -1; 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (type()->Is(HeapType::String())) { 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch function_index = Context::STRING_FUNCTION_INDEX; 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (type()->Is(HeapType::Symbol())) { 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch function_index = Context::SYMBOL_FUNCTION_INDEX; 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (type()->Is(HeapType::Number())) { 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch function_index = Context::NUMBER_FUNCTION_INDEX; 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (type()->Is(HeapType::Boolean())) { 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch function_index = Context::BOOLEAN_FUNCTION_INDEX; 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch check_type = SKIP_RECEIVER; 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (check_type == CHECK_ALL_MAPS) { 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateDirectLoadGlobalFunctionPrototype(masm(), function_index, 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch1(), miss); 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* function = isolate()->native_context()->get(function_index); 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* prototype = JSFunction::cast(function)->instance_prototype(); 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch set_type_for_object(handle(prototype, isolate())); 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch object_reg = scratch1(); 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the maps starting from the prototype haven't changed. 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CheckPrototypes(object_reg, scratch1(), scratch2(), scratch3(), name, 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch miss, check_type); 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Frontend for store uses the name register. It has to be restored before a 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// miss. 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister NamedStoreHandlerCompiler::FrontendHeader(Register object_reg, 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name, 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* miss) { 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CheckPrototypes(object_reg, this->name(), scratch1(), scratch2(), name, 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch miss, SKIP_RECEIVER); 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRegister PropertyHandlerCompiler::Frontend(Handle<Name> name) { 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (IC::ICUseVector(kind())) { 135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PushVectorAndSlot(); 136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register reg = FrontendHeader(receiver(), name, &miss); 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrontendFooter(name, &miss); 139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The footer consumes the vector and slot from the stack if miss occurs. 140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (IC::ICUseVector(kind())) { 141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DiscardVectorAndSlot(); 142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return reg; 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PropertyHandlerCompiler::NonexistentFrontendHeader(Handle<Name> name, 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* miss, 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2) { 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register holder_reg; 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> last_map; 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (holder().is_null()) { 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch holder_reg = receiver(); 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch last_map = IC::TypeToMap(*type(), isolate()); 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If |type| has null as its prototype, |holder()| is 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Handle<JSObject>::null(). 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(last_map->prototype() == isolate()->heap()->null_value()); 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch holder_reg = FrontendHeader(receiver(), name, miss); 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch last_map = handle(holder()->map()); 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (last_map->is_dictionary_map()) { 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (last_map->IsJSGlobalObjectMap()) { 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSGlobalObject> global = 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch holder().is_null() 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? Handle<JSGlobalObject>::cast(type()->AsConstant()->Value()) 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : Handle<JSGlobalObject>::cast(holder()); 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateCheckPropertyCell(masm(), global, name, scratch1, miss); 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!name->IsUniqueName()) { 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(name->IsString()); 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name = factory()->InternalizeString(Handle<String>::cast(name)); 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(holder().is_null() || 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch holder()->property_dictionary()->FindEntry(name) == 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kNotFound); 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateDictionaryNegativeLookup(masm(), miss, holder_reg, name, scratch1, 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch2); 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::CompileLoadField(Handle<Name> name, 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldIndex field) { 188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register reg = Frontend(name); 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(receiver(), reg); 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadFieldStub stub(isolate(), field); 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateTailCall(masm(), stub.GetCode()); 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetCode(kind(), Code::FAST, name); 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::CompileLoadConstant(Handle<Name> name, 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int constant_index) { 198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register reg = Frontend(name); 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(receiver(), reg); 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadConstantStub stub(isolate(), constant_index); 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateTailCall(masm(), stub.GetCode()); 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetCode(kind(), Code::FAST, name); 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name) { 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (IC::ICUseVector(kind())) { 210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(kind() == Code::LOAD_IC); 211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PushVectorAndSlot(); 212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NonexistentFrontendHeader(name, &miss, scratch2(), scratch3()); 214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (IC::ICUseVector(kind())) { 215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DiscardVectorAndSlot(); 216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateLoadConstant(isolate()->factory()->undefined_value()); 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrontendFooter(name, &miss); 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetCode(kind(), Code::FAST, name); 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name, Handle<ExecutableAccessorInfo> callback) { 225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register reg = Frontend(name); 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateLoadCallback(reg, callback); 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetCode(kind(), Code::FAST, name); 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name, const CallOptimization& call_optimization) { 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(call_optimization.is_simple_api_call()); 234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Frontend(name); 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> receiver_map = IC::TypeToMap(*type(), isolate()); 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateFastApiCall(masm(), call_optimization, receiver_map, receiver(), 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch1(), false, 0, NULL); 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetCode(kind(), Code::FAST, name); 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::InterceptorVectorSlotPush(Register holder_reg) { 243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (IC::ICUseVector(kind())) { 244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (holder_reg.is(receiver())) { 245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PushVectorAndSlot(); 246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(holder_reg.is(scratch1())); 248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PushVectorAndSlot(scratch2(), scratch3()); 249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::InterceptorVectorSlotPop(Register holder_reg, 255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PopMode mode) { 256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (IC::ICUseVector(kind())) { 257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (mode == DISCARD) { 258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DiscardVectorAndSlot(); 259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (holder_reg.is(receiver())) { 261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PopVectorAndSlot(); 262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(holder_reg.is(scratch1())); 264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PopVectorAndSlot(scratch2(), scratch3()); 265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor( 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LookupIterator* it) { 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // So far the most popular follow ups for interceptor loads are FIELD and 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ExecutableAccessorInfo, so inline only them. Other cases may be added 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // later. 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool inline_followup = false; 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (it->state()) { 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::TRANSITION: 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::ACCESS_CHECK: 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::INTERCEPTOR: 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::JSPROXY: 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::NOT_FOUND: 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::DATA: 286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier inline_followup = 287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier it->property_details().type() == FIELD && !it->is_dictionary_holder(); 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::ACCESSOR: { 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> accessors = it->GetAccessors(); 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline_followup = accessors->IsExecutableAccessorInfo(); 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!inline_followup) break; 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<ExecutableAccessorInfo> info = 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<ExecutableAccessorInfo>::cast(accessors); 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline_followup = info->getter() != NULL && 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExecutableAccessorInfo::IsCompatibleReceiverType( 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate(), info, type()); 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InterceptorVectorSlotPush(receiver()); 303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register reg = FrontendHeader(receiver(), it->name(), &miss); 304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrontendFooter(it->name(), &miss); 305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InterceptorVectorSlotPop(reg); 306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (inline_followup) { 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(368): Compile in the whole chain: all the interceptors in 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // prototypes and ultimate answer. 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateLoadInterceptorWithFollowup(it, reg); 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateLoadInterceptor(reg); 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetCode(kind(), Code::FAST, it->name()); 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadPostInterceptor( 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LookupIterator* it, Register interceptor_reg) { 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> real_named_property_holder(it->GetHolder<JSObject>()); 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch set_type_for_object(holder()); 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch set_holder(real_named_property_holder); 324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InterceptorVectorSlotPush(interceptor_reg); 327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register reg = FrontendHeader(interceptor_reg, it->name(), &miss); 328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrontendFooter(it->name(), &miss); 329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // We discard the vector and slot now because we don't miss below this point. 330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InterceptorVectorSlotPop(reg, DISCARD); 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (it->state()) { 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::ACCESS_CHECK: 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::INTERCEPTOR: 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::JSPROXY: 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::NOT_FOUND: 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::TRANSITION: 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::DATA: { 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(FIELD, it->property_details().type()); 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(receiver(), reg); 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadFieldStub stub(isolate(), it->GetFieldIndex()); 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateTailCall(masm(), stub.GetCode()); 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::ACCESSOR: 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<ExecutableAccessorInfo> info = 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<ExecutableAccessorInfo>::cast(it->GetAccessors()); 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_NE(NULL, info->getter()); 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateLoadCallback(reg, info); 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter( 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name, Handle<JSFunction> getter) { 357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Frontend(name); 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateLoadViaGetter(masm(), type(), receiver(), getter); 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetCode(kind(), Code::FAST, name); 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(verwaest): Cleanup. holder() is actually the receiver. 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> transition, Handle<Name> name) { 366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that we are allowed to write this. 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_nonexistent = holder()->map() == transition->GetBackPointer(); 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (is_nonexistent) { 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Find the top object. 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> last; 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrototypeIterator iter(isolate(), holder()); 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (!iter.IsAtEnd()) { 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch last = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch iter.Advance(); 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!last.is_null()) set_holder(last); 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NonexistentFrontendHeader(name, &miss, scratch1(), scratch2()); 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrontendHeader(receiver(), name, &miss); 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(holder()->HasFastProperties()); 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 385958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int descriptor = transition->LastAdded(); 386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<DescriptorArray> descriptors(transition->instance_descriptors()); 387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PropertyDetails details = descriptors->GetDetails(descriptor); 388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Representation representation = details.representation(); 389958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!representation.IsNone()); 390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Stub is never generated for objects that require access checks. 392958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!transition->is_access_check_needed()); 393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Call to respective StoreTransitionStub. 395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (details.type() == CONSTANT) { 396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateRestoreMap(transition, scratch2(), &miss); 397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(descriptors->GetValue(descriptor)->IsJSFunction()); 398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register map_reg = StoreTransitionDescriptor::MapRegister(); 399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateConstantCheck(map_reg, descriptor, value(), scratch2(), &miss); 400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateRestoreName(name); 401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StoreTransitionStub stub(isolate()); 402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateTailCall(masm(), stub.GetCode()); 403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 404958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (representation.IsHeapObject()) { 406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateFieldTypeChecks(descriptors->GetFieldType(descriptor), value(), 407958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &miss); 408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StoreTransitionStub::StoreMode store_mode = 410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Map::cast(transition->GetBackPointer())->unused_property_fields() == 0 411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ? StoreTransitionStub::ExtendStorageAndStoreMapAndValue 412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier : StoreTransitionStub::StoreMapAndValue; 413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateRestoreMap(transition, scratch2(), &miss); 415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateRestoreName(name); 416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StoreTransitionStub stub(isolate(), 417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldIndex::ForDescriptor(*transition, descriptor), 418958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier representation, store_mode); 419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateTailCall(masm(), stub.GetCode()); 420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateRestoreName(&miss, name); 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TailCallBuiltin(masm(), MissBuiltin(kind())); 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetCode(kind(), Code::FAST, name); 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedStoreHandlerCompiler::CompileStoreField(LookupIterator* it) { 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(it->representation().IsHeapObject()); 432958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 433958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateFieldTypeChecks(*it->GetFieldType(), value(), &miss); 434958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StoreFieldStub stub(isolate(), it->GetFieldIndex(), it->representation()); 435958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateTailCall(masm(), stub.GetCode()); 436958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&miss); 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TailCallBuiltin(masm(), MissBuiltin(kind())); 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetCode(kind(), Code::FAST, it->name()); 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter( 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> object, Handle<Name> name, Handle<JSFunction> setter) { 445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Frontend(name); 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateStoreViaSetter(masm(), type(), receiver(), setter); 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetCode(kind(), Code::FAST, name); 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> object, Handle<Name> name, 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CallOptimization& call_optimization) { 455958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Frontend(name); 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register values[] = {value()}; 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateFastApiCall(masm(), call_optimization, handle(object->map()), 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch receiver(), scratch1(), true, 1, values); 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetCode(kind(), Code::FAST, name); 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ElementHandlerCompiler::CompileElementHandlers( 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MapHandleList* receiver_maps, CodeHandleList* handlers) { 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < receiver_maps->length(); ++i) { 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> receiver_map = receiver_maps->at(i); 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> cached_stub; 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 472958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (receiver_map->IsStringMap()) { 473958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier cached_stub = LoadIndexedStringStub(isolate()).GetCode(); 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) { 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cached_stub = isolate()->builtins()->KeyedLoadIC_Slow(); 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsKind elements_kind = receiver_map->elements_kind(); 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (receiver_map->has_indexed_interceptor()) { 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cached_stub = LoadIndexedInterceptorStub(isolate()).GetCode(); 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (IsSloppyArgumentsElements(elements_kind)) { 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cached_stub = KeyedLoadSloppyArgumentsStub(isolate()).GetCode(); 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (IsFastElementsKind(elements_kind) || 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IsExternalArrayElementsKind(elements_kind) || 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IsFixedTypedArrayElementsKind(elements_kind)) { 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cached_stub = LoadFastElementStub(isolate(), is_js_array, elements_kind) 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch .GetCode(); 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(elements_kind == DICTIONARY_ELEMENTS); 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cached_stub = LoadDictionaryElementStub(isolate()).GetCode(); 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch handlers->Add(cached_stub); 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace v8::internal 499