From 1984ebad50b183bda93b5f9fb33c94feb91dff89 Mon Sep 17 00:00:00 2001 From: "verwaest@chromium.org" Date: Mon, 17 Feb 2014 13:12:56 +0000 Subject: [PATCH] Allow ICs to be generated for own global proxy. R=dcarney@chromium.org Review URL: https://codereview.chromium.org/166233004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19409 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/code-stubs-hydrogen.cc | 13 ++++++++----- src/code-stubs.h | 26 +++++++++++++++++++------- src/ic.cc | 22 +++++++++++++--------- src/isolate.cc | 4 ++-- src/objects-inl.h | 13 ++++++++++--- src/runtime.cc | 2 +- 6 files changed, 53 insertions(+), 27 deletions(-) diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc index 020514e08d..c0e66bc054 100644 --- a/src/code-stubs-hydrogen.cc +++ b/src/code-stubs-hydrogen.cc @@ -1030,13 +1030,16 @@ HValue* CodeStubGraphBuilder::BuildCodeInitializedStub() { Handle placeholder_cell = isolate()->factory()->NewPropertyCell(placeholer_value); - HParameter* receiver = GetParameter(0); HParameter* value = GetParameter(2); - // Check that the map of the global has not changed: use a placeholder map - // that will be replaced later with the global object's map. - Handle placeholder_map = isolate()->factory()->meta_map(); - Add(receiver, placeholder_map, top_info()); + if (stub->check_global()) { + // Check that the map of the global has not changed: use a placeholder map + // that will be replaced later with the global object's map. + Handle placeholder_map = isolate()->factory()->meta_map(); + HValue* global = Add( + StoreGlobalStub::global_placeholder(isolate())); + Add(global, placeholder_map, top_info()); + } HValue* cell = Add(placeholder_cell); HObjectAccess access(HObjectAccess::ForCellPayload(isolate())); diff --git a/src/code-stubs.h b/src/code-stubs.h index 90e7c0ddad..07e34be578 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h @@ -954,19 +954,27 @@ class LoadFieldStub: public HandlerStub { class StoreGlobalStub : public HandlerStub { public: - explicit StoreGlobalStub(bool is_constant) { - bit_field_ = IsConstantBits::encode(is_constant); + explicit StoreGlobalStub(bool is_constant, bool check_global) { + bit_field_ = IsConstantBits::encode(is_constant) | + CheckGlobalBits::encode(check_global); + } + + static Handle global_placeholder(Isolate* isolate) { + return isolate->factory()->uninitialized_value(); } Handle GetCodeCopyFromTemplate(Isolate* isolate, - Map* receiver_map, + GlobalObject* global, PropertyCell* cell) { Handle code = CodeStub::GetCodeCopyFromTemplate(isolate); - // Replace the placeholder cell and global object map with the actual global - // cell and receiver map. + if (check_global()) { + // Replace the placeholder cell and global object map with the actual + // global cell and receiver map. + code->ReplaceNthObject(1, global_placeholder(isolate)->map(), global); + code->ReplaceNthObject(1, isolate->heap()->meta_map(), global->map()); + } Map* cell_map = isolate->heap()->global_property_cell_map(); code->ReplaceNthObject(1, cell_map, cell); - code->ReplaceNthObject(1, isolate->heap()->meta_map(), receiver_map); return code; } @@ -978,9 +986,12 @@ class StoreGlobalStub : public HandlerStub { Isolate* isolate, CodeStubInterfaceDescriptor* descriptor); - bool is_constant() { + bool is_constant() const { return IsConstantBits::decode(bit_field_); } + bool check_global() const { + return CheckGlobalBits::decode(bit_field_); + } void set_is_constant(bool value) { bit_field_ = IsConstantBits::update(bit_field_, value); } @@ -997,6 +1008,7 @@ class StoreGlobalStub : public HandlerStub { class IsConstantBits: public BitField {}; class RepresentationBits: public BitField {}; + class CheckGlobalBits: public BitField {}; DISALLOW_COPY_AND_ASSIGN(StoreGlobalStub); }; diff --git a/src/ic.cc b/src/ic.cc index 44bc2f2e6b..dc9daffb82 100644 --- a/src/ic.cc +++ b/src/ic.cc @@ -1069,7 +1069,7 @@ MaybeObject* KeyedLoadIC::Load(Handle object, Handle key) { maybe_object = LoadIC::Load(object, Handle::cast(key)); if (maybe_object->IsFailure()) return maybe_object; } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { - ASSERT(!object->IsJSGlobalProxy()); + ASSERT(!object->IsAccessCheckNeeded()); if (object->IsString() && key->IsNumber()) { if (state() == UNINITIALIZED) stub = string_stub(); } else if (object->IsJSObject()) { @@ -1122,7 +1122,9 @@ static bool LookupForWrite(Handle receiver, } if (lookup->IsPropertyCallbacks()) return true; - // JSGlobalProxy always goes via the runtime, so it's safe to cache. + // JSGlobalProxy either stores on the global object in the prototype, or + // goes into the runtime if access checks are needed, so this is always + // safe. if (receiver->IsJSGlobalProxy()) return true; // Currently normal holders in the prototype chain are not supported. They // would require a runtime positive lookup and verification that the details @@ -1309,7 +1311,7 @@ Handle StoreIC::CompileHandler(LookupResult* lookup, Handle name, Handle value, InlineCacheHolderFlag cache_holder) { - if (object->IsJSGlobalProxy()) return slow_stub(); + if (object->IsAccessCheckNeeded()) return slow_stub(); ASSERT(cache_holder == OWN_MAP); // This is currently guaranteed by checks in StoreIC::Store. Handle receiver = Handle::cast(object); @@ -1337,17 +1339,19 @@ Handle StoreIC::CompileHandler(LookupResult* lookup, } case NORMAL: if (kind() == Code::KEYED_STORE_IC) break; - if (receiver->IsGlobalObject()) { + if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) { // The stub generated for the global object picks the value directly // from the property cell. So the property must be directly on the // global object. - Handle global = Handle::cast(receiver); + Handle global = receiver->IsJSGlobalProxy() + ? handle(GlobalObject::cast(receiver->GetPrototype())) + : Handle::cast(receiver); Handle cell(global->GetPropertyCell(lookup), isolate()); Handle union_type = PropertyCell::UpdatedType(cell, value); - StoreGlobalStub stub(union_type->IsConstant()); - + StoreGlobalStub stub( + union_type->IsConstant(), receiver->IsJSGlobalProxy()); Handle code = stub.GetCodeCopyFromTemplate( - isolate(), receiver->map(), *cell); + isolate(), *global, *cell); // TODO(verwaest): Move caching of these NORMAL stubs outside as well. HeapObject::UpdateMapCodeCache(receiver, name, code); return code; @@ -1684,7 +1688,7 @@ MaybeObject* KeyedStoreIC::Store(Handle object, } if (use_ic) { - ASSERT(!object->IsJSGlobalProxy()); + ASSERT(!object->IsAccessCheckNeeded()); if (object->IsJSObject()) { Handle receiver = Handle::cast(object); diff --git a/src/isolate.cc b/src/isolate.cc index a008b6a3c1..ca324603f7 100644 --- a/src/isolate.cc +++ b/src/isolate.cc @@ -778,7 +778,7 @@ static MayAccessDecision MayAccessPreCheck(Isolate* isolate, bool Isolate::MayNamedAccess(JSObject* receiver, Object* key, v8::AccessType type) { - ASSERT(receiver->IsAccessCheckNeeded()); + ASSERT(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded()); // The callers of this method are not expecting a GC. DisallowHeapAllocation no_gc; @@ -829,7 +829,7 @@ bool Isolate::MayNamedAccess(JSObject* receiver, Object* key, bool Isolate::MayIndexedAccess(JSObject* receiver, uint32_t index, v8::AccessType type) { - ASSERT(receiver->IsAccessCheckNeeded()); + ASSERT(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded()); // Check for compatibility between the security tokens in the // current lexical context and the accessed object. ASSERT(context()); diff --git a/src/objects-inl.h b/src/objects-inl.h index ea0dfe1637..7f2368839b 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -927,7 +927,8 @@ bool Object::IsJSGlobalProxy() { bool result = IsHeapObject() && (HeapObject::cast(this)->map()->instance_type() == JS_GLOBAL_PROXY_TYPE); - ASSERT(!result || IsAccessCheckNeeded()); + ASSERT(!result || + HeapObject::cast(this)->map()->is_access_check_needed()); return result; } @@ -952,8 +953,14 @@ bool Object::IsUndetectableObject() { bool Object::IsAccessCheckNeeded() { - return IsHeapObject() - && HeapObject::cast(this)->map()->is_access_check_needed(); + if (!IsHeapObject()) return false; + if (IsJSGlobalProxy()) { + JSGlobalProxy* proxy = JSGlobalProxy::cast(this); + GlobalObject* global = + proxy->GetIsolate()->context()->global_object(); + return proxy->IsDetachedFrom(global); + } + return HeapObject::cast(this)->map()->is_access_check_needed(); } diff --git a/src/runtime.cc b/src/runtime.cc index a7ed3a243b..d5768a459b 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -14649,7 +14649,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessAllowedForObserver) { ASSERT(args.length() == 3); CONVERT_ARG_HANDLE_CHECKED(JSFunction, observer, 0); CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 1); - ASSERT(object->IsAccessCheckNeeded()); + ASSERT(object->map()->is_access_check_needed()); Handle key = args.at(2); SaveContext save(isolate); isolate->set_context(observer->context());