Revision: 19756
Author: [email protected]
Date: Mon Mar 10 12:23:05 2014 UTC
Log: Reland and fix "Allow ICs to be generated for own global proxy."
BUG=
[email protected]
Review URL: https://codereview.chromium.org/176793003
http://code.google.com/p/v8/source/detail?r=19756
Added:
/branches/bleeding_edge/test/mjsunit/regress/regress-store-global-proxy.js
Modified:
/branches/bleeding_edge/src/arm/stub-cache-arm.cc
/branches/bleeding_edge/src/code-stubs-hydrogen.cc
/branches/bleeding_edge/src/code-stubs.h
/branches/bleeding_edge/src/ic.cc
/branches/bleeding_edge/src/isolate.cc
/branches/bleeding_edge/src/mips/stub-cache-mips.cc
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/runtime.cc
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/regress/regress-store-global-proxy.js
Mon Mar 10 12:23:05 2014 UTC
@@ -0,0 +1,12 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+delete Object.prototype.__proto__;
+
+function f() {
+ this.toString = 1;
+}
+
+f.apply({});
+f();
=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Mon Mar 10 08:40:03
2014 UTC
+++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Mon Mar 10 12:23:05
2014 UTC
@@ -1303,21 +1303,6 @@
Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
Handle<JSObject> object,
Handle<Name> name) {
- Label miss;
-
- // Check that the map of the object hasn't changed.
- __ CheckMap(receiver(), scratch1(), Handle<Map>(object->map()), &miss,
- DO_SMI_CHECK);
-
- // Perform global security token check if needed.
- if (object->IsJSGlobalProxy()) {
- __ CheckAccessGlobalProxy(receiver(), scratch1(), &miss);
- }
-
- // Stub is never generated for non-global objects that require access
- // checks.
- ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
-
__ Push(receiver(), this->name(), value());
// Do tail-call to the runtime system.
@@ -1325,10 +1310,6 @@
ExternalReference(IC_Utility(IC::kStoreInterceptorProperty),
isolate());
__ TailCallExternalReference(store_ic_property, 3, 1);
- // Handle store cache miss.
- __ bind(&miss);
- TailCallBuiltin(masm(), MissBuiltin(kind()));
-
// Return the generated code.
return GetCode(kind(), Code::FAST, name);
}
=======================================
--- /branches/bleeding_edge/src/code-stubs-hydrogen.cc Tue Feb 25 16:11:58
2014 UTC
+++ /branches/bleeding_edge/src/code-stubs-hydrogen.cc Mon Mar 10 12:23:05
2014 UTC
@@ -1049,13 +1049,16 @@
Handle<PropertyCell> 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<Map> placeholder_map = isolate()->factory()->meta_map();
- Add<HCheckMaps>(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<Map> placeholder_map = isolate()->factory()->meta_map();
+ HValue* global = Add<HConstant>(
+ StoreGlobalStub::global_placeholder(isolate()));
+ Add<HCheckMaps>(global, placeholder_map, top_info());
+ }
HValue* cell = Add<HConstant>(placeholder_cell);
HObjectAccess access(HObjectAccess::ForCellPayload(isolate()));
=======================================
--- /branches/bleeding_edge/src/code-stubs.h Tue Mar 4 12:48:17 2014 UTC
+++ /branches/bleeding_edge/src/code-stubs.h Mon Mar 10 12:23:05 2014 UTC
@@ -962,19 +962,27 @@
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<HeapObject> global_placeholder(Isolate* isolate) {
+ return isolate->factory()->uninitialized_value();
}
Handle<Code> GetCodeCopyFromTemplate(Isolate* isolate,
- Map* receiver_map,
+ GlobalObject* global,
PropertyCell* cell) {
Handle<Code> 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;
}
@@ -986,9 +994,12 @@
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);
}
@@ -1005,6 +1016,7 @@
class IsConstantBits: public BitField<bool, 0, 1> {};
class RepresentationBits: public BitField<Representation::Kind, 1, 8> {};
+ class CheckGlobalBits: public BitField<bool, 9, 1> {};
DISALLOW_COPY_AND_ASSIGN(StoreGlobalStub);
};
=======================================
--- /branches/bleeding_edge/src/ic.cc Mon Mar 10 08:40:03 2014 UTC
+++ /branches/bleeding_edge/src/ic.cc Mon Mar 10 12:23:05 2014 UTC
@@ -1072,7 +1072,7 @@
maybe_object = LoadIC::Load(object, Handle<String>::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()) {
@@ -1111,22 +1111,20 @@
Handle<JSObject> holder = receiver;
receiver->Lookup(*name, lookup);
if (lookup->IsFound()) {
- if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false;
-
- if (lookup->holder() == *receiver) {
- if (lookup->IsInterceptor() && !HasInterceptorSetter(*receiver)) {
- receiver->LocalLookupRealNamedProperty(*name, lookup);
- return lookup->IsFound() &&
- !lookup->IsReadOnly() &&
- lookup->CanHoldValue(value) &&
- lookup->IsCacheable();
- }
- return lookup->CanHoldValue(value);
+ if (lookup->IsInterceptor()
&& !HasInterceptorSetter(lookup->holder())) {
+ receiver->LocalLookupRealNamedProperty(*name, lookup);
+ if (!lookup->IsFound()) return false;
}
+ if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false;
+ if (lookup->holder() == *receiver) return lookup->CanHoldValue(value);
if (lookup->IsPropertyCallbacks()) return true;
- // JSGlobalProxy always goes via the runtime, so it's safe to cache.
- if (receiver->IsJSGlobalProxy()) return true;
+ // 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 lookup->holder() == receiver->GetPrototype();
+ }
// Currently normal holders in the prototype chain are not supported.
They
// would require a runtime positive lookup and verification that the
details
// have not changed.
@@ -1311,7 +1309,7 @@
Handle<String> name,
Handle<Object> 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<JSObject> receiver = Handle<JSObject>::cast(object);
@@ -1335,17 +1333,19 @@
}
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<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
+ Handle<GlobalObject> global = receiver->IsJSGlobalProxy()
+ ? handle(GlobalObject::cast(receiver->GetPrototype()))
+ : Handle<GlobalObject>::cast(receiver);
Handle<PropertyCell> cell(global->GetPropertyCell(lookup),
isolate());
Handle<HeapType> union_type = PropertyCell::UpdatedType(cell,
value);
- StoreGlobalStub stub(union_type->IsConstant());
-
+ StoreGlobalStub stub(
+ union_type->IsConstant(), receiver->IsJSGlobalProxy());
Handle<Code> 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;
@@ -1385,7 +1385,7 @@
}
case INTERCEPTOR:
if (kind() == Code::KEYED_STORE_IC) break;
- ASSERT(HasInterceptorSetter(*receiver));
+ ASSERT(HasInterceptorSetter(*holder));
return compiler.CompileStoreInterceptor(receiver, name);
case CONSTANT:
break;
@@ -1681,7 +1681,7 @@
}
if (use_ic) {
- ASSERT(!object->IsJSGlobalProxy());
+ ASSERT(!object->IsAccessCheckNeeded());
if (object->IsJSObject()) {
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
=======================================
--- /branches/bleeding_edge/src/isolate.cc Mon Mar 10 08:56:48 2014 UTC
+++ /branches/bleeding_edge/src/isolate.cc Mon Mar 10 12:23:05 2014 UTC
@@ -778,7 +778,7 @@
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::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());
=======================================
--- /branches/bleeding_edge/src/mips/stub-cache-mips.cc Tue Mar 4 20:22:56
2014 UTC
+++ /branches/bleeding_edge/src/mips/stub-cache-mips.cc Mon Mar 10 12:23:05
2014 UTC
@@ -1293,21 +1293,6 @@
Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
Handle<JSObject> object,
Handle<Name> name) {
- Label miss;
-
- // Check that the map of the object hasn't changed.
- __ CheckMap(receiver(), scratch1(), Handle<Map>(object->map()), &miss,
- DO_SMI_CHECK);
-
- // Perform global security token check if needed.
- if (object->IsJSGlobalProxy()) {
- __ CheckAccessGlobalProxy(receiver(), scratch1(), &miss);
- }
-
- // Stub is never generated for non-global objects that require access
- // checks.
- ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
-
__ Push(receiver(), this->name(), value());
// Do tail-call to the runtime system.
@@ -1315,10 +1300,6 @@
ExternalReference(IC_Utility(IC::kStoreInterceptorProperty),
isolate());
__ TailCallExternalReference(store_ic_property, 3, 1);
- // Handle store cache miss.
- __ bind(&miss);
- TailCallBuiltin(masm(), MissBuiltin(kind()));
-
// Return the generated code.
return GetCode(kind(), Code::FAST, name);
}
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Fri Mar 7 10:12:17 2014 UTC
+++ /branches/bleeding_edge/src/objects-inl.h Mon Mar 10 12:23:05 2014 UTC
@@ -926,7 +926,8 @@
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;
}
@@ -951,8 +952,14 @@
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();
}
=======================================
--- /branches/bleeding_edge/src/objects.h Mon Mar 10 08:28:59 2014 UTC
+++ /branches/bleeding_edge/src/objects.h Mon Mar 10 12:23:05 2014 UTC
@@ -2361,10 +2361,6 @@
// been modified since it was created. May give false positives.
bool IsDirty();
- // If the receiver is a JSGlobalProxy this method will return its
prototype,
- // otherwise the result is the receiver itself.
- inline Object* BypassGlobalProxy();
-
// Accessors for hidden properties object.
//
// Hidden properties are not local properties of the object itself.
=======================================
--- /branches/bleeding_edge/src/runtime.cc Mon Mar 10 08:28:59 2014 UTC
+++ /branches/bleeding_edge/src/runtime.cc Mon Mar 10 12:23:05 2014 UTC
@@ -14716,7 +14716,7 @@
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<Object> key = args.at<Object>(2);
SaveContext save(isolate);
isolate->set_context(observer->context());
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.