📄 heap.cc.svn-base
字号:
Object* Heap::AllocateArgumentsObject(Object* callee, int length) { // To get fast allocation and map sharing for arguments objects we // allocate them based on an arguments boilerplate. // This calls Copy directly rather than using Heap::AllocateRaw so we // duplicate the check here. ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); JSObject* boilerplate = Top::context()->global_context()->arguments_boilerplate(); Object* result = boilerplate->Copy(); if (result->IsFailure()) return result; Object* obj = JSObject::cast(result)->properties(); FixedArray::cast(obj)->set(arguments_callee_index, callee); FixedArray::cast(obj)->set(arguments_length_index, Smi::FromInt(length)); // Allocate the fixed array. obj = Heap::AllocateFixedArray(length); if (obj->IsFailure()) return obj; JSObject::cast(result)->set_elements(FixedArray::cast(obj)); // Check the state of the object ASSERT(JSObject::cast(result)->HasFastProperties()); ASSERT(JSObject::cast(result)->HasFastElements()); return result;}Object* Heap::AllocateInitialMap(JSFunction* fun) { ASSERT(!fun->has_initial_map()); // First create a new map. Object* map_obj = Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); if (map_obj->IsFailure()) return map_obj; // Fetch or allocate prototype. Object* prototype; if (fun->has_instance_prototype()) { prototype = fun->instance_prototype(); } else { prototype = AllocateFunctionPrototype(fun); if (prototype->IsFailure()) return prototype; } Map* map = Map::cast(map_obj); map->set_unused_property_fields(fun->shared()->expected_nof_properties()); map->set_prototype(prototype); return map;}void Heap::InitializeJSObjectFromMap(JSObject* obj, FixedArray* properties, Map* map) { obj->set_properties(properties); obj->initialize_elements(); // TODO(1240798): Initialize the object's body using valid initial values // according to the object's initial map. For example, if the map's // instance type is JS_ARRAY_TYPE, the length field should be initialized // to a number (eg, Smi::FromInt(0)) and the elements initialized to a // fixed array (eg, Heap::empty_fixed_array()). Currently, the object // verification code has to cope with (temporarily) invalid objects. See // for example, JSArray::JSArrayVerify). obj->InitializeBody(map->instance_size());}Object* Heap::AllocateJSObjectFromMap(Map* map, PretenureFlag pretenure) { // JSFunctions should be allocated using AllocateFunction to be // properly initialized. ASSERT(map->instance_type() != JS_FUNCTION_TYPE); // Allocate the backing storage for the properties. Object* properties = AllocateFixedArray(map->unused_property_fields()); if (properties->IsFailure()) return properties; // Allocate the JSObject. AllocationSpace space = (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE; if (map->instance_size() > MaxHeapObjectSize()) space = LO_SPACE; Object* obj = Allocate(map, space); if (obj->IsFailure()) return obj; // Initialize the JSObject. InitializeJSObjectFromMap(JSObject::cast(obj), FixedArray::cast(properties), map); return obj;}Object* Heap::AllocateJSObject(JSFunction* constructor, PretenureFlag pretenure) { // Allocate the initial map if absent. if (!constructor->has_initial_map()) { Object* initial_map = AllocateInitialMap(constructor); if (initial_map->IsFailure()) return initial_map; constructor->set_initial_map(Map::cast(initial_map)); Map::cast(initial_map)->set_constructor(constructor); } // Allocate the object based on the constructors initial map. return AllocateJSObjectFromMap(constructor->initial_map(), pretenure);}Object* Heap::ReinitializeJSGlobalObject(JSFunction* constructor, JSGlobalObject* object) { // Allocate initial map if absent. if (!constructor->has_initial_map()) { Object* initial_map = AllocateInitialMap(constructor); if (initial_map->IsFailure()) return initial_map; constructor->set_initial_map(Map::cast(initial_map)); Map::cast(initial_map)->set_constructor(constructor); } Map* map = constructor->initial_map(); // Check that the already allocated object has the same size as // objects allocated using the constructor. ASSERT(map->instance_size() == object->map()->instance_size()); // Allocate the backing storage for the properties. Object* properties = AllocateFixedArray(map->unused_property_fields()); if (properties->IsFailure()) return properties; // Reset the map for the object. object->set_map(constructor->initial_map()); // Reinitialize the object from the constructor map. InitializeJSObjectFromMap(object, FixedArray::cast(properties), map); return object;}Object* Heap::AllocateStringFromAscii(Vector<const char> string, PretenureFlag pretenure) { Object* result = AllocateRawAsciiString(string.length(), pretenure); if (result->IsFailure()) return result; // Copy the characters into the new object. AsciiString* string_result = AsciiString::cast(result); for (int i = 0; i < string.length(); i++) { string_result->AsciiStringSet(i, string[i]); } return result;}Object* Heap::AllocateStringFromUtf8(Vector<const char> string, PretenureFlag pretenure) { // Count the number of characters in the UTF-8 string and check if // it is an ASCII string. Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder()); decoder->Reset(string.start(), string.length()); int chars = 0; bool is_ascii = true; while (decoder->has_more()) { uc32 r = decoder->GetNext(); if (r > String::kMaxAsciiCharCode) is_ascii = false; chars++; } // If the string is ascii, we do not need to convert the characters // since UTF8 is backwards compatible with ascii. if (is_ascii) return AllocateStringFromAscii(string, pretenure); Object* result = AllocateRawTwoByteString(chars, pretenure); if (result->IsFailure()) return result; // Convert and copy the characters into the new object. String* string_result = String::cast(result); decoder->Reset(string.start(), string.length()); for (int i = 0; i < chars; i++) { uc32 r = decoder->GetNext(); string_result->Set(i, r); } return result;}Object* Heap::AllocateStringFromTwoByte(Vector<const uc16> string, PretenureFlag pretenure) { // Check if the string is an ASCII string. int i = 0; while (i < string.length() && string[i] <= String::kMaxAsciiCharCode) i++; Object* result; if (i == string.length()) { // It's an ASCII string. result = AllocateRawAsciiString(string.length(), pretenure); } else { // It's not an ASCII string. result = AllocateRawTwoByteString(string.length(), pretenure); } if (result->IsFailure()) return result; // Copy the characters into the new object, which may be either ASCII or // UTF-16. String* string_result = String::cast(result); for (int i = 0; i < string.length(); i++) { string_result->Set(i, string[i]); } return result;}Map* Heap::SymbolMapForString(String* string) { // If the string is in new space it cannot be used as a symbol. if (InNewSpace(string)) return NULL; // Find the corresponding symbol map for strings. Map* map = string->map(); if (map == short_ascii_string_map()) return short_ascii_symbol_map(); if (map == medium_ascii_string_map()) return medium_ascii_symbol_map(); if (map == long_ascii_string_map()) return long_ascii_symbol_map(); if (map == short_string_map()) return short_symbol_map(); if (map == medium_string_map()) return medium_symbol_map(); if (map == long_string_map()) return long_symbol_map(); if (map == short_cons_string_map()) return short_cons_symbol_map(); if (map == medium_cons_string_map()) return medium_cons_symbol_map(); if (map == long_cons_string_map()) return long_cons_symbol_map(); if (map == short_cons_ascii_string_map()) { return short_cons_ascii_symbol_map(); } if (map == medium_cons_ascii_string_map()) { return medium_cons_ascii_symbol_map(); } if (map == long_cons_ascii_string_map()) { return long_cons_ascii_symbol_map(); } if (map == short_sliced_string_map()) return short_sliced_symbol_map(); if (map == medium_sliced_string_map()) return short_sliced_symbol_map(); if (map == long_sliced_string_map()) return short_sliced_symbol_map(); if (map == short_sliced_ascii_string_map()) { return short_sliced_ascii_symbol_map(); } if (map == medium_sliced_ascii_string_map()) { return short_sliced_ascii_symbol_map(); } if (map == long_sliced_ascii_string_map()) { return short_sliced_ascii_symbol_map(); } if (map == short_external_string_map()) return short_external_string_map(); if (map == medium_external_string_map()) return medium_external_string_map(); if (map == long_external_string_map()) return long_external_string_map(); if (map == short_external_ascii_string_map()) { return short_external_ascii_string_map(); } if (map == medium_external_ascii_string_map()) { return medium_external_ascii_string_map(); } if (map == long_external_ascii_string_map()) { return long_external_ascii_string_map(); } // No match found. return NULL;}Object* Heap::AllocateSymbol(unibrow::CharacterStream* buffer, int chars, int hash) { // Ensure the chars matches the number of characters in the buffer. ASSERT(static_cast<unsigned>(chars) == buffer->Length()); // Determine whether the string is ascii. bool is_ascii = true; while (buffer->has_more()) { if (buffer->GetNext() > unibrow::Utf8::kMaxOneByteChar) is_ascii = false; } buffer->Rewind(); // Compute map and object size. int size; Map* map; if (is_ascii) { if (chars <= String::kMaxShortStringSize) { map = short_ascii_symbol_map(); } else if (chars <= String::kMaxMediumStringSize) { map = medium_ascii_symbol_map(); } else { map = long_ascii_symbol_map(); } size = AsciiString::SizeFor(chars); } else { if (chars <= String::kMaxShortStringSize) { map = short_symbol_map(); } else if (chars <= String::kMaxMediumStringSize) { map = medium_symbol_map(); } else { map = long_symbol_map(); } size = TwoByteString::SizeFor(chars); } // Allocate string. AllocationSpace space = (size > MaxHeapObjectSize()) ? LO_SPACE : OLD_DATA_SPACE; Object* result = AllocateRaw(size, space); if (result->IsFailure()) return result; reinterpret_cast<HeapObject*>(result)->set_map(map); // The hash value contains the length of the string. String::cast(result)->set_length_field(hash); ASSERT_EQ(size, String::cast(result)->Size()); // Fill in the characters. for (int i = 0; i < chars; i++) { String::cast(result)->Set(i, buffer->GetNext()); } return result;}Object* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) { AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; int size = AsciiString::SizeFor(length); if (size > MaxHeapObjectSize()) { space = LO_SPACE; } // Use AllocateRaw rather than Allocate because the object's size cannot be // determined from the map. Object* result = AllocateRaw(size, space); if (result->IsFailure()) return result; // Determine the map based on the string's length. Map* map; if (length <= String::kMaxShortStringSize) { map = short_ascii_string_map(); } else if (length <= String::kMaxMediumStringSize) { map = medium_ascii_string_map(); } else { map = long_ascii_string_map(); } // Partially initialize the object. HeapObject::cast(result)->set_map(map); String::cast(result)->set_length(length); ASSERT_EQ(size, HeapObject::cast(result)->Size()); return result;}Object* Heap::AllocateRawTwoByteString(int length, PretenureFlag pretenure) { AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; int size = TwoByteString::SizeFor(length); if (size > MaxHeapObjectSize()) { space = LO_SPACE; } // Use AllocateRaw rather than Allocate because the object's size cannot be // determined from the map. Object* result = AllocateRaw(size, space); if (result->IsFailure()) return result; // Determine the map based on the string's length. Map* map; if (length <= String::kMaxShortStringSize) { map = short_string_map(); } else if (length <= String::kMaxMediumStringSize) { map = medium_string_map(); } else { map = long_string_map(); } // Partially initialize the object. HeapObject::cast(result)->set_map(map); String::cast(result)->set_length(length); ASSERT_EQ(size, HeapObject::cast(result)->Size()); return result;}Object* Heap::AllocateEmptyFixedArray() { int size = FixedArray::SizeFor(0); Object* result = AllocateRaw(size, OLD_DATA_SPACE); if (result->IsFailure()) return result; // Initialize the object. reinterpret_cast<Array*>(result)->set_map(fixed_array_map()); reinterpret_cast<Array*>(result)->set_length(0); return result;}Object* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) { ASSERT(empty_fixed_array()->IsFixedArray()); if (length == 0) return empty_fixed_array(); int size =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -