diff options
Diffstat (limited to 'src/declarative/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch')
-rw-r--r-- | src/declarative/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch | 364 |
1 files changed, 364 insertions, 0 deletions
diff --git a/src/declarative/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch b/src/declarative/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch new file mode 100644 index 0000000000..daa2250a25 --- /dev/null +++ b/src/declarative/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch @@ -0,0 +1,364 @@ +From ae8688b53d67044f2c9b0cce25fc282b078610c1 Mon Sep 17 00:00:00 2001 +From: Aaron Kennedy <aaron.kennedy@nokia.com> +Date: Mon, 23 May 2011 16:21:02 +1000 +Subject: [PATCH 3/8] Add a "fallback" mode for named property interceptors + +By default interceptors are called before the normal property +resolution on objects. When an interceptor is installed as a +"fallback" interceptor, it is only called if the object doesn't +already have the property. + +In the case of a global object having an fallback interceptor, +the interceptor is not invoked at all for var or function +declarations. +--- + include/v8.h | 8 ++++++++ + src/api.cc | 29 +++++++++++++++++++++++++++++ + src/factory.cc | 4 ++++ + src/handles.cc | 6 ++++-- + src/handles.h | 3 ++- + src/objects-inl.h | 16 ++++++++++++++++ + src/objects.cc | 22 ++++++++++++++++------ + src/objects.h | 18 ++++++++++++++---- + src/runtime.cc | 11 ++++++----- + 9 files changed, 99 insertions(+), 18 deletions(-) + +diff --git a/include/v8.h b/include/v8.h +index bbd29e9..85452aa 100644 +--- a/include/v8.h ++++ b/include/v8.h +@@ -2169,6 +2169,7 @@ class V8EXPORT FunctionTemplate : public Template { + NamedPropertyQuery query, + NamedPropertyDeleter remover, + NamedPropertyEnumerator enumerator, ++ bool is_fallback, + Handle<Value> data); + void SetIndexedInstancePropertyHandler(IndexedPropertyGetter getter, + IndexedPropertySetter setter, +@@ -2253,6 +2254,13 @@ class V8EXPORT ObjectTemplate : public Template { + NamedPropertyEnumerator enumerator = 0, + Handle<Value> data = Handle<Value>()); + ++ void SetFallbackPropertyHandler(NamedPropertyGetter getter, ++ NamedPropertySetter setter = 0, ++ NamedPropertyQuery query = 0, ++ NamedPropertyDeleter deleter = 0, ++ NamedPropertyEnumerator enumerator = 0, ++ Handle<Value> data = Handle<Value>()); ++ + /** + * Sets an indexed property handler on the object template. + * +diff --git a/src/api.cc b/src/api.cc +index 381935b..8b0b32a 100644 +--- a/src/api.cc ++++ b/src/api.cc +@@ -981,6 +981,7 @@ void FunctionTemplate::SetNamedInstancePropertyHandler( + NamedPropertyQuery query, + NamedPropertyDeleter remover, + NamedPropertyEnumerator enumerator, ++ bool is_fallback, + Handle<Value> data) { + i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); + if (IsDeadCheck(isolate, +@@ -999,6 +1000,7 @@ void FunctionTemplate::SetNamedInstancePropertyHandler( + if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query); + if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover); + if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator); ++ obj->set_is_fallback(i::Smi::FromInt(is_fallback)); + + if (data.IsEmpty()) data = v8::Undefined(); + obj->set_data(*Utils::OpenHandle(*data)); +@@ -1143,6 +1145,33 @@ void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter, + query, + remover, + enumerator, ++ false, ++ data); ++} ++ ++ ++void ObjectTemplate::SetFallbackPropertyHandler(NamedPropertyGetter getter, ++ NamedPropertySetter setter, ++ NamedPropertyQuery query, ++ NamedPropertyDeleter remover, ++ NamedPropertyEnumerator enumerator, ++ Handle<Value> data) { ++ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ++ if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetFallbackPropertyHandler()")) { ++ return; ++ } ++ ENTER_V8(isolate); ++ i::HandleScope scope(isolate); ++ EnsureConstructor(this); ++ i::FunctionTemplateInfo* constructor = ++ i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor()); ++ i::Handle<i::FunctionTemplateInfo> cons(constructor); ++ Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter, ++ setter, ++ query, ++ remover, ++ enumerator, ++ true, + data); + } + +diff --git a/src/factory.cc b/src/factory.cc +index 7dee66f..dcdc645 100644 +--- a/src/factory.cc ++++ b/src/factory.cc +@@ -1058,6 +1058,10 @@ Handle<JSFunction> Factory::CreateApiFunction( + // Set interceptor information in the map. + if (!obj->named_property_handler()->IsUndefined()) { + map->set_has_named_interceptor(); ++ ++ InterceptorInfo *nph = InterceptorInfo::cast(obj->named_property_handler()); ++ bool is_fallback = nph->is_fallback()->IsUndefined()?false:nph->is_fallback()->value(); ++ map->set_named_interceptor_is_fallback(is_fallback); + } + if (!obj->indexed_property_handler()->IsUndefined()) { + map->set_has_indexed_interceptor(); +diff --git a/src/handles.cc b/src/handles.cc +index 326de86..dd3a86c 100644 +--- a/src/handles.cc ++++ b/src/handles.cc +@@ -262,9 +262,11 @@ Handle<Object> SetProperty(Handle<JSObject> object, + Handle<String> key, + Handle<Object> value, + PropertyAttributes attributes, +- StrictModeFlag strict_mode) { ++ StrictModeFlag strict_mode, ++ bool skip_fallback_interceptor) { + CALL_HEAP_FUNCTION(object->GetIsolate(), +- object->SetProperty(*key, *value, attributes, strict_mode), ++ object->SetProperty(*key, *value, attributes, strict_mode, ++ skip_fallback_interceptor), + Object); + } + +diff --git a/src/handles.h b/src/handles.h +index 3839f37..4b42506 100644 +--- a/src/handles.h ++++ b/src/handles.h +@@ -188,7 +188,8 @@ Handle<Object> SetProperty(Handle<JSObject> object, + Handle<String> key, + Handle<Object> value, + PropertyAttributes attributes, +- StrictModeFlag strict_mode); ++ StrictModeFlag strict_mode, ++ bool skip_fallback_interceptor = false); + + Handle<Object> SetProperty(Handle<Object> object, + Handle<Object> key, +diff --git a/src/objects-inl.h b/src/objects-inl.h +index cce3edd..6aaca2f 100644 +--- a/src/objects-inl.h ++++ b/src/objects-inl.h +@@ -2521,6 +2521,21 @@ bool Map::is_shared() { + } + + ++void Map::set_named_interceptor_is_fallback(bool value) ++{ ++ if (value) { ++ set_bit_field3(bit_field3() | (1 << kNamedInterceptorIsFallback)); ++ } else { ++ set_bit_field3(bit_field3() & ~(1 << kNamedInterceptorIsFallback)); ++ } ++} ++ ++bool Map::named_interceptor_is_fallback() ++{ ++ return ((1 << kNamedInterceptorIsFallback) & bit_field3()) != 0; ++} ++ ++ + JSFunction* Map::unchecked_constructor() { + return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset)); + } +@@ -2970,6 +2985,7 @@ ACCESSORS(InterceptorInfo, query, Object, kQueryOffset) + ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset) + ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset) + ACCESSORS(InterceptorInfo, data, Object, kDataOffset) ++ACCESSORS(InterceptorInfo, is_fallback, Smi, kFallbackOffset) + + ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset) + ACCESSORS(CallHandlerInfo, data, Object, kDataOffset) +diff --git a/src/objects.cc b/src/objects.cc +index 79d7240..15e2cdb 100644 +--- a/src/objects.cc ++++ b/src/objects.cc +@@ -1712,9 +1712,10 @@ MaybeObject* JSObject::SetPropertyWithInterceptor( + MaybeObject* JSObject::SetProperty(String* name, + Object* value, + PropertyAttributes attributes, +- StrictModeFlag strict_mode) { ++ StrictModeFlag strict_mode, ++ bool skip_fallback_interceptor) { + LookupResult result; +- LocalLookup(name, &result); ++ LocalLookup(name, &result, skip_fallback_interceptor); + return SetProperty(&result, name, value, attributes, strict_mode); + } + +@@ -3148,7 +3149,8 @@ AccessorDescriptor* Map::FindAccessor(String* name) { + } + + +-void JSObject::LocalLookup(String* name, LookupResult* result) { ++void JSObject::LocalLookup(String* name, LookupResult* result, ++ bool skip_fallback_interceptor) { + ASSERT(name->IsString()); + + Heap* heap = GetHeap(); +@@ -3174,22 +3176,30 @@ void JSObject::LocalLookup(String* name, LookupResult* result) { + } + + // Check for lookup interceptor except when bootstrapping. +- if (HasNamedInterceptor() && !heap->isolate()->bootstrapper()->IsActive()) { ++ bool wouldIntercept = HasNamedInterceptor() && !heap->isolate()->bootstrapper()->IsActive(); ++ if (wouldIntercept && !map()->named_interceptor_is_fallback()) { + result->InterceptorResult(this); + return; + } + + LocalLookupRealNamedProperty(name, result); ++ ++ if (wouldIntercept && !skip_fallback_interceptor && !result->IsProperty() && ++ map()->named_interceptor_is_fallback()) { ++ result->InterceptorResult(this); ++ return; ++ } + } + + +-void JSObject::Lookup(String* name, LookupResult* result) { ++void JSObject::Lookup(String* name, LookupResult* result, ++ bool skip_fallback_interceptor) { + // Ecma-262 3rd 8.6.2.4 + Heap* heap = GetHeap(); + for (Object* current = this; + current != heap->null_value(); + current = JSObject::cast(current)->GetPrototype()) { +- JSObject::cast(current)->LocalLookup(name, result); ++ JSObject::cast(current)->LocalLookup(name, result, skip_fallback_interceptor); + if (result->IsProperty()) return; + } + result->NotFound(); +diff --git a/src/objects.h b/src/objects.h +index 07e1089..a209cd0 100644 +--- a/src/objects.h ++++ b/src/objects.h +@@ -1405,7 +1405,8 @@ class JSObject: public HeapObject { + MUST_USE_RESULT MaybeObject* SetProperty(String* key, + Object* value, + PropertyAttributes attributes, +- StrictModeFlag strict_mode); ++ StrictModeFlag strict_mode, ++ bool skip_fallback_interceptor = false); + MUST_USE_RESULT MaybeObject* SetProperty(LookupResult* result, + String* key, + Object* value, +@@ -1637,8 +1638,8 @@ class JSObject: public HeapObject { + + // Lookup a property. If found, the result is valid and has + // detailed information. +- void LocalLookup(String* name, LookupResult* result); +- void Lookup(String* name, LookupResult* result); ++ void LocalLookup(String* name, LookupResult* result, bool skip_fallback_interceptor = false); ++ void Lookup(String* name, LookupResult* result, bool skip_fallback_interceptor = false); + + // The following lookup functions skip interceptors. + void LocalLookupRealNamedProperty(String* name, LookupResult* result); +@@ -3714,6 +3715,12 @@ class Map: public HeapObject { + inline void set_is_access_check_needed(bool access_check_needed); + inline bool is_access_check_needed(); + ++ ++ // Whether the named interceptor is a fallback interceptor or not ++ inline void set_named_interceptor_is_fallback(bool value); ++ inline bool named_interceptor_is_fallback(); ++ ++ + // [prototype]: implicit prototype object. + DECL_ACCESSORS(prototype, Object) + +@@ -3904,6 +3911,7 @@ class Map: public HeapObject { + static const int kHasExternalArrayElements = 6; + + // Bit positions for bit field 3 ++ static const int kNamedInterceptorIsFallback = 0; + + // Layout of the default cache. It holds alternating name and code objects. + static const int kCodeCacheEntrySize = 2; +@@ -6276,6 +6284,7 @@ class InterceptorInfo: public Struct { + DECL_ACCESSORS(deleter, Object) + DECL_ACCESSORS(enumerator, Object) + DECL_ACCESSORS(data, Object) ++ DECL_ACCESSORS(is_fallback, Smi) + + static inline InterceptorInfo* cast(Object* obj); + +@@ -6295,7 +6304,8 @@ class InterceptorInfo: public Struct { + static const int kDeleterOffset = kQueryOffset + kPointerSize; + static const int kEnumeratorOffset = kDeleterOffset + kPointerSize; + static const int kDataOffset = kEnumeratorOffset + kPointerSize; +- static const int kSize = kDataOffset + kPointerSize; ++ static const int kFallbackOffset = kDataOffset + kPointerSize; ++ static const int kSize = kFallbackOffset + kPointerSize; + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptorInfo); +diff --git a/src/runtime.cc b/src/runtime.cc +index 7335da8..660352c 100644 +--- a/src/runtime.cc ++++ b/src/runtime.cc +@@ -1097,7 +1097,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { + // Lookup the property in the global object, and don't set the + // value of the variable if the property is already there. + LookupResult lookup; +- global->Lookup(*name, &lookup); ++ global->Lookup(*name, &lookup, true); + if (lookup.IsProperty()) { + // Determine if the property is local by comparing the holder + // against the global object. The information will be used to +@@ -1152,7 +1152,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { + } + + LookupResult lookup; +- global->LocalLookup(*name, &lookup); ++ global->LocalLookup(*name, &lookup, true); + + PropertyAttributes attributes = is_const_property + ? static_cast<PropertyAttributes>(base | READ_ONLY) +@@ -1196,7 +1196,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { + name, + value, + attributes, +- strict_mode)); ++ strict_mode, ++ true)); + } + } + +@@ -1343,7 +1344,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { + JSObject* real_holder = global; + LookupResult lookup; + while (true) { +- real_holder->LocalLookup(*name, &lookup); ++ real_holder->LocalLookup(*name, &lookup, true); + if (lookup.IsProperty()) { + // Determine if this is a redeclaration of something read-only. + if (lookup.IsReadOnly()) { +@@ -1400,7 +1401,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { + + global = isolate->context()->global(); + if (assign) { +- return global->SetProperty(*name, args[2], attributes, strict_mode); ++ return global->SetProperty(*name, args[2], attributes, strict_mode, true); + } + return isolate->heap()->undefined_value(); + } +-- +1.7.2.3 + |