1. Register canonical names for internal VM classes and get rid of the method GetSingletonClassName

2. Create the empty_array object as a singleton in the VM isolate and remove it from the object store
3. Remove eager population of the functions_cache entry in the class. This results in a pretty impressive reduction of the initial isolate heap size:
    - on IA32 it goes from 1331k to 1071k
    - on X64 it goes from 2431k to 1911k
    - snapshot size also is reduced from 859219 bytes to 789147 bytes.
    (as a follow up change I will consider completely removing functions cache)
Review URL: https://chromiumcodereview.appspot.com//10827249

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@10535 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
asiva@google.com
2012-08-10 21:43:00 +00:00
parent 929f158657
commit 5fd180cdfc
17 changed files with 159 additions and 122 deletions
+1 -1
View File
@@ -11,7 +11,7 @@ namespace dart {
static RawClass* CreateTestClass(const char* name) {
const Array& empty_array = Array::Handle(Array::Empty());
const Array& empty_array = Array::Handle(Object::empty_array());
const String& class_name = String::Handle(Symbols::New(name));
const Script& script = Script::Handle();
const Class& cls =
+1 -1
View File
@@ -80,7 +80,7 @@ RawArray* StackmapTableBuilder::FinalizeStackmaps(const Code& code) {
intptr_t num_entries = Length();
uword entry_point = code.EntryPoint();
if (num_entries == 0) {
return Array::Empty();
return Object::empty_array();
}
for (intptr_t i = 0; i < num_entries; i++) {
stack_map_ = Map(i);
+7
View File
@@ -1663,6 +1663,10 @@ void FunctionsCache::AddCompiledFunction(const Function& function,
#if 0
ASSERT(function.HasCode());
Array& cache = Array::Handle(class_.functions_cache());
if (cache.IsNull()) {
class_.InitFunctionsCache();
cache = class_.functions_cache();
}
// Search for first free slot. Last entry is always NULL object.
for (intptr_t i = 0; i < (cache.Length() - kNumEntries); i += kNumEntries) {
if (Object::Handle(cache.At(i)).IsNull()) {
@@ -1692,6 +1696,9 @@ RawCode* FunctionsCache::LookupCode(const String& function_name,
int num_arguments,
int num_named_arguments) {
const Array& cache = Array::Handle(class_.functions_cache());
if (cache.IsNull()) {
return Code::null(); // Functions cache has not been populated yet.
}
String& test_name = String::Handle();
for (intptr_t i = 0; i < cache.Length(); i += kNumEntries) {
test_name ^= cache.At(i + FunctionsCache::kFunctionName);
+2 -7
View File
@@ -412,13 +412,8 @@ void HeapProfiler::WriteLoadClass(const RawClass* raw_class) {
record.WritePointer(raw_class);
// stack trace serial number
record.Write32(0);
if (raw_class->ptr()->name_ == String::null()) {
intptr_t class_id = raw_class->ptr()->id_;
const char* name = Object::GetSingletonClassName(class_id);
record.WritePointer(StringId(name));
} else {
record.WritePointer(StringId(raw_class->ptr()->name_));
}
ASSERT(raw_class->ptr()->name_ != String::null());
record.WritePointer(StringId(raw_class->ptr()->name_));
}
+83 -95
View File
@@ -59,6 +59,7 @@ cpp_vtable Smi::handle_vtable_ = 0;
#endif
#define RAW_NULL kHeapObjectTag
RawObject* Object::null_ = reinterpret_cast<RawInstance*>(RAW_NULL);
RawArray* Object::empty_array_ = reinterpret_cast<RawArray*>(RAW_NULL);
RawInstance* Object::sentinel_ = reinterpret_cast<RawInstance*>(RAW_NULL);
RawInstance* Object::transition_sentinel_ =
reinterpret_cast<RawInstance*>(RAW_NULL);
@@ -185,47 +186,6 @@ static RawString* IdentifierPrettyName(const String& name) {
}
// TODO(asiva): Get rid of this function once we have predefined names for
// the shared classes and set that up in the name field.
const char* Object::GetSingletonClassName(intptr_t class_id) {
switch (class_id) {
case kClassCid: return "Class";
case kNullCid: return "Null";
case kDynamicCid: return "Dynamic";
case kVoidCid: return "void";
case kUnresolvedClassCid: return "UnresolvedClass";
case kTypeCid: return "Type";
case kTypeParameterCid: return "TypeParameter";
case kTypeArgumentsCid: return "TypeArguments";
case kInstantiatedTypeArgumentsCid: return "InstantiatedTypeArguments";
case kFunctionCid: return "Function";
case kFieldCid: return "Field";
case kLiteralTokenCid: return "LiteralToken";
case kTokenStreamCid: return "TokenStream";
case kScriptCid: return "Script";
case kLibraryCid: return "Library";
case kLibraryPrefixCid: return "LibraryPrefix";
case kCodeCid: return "Code";
case kInstructionsCid: return "Instructions";
case kPcDescriptorsCid: return "PcDescriptors";
case kStackmapCid: return "Stackmap";
case kLocalVarDescriptorsCid: return "LocalVarDescriptors";
case kExceptionHandlersCid: return "ExceptionHandlers";
case kContextCid: return "Context";
case kContextScopeCid: return "ContextScope";
case kICDataCid: return "ICData";
case kSubtypeTestCacheCid: return "SubtypeTestCache";
case kApiErrorCid: return "ApiError";
case kLanguageErrorCid: return "LanguageError";
case kUnhandledExceptionCid: return "UnhandledException";
case kUnwindErrorCid: return "UnwindError";
default: break;
}
UNREACHABLE();
return NULL;
}
void Object::InitOnce() {
// TODO(iposva): NoGCScope needs to be added here.
ASSERT(class_class() == null_);
@@ -239,7 +199,7 @@ void Object::InitOnce() {
Isolate* isolate = Isolate::Current();
Heap* heap = isolate->heap();
// Allocate and initialize the null instance, except its class_ field.
// Allocate and initialize the null instance.
// 'null_' must be the first object allocated as it is used in allocation to
// clear the object.
{
@@ -251,7 +211,7 @@ void Object::InitOnce() {
// Initialize object_store empty array to null_ in order to be able to check
// if the empty array was allocated (RAW_NULL is not available).
isolate->object_store()->set_empty_array(Array::Handle());
empty_array_ = Array::null();
Class& cls = Class::Handle();
@@ -303,14 +263,6 @@ void Object::InitOnce() {
transition_sentinel_ = transition_sentinel.raw();
}
// The interface "Dynamic" is not a VM internal class. It is the type class of
// the "unknown type". For efficiency, we allocate it in the VM isolate.
// Therefore, it cannot have a heap allocated name (the name is hard coded,
// see GetSingletonClassName) and its array fields cannot be set to the empty
// array, but remain null.
//
// TODO(turnidge): Once the empty array is allocated in the vm
// isolate, use it here.
cls = Class::New<Instance>(kDynamicCid);
cls.set_is_finalized();
cls.set_is_interface();
@@ -411,6 +363,57 @@ void Object::InitOnce() {
isolate->object_store()->set_array_class(cls);
cls = Class::New<OneByteString>();
isolate->object_store()->set_one_byte_string_class(cls);
// Allocate and initialize the empty_array instance.
{
uword address = heap->Allocate(Array::InstanceSize(0), Heap::kOld);
empty_array_ = reinterpret_cast<RawArray*>(address + kHeapObjectTag);
InitializeObject(address, kArrayCid, Array::InstanceSize(0));
empty_array_->ptr()->length_ = Smi::New(0);
}
}
#define SET_CLASS_NAME(class_name, name) \
cls = class_name##_class(); \
str = Symbols::name(); \
cls.set_name(str); \
void Object::RegisterSingletonClassNames() {
Class& cls = Class::Handle();
String& str = String::Handle();
SET_CLASS_NAME(class, Class);
SET_CLASS_NAME(null, Null);
SET_CLASS_NAME(dynamic, Dynamic);
SET_CLASS_NAME(void, Void);
SET_CLASS_NAME(unresolved_class, UnresolvedClass);
SET_CLASS_NAME(type, Type);
SET_CLASS_NAME(type_parameter, TypeParameter);
SET_CLASS_NAME(type_arguments, TypeArguments);
SET_CLASS_NAME(instantiated_type_arguments, InstantiatedTypeArguments);
SET_CLASS_NAME(function, Function);
SET_CLASS_NAME(field, Field);
SET_CLASS_NAME(literal_token, LiteralToken);
SET_CLASS_NAME(token_stream, TokenStream);
SET_CLASS_NAME(script, Script);
SET_CLASS_NAME(library, LibraryClass);
SET_CLASS_NAME(library_prefix, LibraryPrefix);
SET_CLASS_NAME(code, Code);
SET_CLASS_NAME(instructions, Instructions);
SET_CLASS_NAME(pc_descriptors, PcDescriptors);
SET_CLASS_NAME(stackmap, Stackmap);
SET_CLASS_NAME(var_descriptors, LocalVarDescriptors);
SET_CLASS_NAME(exception_handlers, ExceptionHandlers);
SET_CLASS_NAME(deopt_info, DeoptInfo);
SET_CLASS_NAME(context, Context);
SET_CLASS_NAME(context_scope, ContextScope);
SET_CLASS_NAME(icdata, ICData);
SET_CLASS_NAME(subtypetestcache, SubtypeTestCache);
SET_CLASS_NAME(api_error, ApiError);
SET_CLASS_NAME(language_error, LanguageError);
SET_CLASS_NAME(unhandled_exception, UnhandledException);
SET_CLASS_NAME(unwind_error, UnwindError);
}
@@ -468,14 +471,6 @@ RawError* Object::Init(Isolate* isolate) {
// declared in RawArray.
cls.set_type_arguments_instance_field_offset(Array::type_arguments_offset());
Array& empty_array = Array::Handle();
empty_array = Array::New(0, Heap::kOld);
object_store->set_empty_array(empty_array);
// Re-initialize fields of the array class now that the empty array
// has been created.
cls.InitEmptyFields();
// Set up the growable object array class (Has to be done after the array
// class is setup as one of its field is an array object).
cls = Class::New<GrowableObjectArray>();
@@ -835,10 +830,6 @@ void Object::InitFromSnapshot(Isolate* isolate) {
cls = Class::New<Array>();
object_store->set_array_class(cls);
Array& empty_array = Array::Handle();
empty_array = Array::New(0);
object_store->set_empty_array(empty_array);
cls = Class::New<ImmutableArray>();
object_store->set_immutable_array_class(cls);
@@ -1037,11 +1028,8 @@ RawObject* Object::Clone(const Object& src, Heap::Space space) {
RawString* Class::Name() const {
if (raw_ptr()->name_ != String::null()) {
return raw_ptr()->name_;
}
ASSERT(class_class() != Class::null()); // class_class_ should be set up.
return Symbols::New(GetSingletonClassName(raw_ptr()->id_));
ASSERT(raw_ptr()->name_ != String::null());
return raw_ptr()->name_;
}
@@ -1186,20 +1174,22 @@ RawClass* Class::New() {
// Initialize class fields of type Array with empty array.
void Class::InitEmptyFields() {
const Array& empty_array = Array::Handle(Array::Empty());
if (empty_array.IsNull()) {
if (Object::empty_array() == Array::null()) {
// The empty array has not been initialized yet.
return;
}
StorePointer(&raw_ptr()->interfaces_, empty_array.raw());
// TODO(srdjan): Make functions_cache growable and start with a smaller size.
Array& fcache =
Array::Handle(Array::New(FunctionsCache::kNumEntries * 32, Heap::kOld));
StorePointer(&raw_ptr()->functions_cache_, fcache.raw());
StorePointer(&raw_ptr()->constants_, empty_array.raw());
StorePointer(&raw_ptr()->canonical_types_, empty_array.raw());
StorePointer(&raw_ptr()->functions_, empty_array.raw());
StorePointer(&raw_ptr()->fields_, empty_array.raw());
StorePointer(&raw_ptr()->interfaces_, Object::empty_array());
StorePointer(&raw_ptr()->constants_, Object::empty_array());
StorePointer(&raw_ptr()->canonical_types_, Object::empty_array());
StorePointer(&raw_ptr()->functions_, Object::empty_array());
StorePointer(&raw_ptr()->fields_, Object::empty_array());
}
void Class::InitFunctionsCache() const {
// TODO(srdjan): Make functions_cache growable and start with smaller size.
StorePointer(&raw_ptr()->functions_cache_,
Array::New(FunctionsCache::kNumEntries * 32, Heap::kOld));
}
@@ -1564,12 +1554,13 @@ RawClass* Class::NewSignatureClass(const String& name,
const intptr_t token_pos = signature_function.token_pos();
Class& result = Class::Handle(New<Closure>(name, script, token_pos));
const Type& super_type = Type::Handle(Type::ObjectType());
const Array& empty_array = Array::Handle(Object::empty_array());
ASSERT(!super_type.IsNull());
result.set_super_type(super_type);
result.set_signature_function(signature_function);
result.set_type_parameters(type_parameters);
result.SetFields(Array::Handle(Array::Empty()));
result.SetFunctions(Array::Handle(Array::Empty()));
result.SetFields(empty_array);
result.SetFunctions(empty_array);
result.set_type_arguments_instance_field_offset(
Closure::type_arguments_offset());
// Implements interface "Function".
@@ -1623,9 +1614,10 @@ RawClass* Class::NewNativeWrapper(Library* library,
int field_count) {
Class& cls = Class::Handle(library->LookupClass(name));
if (cls.IsNull()) {
const Array& empty_array = Array::Handle(Object::empty_array());
cls = New<Instance>(name, Script::Handle(), Scanner::kDummyTokenIndex);
cls.SetFields(Array::Handle(Array::Empty()));
cls.SetFunctions(Array::Handle(Array::Empty()));
cls.SetFields(empty_array);
cls.SetFunctions(empty_array);
// Set super class to Object.
cls.set_super_type(Type::Handle(Type::ObjectType()));
// Compute instance size.
@@ -4022,8 +4014,9 @@ RawFunction* Function::New(const String& name,
ASSERT(name.IsOneByteString());
ASSERT(!owner.IsNull());
const Function& result = Function::Handle(Function::New());
result.set_parameter_types(Array::Handle(Array::Empty()));
result.set_parameter_names(Array::Handle(Array::Empty()));
const Array& empty_array = Array::Handle(Object::empty_array());
result.set_parameter_types(empty_array);
result.set_parameter_names(empty_array);
result.set_name(name);
result.set_kind(kind);
result.set_is_static(is_static);
@@ -6044,10 +6037,10 @@ RawLibrary* Library::NewLibraryHelper(const String& url,
result.StorePointer(&result.raw_ptr()->name_, url.raw());
result.StorePointer(&result.raw_ptr()->url_, url.raw());
result.raw_ptr()->private_key_ = Scanner::AllocatePrivateKey(result);
result.raw_ptr()->dictionary_ = Array::Empty();
result.raw_ptr()->anonymous_classes_ = Array::Empty();
result.raw_ptr()->dictionary_ = Object::empty_array();
result.raw_ptr()->anonymous_classes_ = Object::empty_array();
result.raw_ptr()->num_anonymous_ = 0;
result.raw_ptr()->imports_ = Array::Empty();
result.raw_ptr()->imports_ = Object::empty_array();
result.raw_ptr()->loaded_scripts_ = Array::null();
result.set_native_entry_resolver(NULL);
result.raw_ptr()->corelib_imported_ = true;
@@ -7014,7 +7007,7 @@ Code::Comments& Code::Comments::New(intptr_t count) {
FATAL1("Fatal error in Code::Comments::New: invalid count %ld\n", count);
}
if (count == 0) {
comments = new Comments(Array::Empty());
comments = new Comments(Object::empty_array());
} else {
comments = new Comments(Array::New(count * kNumberOfEntries));
}
@@ -9980,17 +9973,12 @@ RawArray* Array::Grow(const Array& source, int new_length, Heap::Space space) {
}
RawArray* Array::Empty() {
return Isolate::Current()->object_store()->empty_array();
}
RawArray* Array::MakeArray(const GrowableObjectArray& growable_array) {
intptr_t used_len = growable_array.Length();
intptr_t capacity_len = growable_array.Capacity();
Isolate* isolate = Isolate::Current();
const Array& array = Array::Handle(isolate, growable_array.data());
const Array& new_array = Array::Handle(isolate, Array::Empty());
const Array& new_array = Array::Handle(isolate, Object::empty_array());
intptr_t capacity_size = Array::InstanceSize(capacity_len);
intptr_t used_size = Array::InstanceSize(used_len);
NoGCScope no_gc;
+6 -5
View File
@@ -235,6 +235,7 @@ CLASS_LIST_NO_OBJECT(DEFINE_CLASS_TESTER);
}
static RawObject* null() { return null_; }
static RawArray* empty_array() { return empty_array_; }
// The sentinel is a value that cannot be produced by Dart code.
// It can be used to mark special values, for example to distinguish
@@ -284,8 +285,6 @@ CLASS_LIST_NO_OBJECT(DEFINE_CLASS_TESTER);
static RawClass* icdata_class() { return icdata_class_; }
static RawClass* subtypetestcache_class() { return subtypetestcache_class_; }
static const char* GetSingletonClassName(intptr_t class_id);
static RawClass* CreateAndRegisterInterface(const char* cname,
const Script& script,
const Library& lib);
@@ -302,6 +301,7 @@ CLASS_LIST_NO_OBJECT(DEFINE_CLASS_TESTER);
static RawError* Init(Isolate* isolate);
static void InitFromSnapshot(Isolate* isolate);
static void InitOnce();
static void RegisterSingletonClassNames();
static intptr_t InstanceSize() {
return RoundedAllocationSize(sizeof(RawObject));
@@ -376,6 +376,7 @@ CLASS_LIST_NO_OBJECT(DEFINE_CLASS_TESTER);
// The static values below are singletons shared between the different
// isolates. They are all allocated in the non-GC'd Dart::vm_isolate_.
static RawObject* null_;
static RawArray* empty_array_;
static RawInstance* sentinel_;
static RawInstance* transition_sentinel_;
@@ -687,6 +688,9 @@ class Class : public Object {
void Finalize() const;
// Initialize the functions cache array.
void InitFunctionsCache() const;
// Allocate a class used for VM internal objects.
template <class FakeObject> static RawClass* New();
@@ -3928,9 +3932,6 @@ class Array : public Instance {
int new_length,
Heap::Space space = Heap::kNew);
// Returns the preallocated empty array, used to initialize array fields.
static RawArray* Empty();
// Return an Array object that contains all the elements currently present
// in the specified Growable Object Array. This is done by first truncating
// the Growable Object Array's backing array to the currently used size and
-1
View File
@@ -61,7 +61,6 @@ ObjectStore::ObjectStore()
jsregexp_class_(Class::null()),
true_value_(Bool::null()),
false_value_(Bool::null()),
empty_array_(Array::null()),
symbol_table_(Array::null()),
canonical_type_arguments_(Array::null()),
core_library_(Library::null()),
-4
View File
@@ -421,9 +421,6 @@ class ObjectStore {
RawBool* false_value() const { return false_value_; }
void set_false_value(const Bool& value) { false_value_ = value.raw(); }
RawArray* empty_array() const { return empty_array_; }
void set_empty_array(const Array& value) { empty_array_ = value.raw(); }
RawContext* empty_context() const { return empty_context_; }
void set_empty_context(const Context& value) {
empty_context_ = value.raw();
@@ -514,7 +511,6 @@ class ObjectStore {
RawClass* jsregexp_class_;
RawBool* true_value_;
RawBool* false_value_;
RawArray* empty_array_;
RawArray* symbol_table_;
RawArray* canonical_type_arguments_;
RawLibrary* core_library_;
+6 -4
View File
@@ -21,7 +21,7 @@ TEST_CASE(Class) {
Class::New(class_name, script, Scanner::kDummyTokenIndex));
// Class has no fields.
const Array& no_fields = Array::Handle(Array::Empty());
const Array& no_fields = Array::Handle(Object::empty_array());
cls.SetFields(no_fields);
// Create and populate the function arrays.
@@ -111,6 +111,8 @@ TEST_CASE(Class) {
cls.set_interfaces(interfaces);
cls.Finalize();
ASSERT(cls.functions_cache() == Array::null());
cls.InitFunctionsCache();
const Array& array = Array::Handle(cls.functions_cache());
array.SetAt(0, function_name);
cls.set_functions_cache(array);
@@ -172,7 +174,7 @@ TEST_CASE(InstanceClass) {
Class::Handle(Class::New(class_name, script, Scanner::kDummyTokenIndex));
// No functions and no super class for the EmptyClass.
const Array& no_fields = Array::Handle(Array::Empty());
const Array& no_fields = Array::Handle(Object::empty_array());
empty_class.SetFields(no_fields);
empty_class.Finalize();
EXPECT_EQ(kObjectAlignment, empty_class.instance_size());
@@ -203,7 +205,7 @@ TEST_CASE(Interface) {
Script& script = Script::Handle();
const Class& factory_class =
Class::Handle(Class::New(class_name, script, Scanner::kDummyTokenIndex));
const Array& no_fields = Array::Handle(Array::Empty());
const Array& no_fields = Array::Handle(Object::empty_array());
// Finalizes the class.
factory_class.SetFields(no_fields);
@@ -1765,7 +1767,7 @@ TEST_CASE(Array) {
other_array.SetAt(2, array);
EXPECT(!array.Equals(other_array));
EXPECT_EQ(0, Array::Handle(Array::Empty()).Length());
EXPECT_EQ(0, Array::Handle(Object::empty_array()).Length());
}
+4 -4
View File
@@ -2930,13 +2930,13 @@ void Parser::ParseClassDefinition(const GrowableObjectArray& pending_classes) {
if (cls.is_interface()) {
ErrorMsg(classname_pos, "'%s' is already defined as interface",
class_name.ToCString());
} else if (cls.functions() != Array::Empty()) {
} else if (cls.functions() != Object::empty_array()) {
ErrorMsg(classname_pos, "class '%s' is already defined",
class_name.ToCString());
}
}
ASSERT(!cls.IsNull());
ASSERT(cls.functions() == Array::Empty());
ASSERT(cls.functions() == Object::empty_array());
set_current_class(cls);
ParseTypeParameters(cls);
Type& super_type = Type::Handle();
@@ -3208,14 +3208,14 @@ void Parser::ParseInterfaceDefinition(
ErrorMsg(interfacename_pos,
"'%s' is already defined as class",
interface_name.ToCString());
} else if (interface.functions() != Array::Empty()) {
} else if (interface.functions() != Object::empty_array()) {
ErrorMsg(interfacename_pos,
"interface '%s' is already defined",
interface_name.ToCString());
}
}
ASSERT(!interface.IsNull());
ASSERT(interface.functions() == Array::Empty());
ASSERT(interface.functions() == Object::empty_array());
set_current_class(interface);
ParseTypeParameters(interface);
+1
View File
@@ -1149,6 +1149,7 @@ class RawArray : public RawInstance {
friend class RawImmutableArray;
friend class SnapshotReader;
friend class GrowableObjectArray;
friend class Object;
};
+9
View File
@@ -581,6 +581,9 @@ RawObject* SnapshotReader::ReadVMIsolateObject(intptr_t header_value) {
if (object_id == kSentinelObject) {
return Object::sentinel();
}
if (object_id == kEmptyArrayObject) {
return Object::empty_array();
}
intptr_t class_id = ClassIdFromObjectId(object_id);
if (IsSingletonClassId(class_id)) {
return isolate()->class_table()->At(class_id); // get singleton class.
@@ -709,6 +712,12 @@ void SnapshotWriter::HandleVMIsolateObject(RawObject* rawobj) {
return;
}
// Check if it is a singleton empty array object.
if (rawobj == Object::empty_array()) {
WriteVMIsolateObject(kEmptyArrayObject);
return;
}
// Check if it is a singleton class object which is shared by
// all isolates.
intptr_t id = rawobj->GetClassId();
+1
View File
@@ -13,6 +13,7 @@ namespace dart {
enum {
kNullObject = 0,
kSentinelObject,
kEmptyArrayObject,
kTrueValue,
kFalseValue,
kClassIdsOffset = kFalseValue,
+3
View File
@@ -293,6 +293,9 @@ static void MegamorphicLookup(Assembler* assembler) {
Label loop, next_iteration;
// Get functions_cache, since it is allocated lazily it maybe null.
__ movl(EAX, FieldAddress(EAX, Class::functions_cache_offset()));
__ cmpl(EAX, raw_null);
__ j(EQUAL, &not_found, Assembler::kNearJump);
// Iterate and search for identical name.
__ leal(EBX, FieldAddress(EAX, Array::data_offset()));
+3
View File
@@ -288,6 +288,9 @@ static void MegamorphicLookup(Assembler* assembler) {
Label loop, next_iteration;
// Get functions_cache, since it is allocated lazily it maybe null.
__ movq(RAX, FieldAddress(RAX, Class::functions_cache_offset()));
__ cmpq(RAX, raw_null);
__ j(EQUAL, &not_found, Assembler::kNearJump);
// Iterate and search for identical name.
__ leaq(R12, FieldAddress(RAX, Array::data_offset()));
+1
View File
@@ -48,6 +48,7 @@ void Symbols::InitOnce(Isolate* isolate) {
Add(symbol_table, str);
predefined_[i] = str.raw();
}
Object::RegisterSingletonClassNames();
}
+31
View File
@@ -53,6 +53,37 @@ class ObjectPointerVisitor;
V(Import, "import") \
V(Source, "source") \
V(Resource, "resource") \
V(Class, "Class") \
V(Null, "Null") \
V(Dynamic, "Dynamic") \
V(Void, "void") \
V(UnresolvedClass, "UnresolvedClass") \
V(Type, "Type") \
V(TypeParameter, "TypeParameter") \
V(TypeArguments, "TypeArguments") \
V(InstantiatedTypeArguments, "InstantiatedTypeArguments") \
V(Function, "Function") \
V(Field, "Field") \
V(LiteralToken, "LiteralToken") \
V(TokenStream, "TokenStream") \
V(Script, "Script") \
V(LibraryClass, "Library") \
V(LibraryPrefix, "LibraryPrefix") \
V(Code, "Code") \
V(Instructions, "Instructions") \
V(PcDescriptors, "PcDescriptors") \
V(Stackmap, "Stackmap") \
V(LocalVarDescriptors, "LocalVarDescriptors") \
V(ExceptionHandlers, "ExceptionHandlers") \
V(DeoptInfo, "DeoptInfo") \
V(Context, "Context") \
V(ContextScope, "ContextScope") \
V(ICData, "ICData") \
V(SubtypeTestCache, "SubtypeTestCache") \
V(ApiError, "ApiError") \
V(LanguageError, "LanguageError") \
V(UnhandledException, "UnhandledException") \
V(UnwindError, "UnwindError") \
// Contains a list of frequently used strings in a canonicalized form. This
// list is kept in the vm_isolate in order to share the copy across isolates