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 5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ic/handler-compiler.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#include "src/field-type.h" 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/call-optimization.h" 9c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch#include "src/ic/handler-configuration-inl.h" 10f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch#include "src/ic/ic-inl.h" 11109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#include "src/ic/ic.h" 12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/isolate-inl.h" 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> PropertyHandlerCompiler::Find(Handle<Name> name, 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> stub_holder, 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::Kind kind, 20bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch CacheHolderFlag cache_holder) { 21bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Code::Flags flags = Code::ComputeHandlerFlags(kind, cache_holder); 22bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Code* code = stub_holder->LookupInCodeCache(*name, flags); 23bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch if (code == nullptr) return Handle<Code>(); 24bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return handle(code); 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::ComputeLoadNonexistent( 29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Name> name, Handle<Map> receiver_map) { 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = name->GetIsolate(); 3113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (receiver_map->prototype()->IsNull(isolate)) { 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(jkummerow/verwaest): If there is no prototype and the property 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is nonexistent, introduce a builtin to handle this (fast properties 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -> return undefined, dictionary properties -> do negative lookup). 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Handle<Code>(); 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CacheHolderFlag flag; 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> stub_holder_map = 39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch IC::GetHandlerCacheHolder(receiver_map, false, isolate, &flag); 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If no dictionary mode objects are present in the prototype chain, the load 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // nonexistent IC stub can be shared for all names for a given map and we use 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the empty string for the map cache in that case. If there are dictionary 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // mode objects involved, we need to do negative lookups in the stub and 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // therefore the stub will be specific to the name. 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> cache_name = 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch receiver_map->is_dictionary_map() 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? name 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : Handle<Name>::cast(isolate->factory()->nonexistent_symbol()); 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> current_map = stub_holder_map; 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> last(JSObject::cast(receiver_map->prototype())); 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (true) { 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (current_map->is_dictionary_map()) cache_name = name; 5413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (current_map->prototype()->IsNull(isolate)) break; 55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (name->IsPrivate()) { 56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // TODO(verwaest): Use nonexistent_private_symbol. 57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch cache_name = name; 58109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (!current_map->has_hidden_prototype()) break; 59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch last = handle(JSObject::cast(current_map->prototype())); 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current_map = handle(last->map()); 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compile the stub that is either shared for all names or 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // name specific if there are global objects involved. 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> handler = PropertyHandlerCompiler::Find( 67bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch cache_name, stub_holder_map, Code::LOAD_IC, flag); 68c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (!handler.is_null()) { 69c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch TRACE_HANDLER_STATS(isolate, LoadIC_HandlerCacheHit_NonExistent); 70c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return handler; 71c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 73bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch TRACE_HANDLER_STATS(isolate, LoadIC_LoadNonexistent); 74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch NamedLoadHandlerCompiler compiler(isolate, receiver_map, last, flag); 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch handler = compiler.CompileLoadNonexistent(cache_name); 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Map::UpdateCodeCache(stub_holder_map, cache_name, handler); 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return handler; 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> PropertyHandlerCompiler::GetCode(Code::Kind kind, 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name) { 83bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Code::Flags flags = Code::ComputeHandlerFlags(kind, cache_holder()); 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> code = GetCodeWithFlags(flags, name); 8513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch PROFILE(isolate(), CodeCreateEvent(CodeEventListener::HANDLER_TAG, 863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch AbstractCode::cast(*code), *name)); 87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#ifdef DEBUG 88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch code->VerifyEmbeddedObjects(); 89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return code; 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm()) 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister NamedLoadHandlerCompiler::FrontendHeader(Register object_reg, 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name, 99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label* miss, 100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ReturnHolder return_what) { 101c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (map()->IsPrimitiveMap() || map()->IsJSGlobalProxyMap()) { 102c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // If the receiver is a global proxy and if we get to this point then 103c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // the compile-time (current) native context has access to global proxy's 104c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // native context. Since access rights revocation is not supported at all, 105c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // we can generate a check that an execution-time native context is either 106c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // the same as compile-time native context or has the same access token. 107c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Handle<Context> native_context = isolate()->native_context(); 108c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Handle<WeakCell> weak_cell(native_context->self_weak_cell(), isolate()); 109c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 110c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch bool compare_native_contexts_only = map()->IsPrimitiveMap(); 111c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GenerateAccessCheck(weak_cell, scratch1(), scratch2(), miss, 112c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch compare_native_contexts_only); 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the maps starting from the prototype haven't changed. 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CheckPrototypes(object_reg, scratch1(), scratch2(), scratch3(), name, 117c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch miss, return_what); 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Frontend for store uses the name register. It has to be restored before a 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// miss. 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister NamedStoreHandlerCompiler::FrontendHeader(Register object_reg, 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name, 125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label* miss, 126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ReturnHolder return_what) { 127c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (map()->IsJSGlobalProxyMap()) { 128c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Handle<Context> native_context = isolate()->native_context(); 129c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Handle<WeakCell> weak_cell(native_context->self_weak_cell(), isolate()); 130c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch GenerateAccessCheck(weak_cell, scratch1(), scratch2(), miss, false); 131c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 132c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CheckPrototypes(object_reg, this->name(), scratch1(), scratch2(), name, 134c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch miss, return_what); 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRegister PropertyHandlerCompiler::Frontend(Handle<Name> name) { 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 140f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (IC::ShouldPushPopSlotAndVector(kind())) { 141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PushVectorAndSlot(); 142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register reg = FrontendHeader(receiver(), name, &miss, RETURN_HOLDER); 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrontendFooter(name, &miss); 145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The footer consumes the vector and slot from the stack if miss occurs. 146f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (IC::ShouldPushPopSlotAndVector(kind())) { 147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DiscardVectorAndSlot(); 148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return reg; 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PropertyHandlerCompiler::NonexistentFrontendHeader(Handle<Name> name, 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* miss, 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2) { 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register holder_reg; 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> last_map; 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (holder().is_null()) { 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch holder_reg = receiver(); 161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch last_map = map(); 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If |type| has null as its prototype, |holder()| is 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Handle<JSObject>::null(). 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(last_map->prototype() == isolate()->heap()->null_value()); 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch last_map = handle(holder()->map()); 167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // This condition matches the branches below. 168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool need_holder = 169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch last_map->is_dictionary_map() && !last_map->IsJSGlobalObjectMap(); 170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch holder_reg = 171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrontendHeader(receiver(), name, miss, 172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch need_holder ? RETURN_HOLDER : DONT_RETURN_ANYTHING); 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (last_map->is_dictionary_map()) { 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (last_map->IsJSGlobalObjectMap()) { 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSGlobalObject> global = 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch holder().is_null() 179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ? Handle<JSGlobalObject>::cast(isolate()->global_object()) 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : Handle<JSGlobalObject>::cast(holder()); 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateCheckPropertyCell(masm(), global, name, scratch1, miss); 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!name->IsUniqueName()) { 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(name->IsString()); 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name = factory()->InternalizeString(Handle<String>::cast(name)); 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(holder().is_null() || 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch holder()->property_dictionary()->FindEntry(name) == 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kNotFound); 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateDictionaryNegativeLookup(masm(), miss, holder_reg, name, scratch1, 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch2); 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::CompileLoadField(Handle<Name> name, 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldIndex field) { 199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register reg = Frontend(name); 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(receiver(), reg); 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadFieldStub stub(isolate(), field); 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateTailCall(masm(), stub.GetCode()); 203bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return GetCode(kind(), name); 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::CompileLoadConstant(Handle<Name> name, 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int constant_index) { 209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register reg = Frontend(name); 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(receiver(), reg); 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadConstantStub stub(isolate(), constant_index); 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateTailCall(masm(), stub.GetCode()); 213bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return GetCode(kind(), name); 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Name> name) { 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 220f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (IC::ShouldPushPopSlotAndVector(kind())) { 221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(kind() == Code::LOAD_IC); 222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PushVectorAndSlot(); 223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NonexistentFrontendHeader(name, &miss, scratch2(), scratch3()); 225f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (IC::ShouldPushPopSlotAndVector(kind())) { 226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DiscardVectorAndSlot(); 227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateLoadConstant(isolate()->factory()->undefined_value()); 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrontendFooter(name, &miss); 230bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return GetCode(kind(), name); 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( 234f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Name> name, Handle<AccessorInfo> callback, Handle<Code> slow_stub) { 235c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (V8_UNLIKELY(FLAG_runtime_stats)) { 236f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GenerateTailCall(masm(), slow_stub); 23713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 238f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Register reg = Frontend(name); 239f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GenerateLoadCallback(reg, callback); 240bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return GetCode(kind(), name); 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( 244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Name> name, const CallOptimization& call_optimization, 245f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int accessor_index, Handle<Code> slow_stub) { 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(call_optimization.is_simple_api_call()); 247c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (V8_UNLIKELY(FLAG_runtime_stats)) { 248f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GenerateTailCall(masm(), slow_stub); 24913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 250f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Register holder = Frontend(name); 251f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GenerateApiAccessorCall(masm(), call_optimization, map(), receiver(), 252f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch scratch2(), false, no_reg, holder, accessor_index); 253bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return GetCode(kind(), name); 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::InterceptorVectorSlotPush(Register holder_reg) { 258f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (IC::ShouldPushPopSlotAndVector(kind())) { 259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (holder_reg.is(receiver())) { 260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PushVectorAndSlot(); 261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(holder_reg.is(scratch1())); 263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PushVectorAndSlot(scratch2(), scratch3()); 264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NamedLoadHandlerCompiler::InterceptorVectorSlotPop(Register holder_reg, 270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PopMode mode) { 271f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (IC::ShouldPushPopSlotAndVector(kind())) { 272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (mode == DISCARD) { 273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DiscardVectorAndSlot(); 274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (holder_reg.is(receiver())) { 276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PopVectorAndSlot(); 277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(holder_reg.is(scratch1())); 279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PopVectorAndSlot(scratch2(), scratch3()); 280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor( 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LookupIterator* it) { 288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // So far the most popular follow ups for interceptor loads are DATA and 289109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // AccessorInfo, so inline only them. Other cases may be added 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // later. 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool inline_followup = false; 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (it->state()) { 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::TRANSITION: 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::ACCESS_CHECK: 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::INTERCEPTOR: 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::JSPROXY: 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::NOT_FOUND: 299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case LookupIterator::INTEGER_INDEXED_EXOTIC: 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::DATA: 302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier inline_followup = 303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch it->property_details().type() == DATA && !it->is_dictionary_holder(); 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::ACCESSOR: { 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> accessors = it->GetAccessors(); 307109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (accessors->IsAccessorInfo()) { 308109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); 309109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch inline_followup = 310109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch info->getter() != NULL && 311109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map()); 312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (accessors->IsAccessorPair()) { 313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<JSObject> property_holder(it->GetHolder<JSObject>()); 314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), 315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch isolate()); 316109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (!(getter->IsJSFunction() || getter->IsFunctionTemplateInfo())) { 317109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch break; 318109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!property_holder->HasFastProperties()) break; 320109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallOptimization call_optimization(getter); 321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Map> receiver_map = map(); 322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch inline_followup = call_optimization.is_simple_api_call() && 323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch call_optimization.IsCompatibleReceiverMap( 324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch receiver_map, property_holder); 325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InterceptorVectorSlotPush(receiver()); 331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool lost_holder_register = false; 332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch auto holder_orig = holder(); 333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // non masking interceptors must check the entire chain, so temporarily reset 334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // the holder to be that last element for the FrontendHeader call. 335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (holder()->GetNamedInterceptor()->non_masking()) { 336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!inline_followup); 337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSObject* last = *holder(); 338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PrototypeIterator iter(isolate(), last); 339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch while (!iter.IsAtEnd()) { 340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch lost_holder_register = true; 341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Casting to JSObject is fine here. The LookupIterator makes sure to 342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // look behind non-masking interceptors during the original lookup, and 343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // we wouldn't try to compile a handler if there was a Proxy anywhere. 344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch last = iter.GetCurrent<JSObject>(); 345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch iter.Advance(); 346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch auto last_handle = handle(last); 348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch set_holder(last_handle); 349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register reg = FrontendHeader(receiver(), it->name(), &miss, RETURN_HOLDER); 351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Reset the holder so further calculations are correct. 352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch set_holder(holder_orig); 353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (lost_holder_register) { 354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (*it->GetReceiver() == *holder()) { 355014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reg = receiver(); 356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Reload lost holder register. 358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch auto cell = isolate()->factory()->NewWeakCell(holder()); 359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadWeakValue(reg, cell, &miss); 360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrontendFooter(it->name(), &miss); 363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InterceptorVectorSlotPop(reg); 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (inline_followup) { 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(368): Compile in the whole chain: all the interceptors in 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // prototypes and ultimate answer. 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateLoadInterceptorWithFollowup(it, reg); 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateLoadInterceptor(reg); 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 371bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return GetCode(kind(), it->name()); 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 374bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid NamedLoadHandlerCompiler::GenerateLoadCallback( 375bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register reg, Handle<AccessorInfo> callback) { 376bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(receiver().is(ApiGetterDescriptor::ReceiverRegister())); 377bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Move(ApiGetterDescriptor::HolderRegister(), reg); 378bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // The callback is alive if this instruction is executed, 379bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // so the weak cell is not cleared and points to data. 380bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback); 381bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ GetWeakValue(ApiGetterDescriptor::CallbackRegister(), cell); 382bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 383bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch CallApiGetterStub stub(isolate()); 384bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ TailCallStub(&stub); 385bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NamedLoadHandlerCompiler::GenerateLoadPostInterceptor( 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LookupIterator* it, Register interceptor_reg) { 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> real_named_property_holder(it->GetHolder<JSObject>()); 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Map> holder_map(holder()->map()); 392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch set_map(holder_map); 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch set_holder(real_named_property_holder); 394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InterceptorVectorSlotPush(interceptor_reg); 397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register reg = 398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrontendHeader(interceptor_reg, it->name(), &miss, RETURN_HOLDER); 399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FrontendFooter(it->name(), &miss); 400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // We discard the vector and slot now because we don't miss below this point. 401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier InterceptorVectorSlotPop(reg, DISCARD); 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (it->state()) { 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::ACCESS_CHECK: 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::INTERCEPTOR: 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::JSPROXY: 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::NOT_FOUND: 408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case LookupIterator::INTEGER_INDEXED_EXOTIC: 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::TRANSITION: 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::DATA: { 412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(DATA, it->property_details().type()); 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(receiver(), reg); 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadFieldStub stub(isolate(), it->GetFieldIndex()); 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateTailCall(masm(), stub.GetCode()); 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LookupIterator::ACCESSOR: 419109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (it->GetAccessors()->IsAccessorInfo()) { 420109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<AccessorInfo> info = 421109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<AccessorInfo>::cast(it->GetAccessors()); 422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_NOT_NULL(info->getter()); 423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GenerateLoadCallback(reg, info); 424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 425109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<Object> function = handle( 426109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AccessorPair::cast(*it->GetAccessors())->getter(), isolate()); 427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CallOptimization call_optimization(function); 428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GenerateApiAccessorCall(masm(), call_optimization, holder_map, 429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch receiver(), scratch2(), false, no_reg, reg, 430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch it->GetAccessorIndex()); 431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter( 436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Name> name, int accessor_index, int expected_arguments) { 437014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register holder = Frontend(name); 438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GenerateLoadViaGetter(masm(), map(), receiver(), holder, accessor_index, 439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch expected_arguments, scratch2()); 440bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return GetCode(kind(), name); 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(verwaest): Cleanup. holder() is actually the receiver. 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> transition, Handle<Name> name) { 447958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label miss; 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 449f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Ensure that the StoreTransitionStub we are going to call has the same 450f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // number of stack arguments. This means that we don't have to adapt them 451f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // if we decide to call the transition or miss stub. 452f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(Descriptor::kStackArgumentsCount == 453f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreTransitionDescriptor::kStackArgumentsCount); 454f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(Descriptor::kStackArgumentsCount == 0 || 455f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Descriptor::kStackArgumentsCount == 3); 456f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(Descriptor::kParameterCount - Descriptor::kValue == 457f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreTransitionDescriptor::kParameterCount - 458f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreTransitionDescriptor::kValue); 459f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(Descriptor::kParameterCount - Descriptor::kSlot == 460f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreTransitionDescriptor::kParameterCount - 461f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreTransitionDescriptor::kSlot); 462f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch STATIC_ASSERT(Descriptor::kParameterCount - Descriptor::kVector == 463f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreTransitionDescriptor::kParameterCount - 464f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreTransitionDescriptor::kVector); 465f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 466f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (Descriptor::kPassLastArgsOnStack) { 467f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue); 468f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 469f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 470f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch bool need_save_restore = IC::ShouldPushPopSlotAndVector(kind()); 471f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (need_save_restore) { 472f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch PushVectorAndSlot(); 473f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that we are allowed to write this. 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_nonexistent = holder()->map() == transition->GetBackPointer(); 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (is_nonexistent) { 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Find the top object. 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> last; 480014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PrototypeIterator::WhereToEnd end = 481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch name->IsPrivate() ? PrototypeIterator::END_AT_NON_HIDDEN 482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch : PrototypeIterator::END_AT_NULL; 48313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch PrototypeIterator iter(isolate(), holder(), kStartAtPrototype, end); 484109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch while (!iter.IsAtEnd()) { 485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch last = PrototypeIterator::GetCurrent<JSObject>(iter); 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch iter.Advance(); 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!last.is_null()) set_holder(last); 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NonexistentFrontendHeader(name, &miss, scratch1(), scratch2()); 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING); 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(holder()->HasFastProperties()); 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 495958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int descriptor = transition->LastAdded(); 496958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Handle<DescriptorArray> descriptors(transition->instance_descriptors()); 497958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PropertyDetails details = descriptors->GetDetails(descriptor); 498958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Representation representation = details.representation(); 499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!representation.IsNone()); 500958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 501958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Stub is never generated for objects that require access checks. 502958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(!transition->is_access_check_needed()); 503958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 504958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Call to respective StoreTransitionStub. 505f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Register map_reg = StoreTransitionDescriptor::MapRegister(); 506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (details.type() == DATA_CONSTANT) { 508958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(descriptors->GetValue(descriptor)->IsJSFunction()); 509f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GenerateRestoreMap(transition, map_reg, scratch1(), &miss); 510f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GenerateConstantCheck(map_reg, descriptor, value(), scratch1(), &miss); 511f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (need_save_restore) { 512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PopVectorAndSlot(); 513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateRestoreName(name); 515f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreMapStub stub(isolate()); 516958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateTailCall(masm(), stub.GetCode()); 517958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 518958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 519958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (representation.IsHeapObject()) { 520958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateFieldTypeChecks(descriptors->GetFieldType(descriptor), value(), 521958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &miss); 522958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 523958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StoreTransitionStub::StoreMode store_mode = 524958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Map::cast(transition->GetBackPointer())->unused_property_fields() == 0 525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ? StoreTransitionStub::ExtendStorageAndStoreMapAndValue 526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier : StoreTransitionStub::StoreMapAndValue; 527f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GenerateRestoreMap(transition, map_reg, scratch1(), &miss); 528f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (need_save_restore) { 529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PopVectorAndSlot(); 530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 531f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // We need to pass name on the stack. 532f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch PopReturnAddress(this->name()); 533f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Push(name); 534f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch PushReturnAddress(this->name()); 535f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 536f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch FieldIndex index = FieldIndex::ForDescriptor(*transition, descriptor); 537f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Move(StoreNamedTransitionDescriptor::FieldOffsetRegister(), 538f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Smi::FromInt(index.index() << kPointerSizeLog2)); 539f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 540f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch StoreTransitionStub stub(isolate(), index.is_inobject(), representation, 541f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch store_mode); 542958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateTailCall(masm(), stub.GetCode()); 543958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 545f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ bind(&miss); 546f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (need_save_restore) { 547f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch PopVectorAndSlot(); 548f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 549f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GenerateRestoreName(name); 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TailCallBuiltin(masm(), MissBuiltin(kind())); 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 552bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return GetCode(kind(), name); 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool NamedStoreHandlerCompiler::RequiresFieldTypeChecks( 556109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldType* field_type) const { 557109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch return field_type->IsClass(); 558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedStoreHandlerCompiler::CompileStoreField(LookupIterator* it) { 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 563958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(it->representation().IsHeapObject()); 564958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 565109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldType* field_type = *it->GetFieldType(); 566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool need_save_restore = false; 567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (RequiresFieldTypeChecks(field_type)) { 568f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch need_save_restore = IC::ShouldPushPopSlotAndVector(kind()); 569f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (Descriptor::kPassLastArgsOnStack) { 570f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue); 571f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (need_save_restore) PushVectorAndSlot(); 573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GenerateFieldTypeChecks(field_type, value(), &miss); 574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (need_save_restore) PopVectorAndSlot(); 575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 577958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier StoreFieldStub stub(isolate(), it->GetFieldIndex(), it->representation()); 578958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateTailCall(masm(), stub.GetCode()); 579958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&miss); 581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (need_save_restore) PopVectorAndSlot(); 582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TailCallBuiltin(masm(), MissBuiltin(kind())); 583bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return GetCode(kind(), it->name()); 584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter( 588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<JSObject> object, Handle<Name> name, int accessor_index, 589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int expected_arguments) { 590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register holder = Frontend(name); 591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GenerateStoreViaSetter(masm(), map(), receiver(), holder, accessor_index, 592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch expected_arguments, scratch2()); 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 594bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return GetCode(kind(), name); 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> object, Handle<Name> name, 599f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch const CallOptimization& call_optimization, int accessor_index, 600f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Code> slow_stub) { 601c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (V8_UNLIKELY(FLAG_runtime_stats)) { 602f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GenerateTailCall(masm(), slow_stub); 60313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 604f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Register holder = Frontend(name); 605f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (Descriptor::kPassLastArgsOnStack) { 606f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue); 607f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 608f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GenerateApiAccessorCall(masm(), call_optimization, handle(object->map()), 609f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch receiver(), scratch2(), true, value(), holder, 610f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch accessor_index); 611bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return GetCode(kind(), name); 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 617f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// static 618f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochHandle<Object> ElementHandlerCompiler::GetKeyedLoadHandler( 619f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Handle<Map> receiver_map, Isolate* isolate) { 620f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (receiver_map->has_indexed_interceptor() && 621f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch !receiver_map->GetIndexedInterceptor()->getter()->IsUndefined(isolate) && 622f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch !receiver_map->GetIndexedInterceptor()->non_masking()) { 623f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadIndexedInterceptorStub); 624f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return LoadIndexedInterceptorStub(isolate).GetCode(); 625f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 626f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (receiver_map->IsStringMap()) { 627f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadIndexedStringStub); 628f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return LoadIndexedStringStub(isolate).GetCode(); 629f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 630f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch InstanceType instance_type = receiver_map->instance_type(); 631f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (instance_type < FIRST_JS_RECEIVER_TYPE) { 632f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TRACE_HANDLER_STATS(isolate, KeyedLoadIC_SlowStub); 633f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return isolate->builtins()->KeyedLoadIC_Slow(); 634f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 636f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ElementsKind elements_kind = receiver_map->elements_kind(); 637f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (IsSloppyArgumentsElements(elements_kind)) { 638f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TRACE_HANDLER_STATS(isolate, KeyedLoadIC_KeyedLoadSloppyArgumentsStub); 639f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return KeyedLoadSloppyArgumentsStub(isolate).GetCode(); 640f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 641f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch bool is_js_array = instance_type == JS_ARRAY_TYPE; 642f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (elements_kind == DICTIONARY_ELEMENTS) { 643f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (FLAG_tf_load_ic_stub) { 644c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadElementDH); 645c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return LoadHandler::LoadElement(isolate, elements_kind, false, 646c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch is_js_array); 647f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 648f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadDictionaryElementStub); 649f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return LoadDictionaryElementStub(isolate).GetCode(); 650f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 651f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(IsFastElementsKind(elements_kind) || 652f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch IsFixedTypedArrayElementsKind(elements_kind)); 653f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // TODO(jkummerow): Use IsHoleyElementsKind(elements_kind). 654f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch bool convert_hole_to_undefined = 655f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch is_js_array && elements_kind == FAST_HOLEY_ELEMENTS && 656f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch *receiver_map == isolate->get_initial_js_array_map(elements_kind); 657f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (FLAG_tf_load_ic_stub) { 658c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadElementDH); 659c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return LoadHandler::LoadElement(isolate, elements_kind, 660c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch convert_hole_to_undefined, is_js_array); 661f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 662f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadFastElementStub); 663f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return LoadFastElementStub(isolate, is_js_array, elements_kind, 664f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch convert_hole_to_undefined) 665f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch .GetCode(); 666f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 667f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 669f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid ElementHandlerCompiler::CompileElementHandlers( 670f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch MapHandleList* receiver_maps, List<Handle<Object>>* handlers) { 671f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (int i = 0; i < receiver_maps->length(); ++i) { 672f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch handlers->Add(GetKeyedLoadHandler(receiver_maps->at(i), isolate())); 673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 677