Handle<PrototypeInfo>::cast(NewStruct(PROTOTYPE_INFO_TYPE));
result->set_prototype_users(WeakFixedArray::Empty());
result->set_validity_cell(Smi::FromInt(0));
+ result->set_constructor_name(Smi::FromInt(0));
return result;
}
CHECK(prototype_users()->IsSmi());
}
CHECK(validity_cell()->IsCell() || validity_cell()->IsSmi());
+ VerifyPointer(constructor_name());
}
ACCESSORS(PrototypeInfo, prototype_users, Object, kPrototypeUsersOffset)
ACCESSORS(PrototypeInfo, validity_cell, Object, kValidityCellOffset)
+ACCESSORS(PrototypeInfo, constructor_name, Object, kConstructorNameOffset)
ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
HeapObject::PrintHeader(os, "PrototypeInfo");
os << "\n - prototype users: " << Brief(prototype_users());
os << "\n - validity cell: " << Brief(validity_cell());
+ os << "\n - constructor name: " << Brief(constructor_name());
os << "\n";
}
String* Map::constructor_name() {
+ if (is_prototype_map() && prototype_info()->IsPrototypeInfo()) {
+ PrototypeInfo* proto_info = PrototypeInfo::cast(prototype_info());
+ if (proto_info->constructor_name()->IsString()) {
+ return String::cast(proto_info->constructor_name());
+ }
+ }
Object* maybe_constructor = GetConstructor();
if (maybe_constructor->IsJSFunction()) {
JSFunction* constructor = JSFunction::cast(maybe_constructor);
Handle<Map> new_map = Map::Copy(handle(object->map()), "CopyAsPrototype");
JSObject::MigrateToMap(object, new_map);
}
+ object->map()->set_is_prototype_map(true);
+
+ // Replace the pointer to the exact constructor with the Object function
+ // from the same context if undetectable from JS. This is to avoid keeping
+ // memory alive unnecessarily.
Object* maybe_constructor = object->map()->GetConstructor();
if (maybe_constructor->IsJSFunction()) {
JSFunction* constructor = JSFunction::cast(maybe_constructor);
- // Replace the pointer to the exact constructor with the Object function
- // from the same context if undetectable from JS. This is to avoid keeping
- // memory alive unnecessarily.
+ Isolate* isolate = object->GetIsolate();
if (!constructor->shared()->IsApiFunction() &&
- object->class_name() ==
- object->GetIsolate()->heap()->Object_string()) {
+ object->class_name() == isolate->heap()->Object_string()) {
+ Handle<String> constructor_name(object->constructor_name(), isolate);
Context* context = constructor->context()->native_context();
JSFunction* object_function = context->object_function();
object->map()->SetConstructor(object_function);
+ Handle<PrototypeInfo> proto_info =
+ Map::GetOrCreatePrototypeInfo(object, isolate);
+ proto_info->set_constructor_name(*constructor_name);
}
}
- object->map()->set_is_prototype_map(true);
}
}
// [validity_cell]: Cell containing the validity bit for prototype chains
// going through this object, or Smi(0) if uninitialized.
DECL_ACCESSORS(validity_cell, Object)
+ // [constructor_name]: User-friendly name of the original constructor.
+ DECL_ACCESSORS(constructor_name, Object)
DECLARE_CAST(PrototypeInfo)
static const int kPrototypeUsersOffset = HeapObject::kHeaderSize;
static const int kValidityCellOffset = kPrototypeUsersOffset + kPointerSize;
- static const int kSize = kValidityCellOffset + kPointerSize;
+ static const int kConstructorNameOffset = kValidityCellOffset + kPointerSize;
+ static const int kSize = kConstructorNameOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PrototypeInfo);
v8::Isolate* isolate = CcTest::isolate();
LocalContext context;
v8::HandleScope scope(isolate);
- v8_compile("function Parent() {};"
- "function Child() {};"
- "Child.prototype = new Parent();"
- "var outer = { inner: function() { } };"
- "var p = new Parent();"
- "var c = new Child();"
- "var x = new outer.inner();")->Run();
+ v8_compile(
+ "function Parent() {};"
+ "function Child() {};"
+ "Child.prototype = new Parent();"
+ "var outer = { inner: function() { } };"
+ "var p = new Parent();"
+ "var c = new Child();"
+ "var x = new outer.inner();"
+ "var proto = Child.prototype;")->Run();
Local<v8::Value> p = context->Global()->Get(v8_str("p"));
CHECK(p->IsObject() &&
CHECK(x->IsObject() &&
x->ToObject(isolate)->GetConstructorName()->Equals(
v8_str("outer.inner")));
+
+ Local<v8::Value> child_prototype = context->Global()->Get(v8_str("proto"));
+ CHECK(child_prototype->IsObject() &&
+ child_prototype->ToObject(isolate)->GetConstructorName()->Equals(
+ v8_str("Parent")));
}