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
This commit is contained in:
parent
35d2e17646
commit
1984ebad50
@ -1030,13 +1030,16 @@ HValue* CodeStubGraphBuilder<StoreGlobalStub>::BuildCodeInitializedStub() {
|
|||||||
Handle<PropertyCell> placeholder_cell =
|
Handle<PropertyCell> placeholder_cell =
|
||||||
isolate()->factory()->NewPropertyCell(placeholer_value);
|
isolate()->factory()->NewPropertyCell(placeholer_value);
|
||||||
|
|
||||||
HParameter* receiver = GetParameter(0);
|
|
||||||
HParameter* value = GetParameter(2);
|
HParameter* value = GetParameter(2);
|
||||||
|
|
||||||
// Check that the map of the global has not changed: use a placeholder map
|
if (stub->check_global()) {
|
||||||
// that will be replaced later with the global object's map.
|
// Check that the map of the global has not changed: use a placeholder map
|
||||||
Handle<Map> placeholder_map = isolate()->factory()->meta_map();
|
// that will be replaced later with the global object's map.
|
||||||
Add<HCheckMaps>(receiver, placeholder_map, top_info());
|
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);
|
HValue* cell = Add<HConstant>(placeholder_cell);
|
||||||
HObjectAccess access(HObjectAccess::ForCellPayload(isolate()));
|
HObjectAccess access(HObjectAccess::ForCellPayload(isolate()));
|
||||||
|
@ -954,19 +954,27 @@ class LoadFieldStub: public HandlerStub {
|
|||||||
|
|
||||||
class StoreGlobalStub : public HandlerStub {
|
class StoreGlobalStub : public HandlerStub {
|
||||||
public:
|
public:
|
||||||
explicit StoreGlobalStub(bool is_constant) {
|
explicit StoreGlobalStub(bool is_constant, bool check_global) {
|
||||||
bit_field_ = IsConstantBits::encode(is_constant);
|
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,
|
Handle<Code> GetCodeCopyFromTemplate(Isolate* isolate,
|
||||||
Map* receiver_map,
|
GlobalObject* global,
|
||||||
PropertyCell* cell) {
|
PropertyCell* cell) {
|
||||||
Handle<Code> code = CodeStub::GetCodeCopyFromTemplate(isolate);
|
Handle<Code> code = CodeStub::GetCodeCopyFromTemplate(isolate);
|
||||||
// Replace the placeholder cell and global object map with the actual global
|
if (check_global()) {
|
||||||
// cell and receiver map.
|
// 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();
|
Map* cell_map = isolate->heap()->global_property_cell_map();
|
||||||
code->ReplaceNthObject(1, cell_map, cell);
|
code->ReplaceNthObject(1, cell_map, cell);
|
||||||
code->ReplaceNthObject(1, isolate->heap()->meta_map(), receiver_map);
|
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -978,9 +986,12 @@ class StoreGlobalStub : public HandlerStub {
|
|||||||
Isolate* isolate,
|
Isolate* isolate,
|
||||||
CodeStubInterfaceDescriptor* descriptor);
|
CodeStubInterfaceDescriptor* descriptor);
|
||||||
|
|
||||||
bool is_constant() {
|
bool is_constant() const {
|
||||||
return IsConstantBits::decode(bit_field_);
|
return IsConstantBits::decode(bit_field_);
|
||||||
}
|
}
|
||||||
|
bool check_global() const {
|
||||||
|
return CheckGlobalBits::decode(bit_field_);
|
||||||
|
}
|
||||||
void set_is_constant(bool value) {
|
void set_is_constant(bool value) {
|
||||||
bit_field_ = IsConstantBits::update(bit_field_, value);
|
bit_field_ = IsConstantBits::update(bit_field_, value);
|
||||||
}
|
}
|
||||||
@ -997,6 +1008,7 @@ class StoreGlobalStub : public HandlerStub {
|
|||||||
|
|
||||||
class IsConstantBits: public BitField<bool, 0, 1> {};
|
class IsConstantBits: public BitField<bool, 0, 1> {};
|
||||||
class RepresentationBits: public BitField<Representation::Kind, 1, 8> {};
|
class RepresentationBits: public BitField<Representation::Kind, 1, 8> {};
|
||||||
|
class CheckGlobalBits: public BitField<bool, 9, 1> {};
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(StoreGlobalStub);
|
DISALLOW_COPY_AND_ASSIGN(StoreGlobalStub);
|
||||||
};
|
};
|
||||||
|
22
src/ic.cc
22
src/ic.cc
@ -1069,7 +1069,7 @@ MaybeObject* KeyedLoadIC::Load(Handle<Object> object, Handle<Object> key) {
|
|||||||
maybe_object = LoadIC::Load(object, Handle<String>::cast(key));
|
maybe_object = LoadIC::Load(object, Handle<String>::cast(key));
|
||||||
if (maybe_object->IsFailure()) return maybe_object;
|
if (maybe_object->IsFailure()) return maybe_object;
|
||||||
} else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) {
|
} else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) {
|
||||||
ASSERT(!object->IsJSGlobalProxy());
|
ASSERT(!object->IsAccessCheckNeeded());
|
||||||
if (object->IsString() && key->IsNumber()) {
|
if (object->IsString() && key->IsNumber()) {
|
||||||
if (state() == UNINITIALIZED) stub = string_stub();
|
if (state() == UNINITIALIZED) stub = string_stub();
|
||||||
} else if (object->IsJSObject()) {
|
} else if (object->IsJSObject()) {
|
||||||
@ -1122,7 +1122,9 @@ static bool LookupForWrite(Handle<JSObject> receiver,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lookup->IsPropertyCallbacks()) return true;
|
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;
|
if (receiver->IsJSGlobalProxy()) return true;
|
||||||
// Currently normal holders in the prototype chain are not supported. They
|
// Currently normal holders in the prototype chain are not supported. They
|
||||||
// would require a runtime positive lookup and verification that the details
|
// would require a runtime positive lookup and verification that the details
|
||||||
@ -1309,7 +1311,7 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
|
|||||||
Handle<String> name,
|
Handle<String> name,
|
||||||
Handle<Object> value,
|
Handle<Object> value,
|
||||||
InlineCacheHolderFlag cache_holder) {
|
InlineCacheHolderFlag cache_holder) {
|
||||||
if (object->IsJSGlobalProxy()) return slow_stub();
|
if (object->IsAccessCheckNeeded()) return slow_stub();
|
||||||
ASSERT(cache_holder == OWN_MAP);
|
ASSERT(cache_holder == OWN_MAP);
|
||||||
// This is currently guaranteed by checks in StoreIC::Store.
|
// This is currently guaranteed by checks in StoreIC::Store.
|
||||||
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
|
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
|
||||||
@ -1337,17 +1339,19 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
|
|||||||
}
|
}
|
||||||
case NORMAL:
|
case NORMAL:
|
||||||
if (kind() == Code::KEYED_STORE_IC) break;
|
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
|
// The stub generated for the global object picks the value directly
|
||||||
// from the property cell. So the property must be directly on the
|
// from the property cell. So the property must be directly on the
|
||||||
// global object.
|
// 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<PropertyCell> cell(global->GetPropertyCell(lookup), isolate());
|
||||||
Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value);
|
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(
|
Handle<Code> code = stub.GetCodeCopyFromTemplate(
|
||||||
isolate(), receiver->map(), *cell);
|
isolate(), *global, *cell);
|
||||||
// TODO(verwaest): Move caching of these NORMAL stubs outside as well.
|
// TODO(verwaest): Move caching of these NORMAL stubs outside as well.
|
||||||
HeapObject::UpdateMapCodeCache(receiver, name, code);
|
HeapObject::UpdateMapCodeCache(receiver, name, code);
|
||||||
return code;
|
return code;
|
||||||
@ -1684,7 +1688,7 @@ MaybeObject* KeyedStoreIC::Store(Handle<Object> object,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (use_ic) {
|
if (use_ic) {
|
||||||
ASSERT(!object->IsJSGlobalProxy());
|
ASSERT(!object->IsAccessCheckNeeded());
|
||||||
|
|
||||||
if (object->IsJSObject()) {
|
if (object->IsJSObject()) {
|
||||||
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
|
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
|
||||||
|
@ -778,7 +778,7 @@ static MayAccessDecision MayAccessPreCheck(Isolate* isolate,
|
|||||||
|
|
||||||
bool Isolate::MayNamedAccess(JSObject* receiver, Object* key,
|
bool Isolate::MayNamedAccess(JSObject* receiver, Object* key,
|
||||||
v8::AccessType type) {
|
v8::AccessType type) {
|
||||||
ASSERT(receiver->IsAccessCheckNeeded());
|
ASSERT(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded());
|
||||||
|
|
||||||
// The callers of this method are not expecting a GC.
|
// The callers of this method are not expecting a GC.
|
||||||
DisallowHeapAllocation no_gc;
|
DisallowHeapAllocation no_gc;
|
||||||
@ -829,7 +829,7 @@ bool Isolate::MayNamedAccess(JSObject* receiver, Object* key,
|
|||||||
bool Isolate::MayIndexedAccess(JSObject* receiver,
|
bool Isolate::MayIndexedAccess(JSObject* receiver,
|
||||||
uint32_t index,
|
uint32_t index,
|
||||||
v8::AccessType type) {
|
v8::AccessType type) {
|
||||||
ASSERT(receiver->IsAccessCheckNeeded());
|
ASSERT(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded());
|
||||||
// Check for compatibility between the security tokens in the
|
// Check for compatibility between the security tokens in the
|
||||||
// current lexical context and the accessed object.
|
// current lexical context and the accessed object.
|
||||||
ASSERT(context());
|
ASSERT(context());
|
||||||
|
@ -927,7 +927,8 @@ bool Object::IsJSGlobalProxy() {
|
|||||||
bool result = IsHeapObject() &&
|
bool result = IsHeapObject() &&
|
||||||
(HeapObject::cast(this)->map()->instance_type() ==
|
(HeapObject::cast(this)->map()->instance_type() ==
|
||||||
JS_GLOBAL_PROXY_TYPE);
|
JS_GLOBAL_PROXY_TYPE);
|
||||||
ASSERT(!result || IsAccessCheckNeeded());
|
ASSERT(!result ||
|
||||||
|
HeapObject::cast(this)->map()->is_access_check_needed());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -952,8 +953,14 @@ bool Object::IsUndetectableObject() {
|
|||||||
|
|
||||||
|
|
||||||
bool Object::IsAccessCheckNeeded() {
|
bool Object::IsAccessCheckNeeded() {
|
||||||
return IsHeapObject()
|
if (!IsHeapObject()) return false;
|
||||||
&& HeapObject::cast(this)->map()->is_access_check_needed();
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -14649,7 +14649,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessAllowedForObserver) {
|
|||||||
ASSERT(args.length() == 3);
|
ASSERT(args.length() == 3);
|
||||||
CONVERT_ARG_HANDLE_CHECKED(JSFunction, observer, 0);
|
CONVERT_ARG_HANDLE_CHECKED(JSFunction, observer, 0);
|
||||||
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 1);
|
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 1);
|
||||||
ASSERT(object->IsAccessCheckNeeded());
|
ASSERT(object->map()->is_access_check_needed());
|
||||||
Handle<Object> key = args.at<Object>(2);
|
Handle<Object> key = args.at<Object>(2);
|
||||||
SaveContext save(isolate);
|
SaveContext save(isolate);
|
||||||
isolate->set_context(observer->context());
|
isolate->set_context(observer->context());
|
||||||
|
Loading…
Reference in New Issue
Block a user