Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index ab6fa54859416d80a4601f1d25358bfe2cbd5221..d8608693245c22bc9003a8a3be43443b99115881 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -7994,8 +7994,9 @@ Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object, |
return Object::WrapForRead(isolate, raw_value, representation); |
} |
+enum class BoilerplateKind { kNormalBoilerplate, kApiBoilerplate }; |
-template<class ContextObject> |
+template <class ContextObject, BoilerplateKind boilerplate_kind> |
class JSObjectWalkVisitor { |
public: |
JSObjectWalkVisitor(ContextObject* site_context, bool copying, |
@@ -8027,10 +8028,9 @@ class JSObjectWalkVisitor { |
const JSObject::DeepCopyHints hints_; |
}; |
- |
-template <class ContextObject> |
-MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk( |
- Handle<JSObject> object) { |
+template <class ContextObject, BoilerplateKind boilerplate_kind> |
+MaybeHandle<JSObject> JSObjectWalkVisitor< |
+ ContextObject, boilerplate_kind>::StructureWalk(Handle<JSObject> object) { |
Isolate* isolate = this->isolate(); |
bool copying = this->copying(); |
bool shallow = hints_ == JSObject::kObjectIsShallow; |
@@ -8050,6 +8050,26 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk( |
Handle<JSObject> copy; |
if (copying) { |
+ if (boilerplate_kind == BoilerplateKind::kApiBoilerplate) { |
+ if (object->IsJSFunction()) { |
+#ifdef DEBUG |
+ // Ensure that it is an Api function and template_instantiations_cache |
+ // contains an entry for function's FunctionTemplateInfo. |
+ JSFunction* function = JSFunction::cast(*object); |
+ CHECK(function->shared()->IsApiFunction()); |
+ FunctionTemplateInfo* data = function->shared()->get_api_func_data(); |
+ auto serial_number = handle(Smi::cast(data->serial_number()), isolate); |
+ CHECK(serial_number->value()); |
+ auto cache = isolate->template_instantiations_cache(); |
+ Object* element = cache->Lookup(serial_number); |
+ CHECK_EQ(function, element); |
+#endif |
+ return object; |
+ } |
+ } else { |
+ // JSFunction objects are not allowed to be in normal boilerplates at all. |
+ DCHECK(!object->IsJSFunction()); |
+ } |
Handle<AllocationSite> site_to_pass; |
if (site_context()->ShouldCreateMemento(object)) { |
site_to_pass = site_context()->current(); |
@@ -8216,8 +8236,9 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk( |
MaybeHandle<JSObject> JSObject::DeepWalk( |
Handle<JSObject> object, |
AllocationSiteCreationContext* site_context) { |
- JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false, |
- kNoHints); |
+ JSObjectWalkVisitor<AllocationSiteCreationContext, |
+ BoilerplateKind::kNormalBoilerplate> v(site_context, |
+ false, kNoHints); |
MaybeHandle<JSObject> result = v.StructureWalk(object); |
Handle<JSObject> for_assert; |
DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object)); |
@@ -8229,13 +8250,35 @@ MaybeHandle<JSObject> JSObject::DeepCopy( |
Handle<JSObject> object, |
AllocationSiteUsageContext* site_context, |
DeepCopyHints hints) { |
- JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints); |
+ JSObjectWalkVisitor<AllocationSiteUsageContext, |
+ BoilerplateKind::kNormalBoilerplate> v(site_context, true, |
+ hints); |
MaybeHandle<JSObject> copy = v.StructureWalk(object); |
Handle<JSObject> for_assert; |
DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object)); |
return copy; |
} |
+class DummyContextObject : public AllocationSiteContext { |
+ public: |
+ explicit DummyContextObject(Isolate* isolate) |
+ : AllocationSiteContext(isolate) {} |
+ |
+ bool ShouldCreateMemento(Handle<JSObject> object) { return false; } |
+ Handle<AllocationSite> EnterNewScope() { return Handle<AllocationSite>(); } |
+ void ExitScope(Handle<AllocationSite> site, Handle<JSObject> object) {} |
+}; |
+ |
+MaybeHandle<JSObject> JSObject::DeepCopyApiBoilerplate( |
+ Handle<JSObject> object) { |
+ DummyContextObject dummy_context_object(object->GetIsolate()); |
+ JSObjectWalkVisitor<DummyContextObject, BoilerplateKind::kApiBoilerplate> v( |
+ &dummy_context_object, true, kNoHints); |
+ MaybeHandle<JSObject> copy = v.StructureWalk(object); |
+ Handle<JSObject> for_assert; |
+ DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object)); |
+ return copy; |
+} |
// static |
MaybeHandle<Object> JSReceiver::ToPrimitive(Handle<JSReceiver> receiver, |