Handlefy Descriptor and other code in objects.cc
R=verwaest@chromium.org Review URL: https://codereview.chromium.org/228333003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20628 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
1b841f369d
commit
41b6c8a0f1
@ -399,19 +399,19 @@ void Genesis::SetFunctionInstanceDescriptor(
|
||||
map->set_instance_descriptors(*descriptors);
|
||||
|
||||
{ // Add length.
|
||||
CallbacksDescriptor d(*factory()->length_string(), *length, attribs);
|
||||
CallbacksDescriptor d(factory()->length_string(), length, attribs);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
{ // Add name.
|
||||
CallbacksDescriptor d(*factory()->name_string(), *name, attribs);
|
||||
CallbacksDescriptor d(factory()->name_string(), name, attribs);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
{ // Add arguments.
|
||||
CallbacksDescriptor d(*factory()->arguments_string(), *args, attribs);
|
||||
CallbacksDescriptor d(factory()->arguments_string(), args, attribs);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
{ // Add caller.
|
||||
CallbacksDescriptor d(*factory()->caller_string(), *caller, attribs);
|
||||
CallbacksDescriptor d(factory()->caller_string(), caller, attribs);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
if (prototypeMode != DONT_ADD_PROTOTYPE) {
|
||||
@ -419,7 +419,7 @@ void Genesis::SetFunctionInstanceDescriptor(
|
||||
if (prototypeMode == ADD_WRITEABLE_PROTOTYPE) {
|
||||
attribs = static_cast<PropertyAttributes>(attribs & ~READ_ONLY);
|
||||
}
|
||||
CallbacksDescriptor d(*factory()->prototype_string(), *prototype, attribs);
|
||||
CallbacksDescriptor d(factory()->prototype_string(), prototype, attribs);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
}
|
||||
@ -540,27 +540,27 @@ void Genesis::SetStrictFunctionInstanceDescriptor(
|
||||
map->set_instance_descriptors(*descriptors);
|
||||
|
||||
{ // Add length.
|
||||
CallbacksDescriptor d(*factory()->length_string(), *length, ro_attribs);
|
||||
CallbacksDescriptor d(factory()->length_string(), length, ro_attribs);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
{ // Add name.
|
||||
CallbacksDescriptor d(*factory()->name_string(), *name, ro_attribs);
|
||||
CallbacksDescriptor d(factory()->name_string(), name, ro_attribs);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
{ // Add arguments.
|
||||
CallbacksDescriptor d(*factory()->arguments_string(), *arguments,
|
||||
CallbacksDescriptor d(factory()->arguments_string(), arguments,
|
||||
rw_attribs);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
{ // Add caller.
|
||||
CallbacksDescriptor d(*factory()->caller_string(), *caller, rw_attribs);
|
||||
CallbacksDescriptor d(factory()->caller_string(), caller, rw_attribs);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
if (prototypeMode != DONT_ADD_PROTOTYPE) {
|
||||
// Add prototype.
|
||||
PropertyAttributes attribs =
|
||||
prototypeMode == ADD_WRITEABLE_PROTOTYPE ? rw_attribs : ro_attribs;
|
||||
CallbacksDescriptor d(*factory()->prototype_string(), *prototype, attribs);
|
||||
CallbacksDescriptor d(factory()->prototype_string(), prototype, attribs);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
}
|
||||
@ -872,7 +872,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
initial_map->set_instance_descriptors(*array_descriptors);
|
||||
|
||||
{ // Add length.
|
||||
CallbacksDescriptor d(*factory->length_string(), *array_length, attribs);
|
||||
CallbacksDescriptor d(factory->length_string(), array_length, attribs);
|
||||
array_function->initial_map()->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
@ -927,7 +927,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
string_map->set_instance_descriptors(*string_descriptors);
|
||||
|
||||
{ // Add length.
|
||||
CallbacksDescriptor d(*factory->length_string(), *string_length, attribs);
|
||||
CallbacksDescriptor d(factory->length_string(), string_length, attribs);
|
||||
string_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
}
|
||||
@ -964,7 +964,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
|
||||
{
|
||||
// ECMA-262, section 15.10.7.1.
|
||||
FieldDescriptor field(heap->source_string(),
|
||||
FieldDescriptor field(factory->source_string(),
|
||||
JSRegExp::kSourceFieldIndex,
|
||||
final,
|
||||
Representation::Tagged());
|
||||
@ -972,7 +972,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
}
|
||||
{
|
||||
// ECMA-262, section 15.10.7.2.
|
||||
FieldDescriptor field(heap->global_string(),
|
||||
FieldDescriptor field(factory->global_string(),
|
||||
JSRegExp::kGlobalFieldIndex,
|
||||
final,
|
||||
Representation::Tagged());
|
||||
@ -980,7 +980,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
}
|
||||
{
|
||||
// ECMA-262, section 15.10.7.3.
|
||||
FieldDescriptor field(heap->ignore_case_string(),
|
||||
FieldDescriptor field(factory->ignore_case_string(),
|
||||
JSRegExp::kIgnoreCaseFieldIndex,
|
||||
final,
|
||||
Representation::Tagged());
|
||||
@ -988,7 +988,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
}
|
||||
{
|
||||
// ECMA-262, section 15.10.7.4.
|
||||
FieldDescriptor field(heap->multiline_string(),
|
||||
FieldDescriptor field(factory->multiline_string(),
|
||||
JSRegExp::kMultilineFieldIndex,
|
||||
final,
|
||||
Representation::Tagged());
|
||||
@ -998,7 +998,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
// ECMA-262, section 15.10.7.5.
|
||||
PropertyAttributes writable =
|
||||
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
|
||||
FieldDescriptor field(heap->last_index_string(),
|
||||
FieldDescriptor field(factory->last_index_string(),
|
||||
JSRegExp::kLastIndexFieldIndex,
|
||||
writable,
|
||||
Representation::Tagged());
|
||||
@ -1181,18 +1181,18 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
|
||||
{ // length
|
||||
FieldDescriptor d(
|
||||
*factory->length_string(), 0, DONT_ENUM, Representation::Tagged());
|
||||
factory->length_string(), 0, DONT_ENUM, Representation::Tagged());
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
{ // callee
|
||||
CallbacksDescriptor d(*factory->callee_string(),
|
||||
*callee,
|
||||
CallbacksDescriptor d(factory->callee_string(),
|
||||
callee,
|
||||
attributes);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
{ // caller
|
||||
CallbacksDescriptor d(*factory->caller_string(),
|
||||
*caller,
|
||||
CallbacksDescriptor d(factory->caller_string(),
|
||||
caller,
|
||||
attributes);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
@ -1388,7 +1388,7 @@ void Genesis::InitializeExperimentalGlobal() {
|
||||
|
||||
Handle<String> value_string = factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("value"));
|
||||
FieldDescriptor value_descr(*value_string,
|
||||
FieldDescriptor value_descr(value_string,
|
||||
JSGeneratorObject::kResultValuePropertyIndex,
|
||||
NONE,
|
||||
Representation::Tagged());
|
||||
@ -1396,7 +1396,7 @@ void Genesis::InitializeExperimentalGlobal() {
|
||||
|
||||
Handle<String> done_string = factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("done"));
|
||||
FieldDescriptor done_descr(*done_string,
|
||||
FieldDescriptor done_descr(done_string,
|
||||
JSGeneratorObject::kResultDonePropertyIndex,
|
||||
NONE,
|
||||
Representation::Tagged());
|
||||
@ -1620,7 +1620,7 @@ Handle<JSFunction> Genesis::InstallInternalArray(
|
||||
|
||||
{ // Add length.
|
||||
CallbacksDescriptor d(
|
||||
*factory()->length_string(), *array_length, attribs);
|
||||
factory()->length_string(), array_length, attribs);
|
||||
array_function->initial_map()->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
@ -1761,71 +1761,71 @@ bool Genesis::InstallNatives() {
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(
|
||||
*factory()->source_string(), *script_source, attribs);
|
||||
factory()->source_string(), script_source, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(*factory()->name_string(), *script_name, attribs);
|
||||
CallbacksDescriptor d(factory()->name_string(), script_name, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(*id_string, *script_id, attribs);
|
||||
CallbacksDescriptor d(id_string, script_id, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(*line_offset_string, *script_line_offset, attribs);
|
||||
CallbacksDescriptor d(line_offset_string, script_line_offset, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(
|
||||
*column_offset_string, *script_column_offset, attribs);
|
||||
column_offset_string, script_column_offset, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(*type_string, *script_type, attribs);
|
||||
CallbacksDescriptor d(type_string, script_type, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(
|
||||
*compilation_type_string, *script_compilation_type, attribs);
|
||||
compilation_type_string, script_compilation_type, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(*line_ends_string, *script_line_ends, attribs);
|
||||
CallbacksDescriptor d(line_ends_string, script_line_ends, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(
|
||||
*context_data_string, *script_context_data, attribs);
|
||||
context_data_string, script_context_data, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(
|
||||
*eval_from_script_string, *script_eval_from_script, attribs);
|
||||
eval_from_script_string, script_eval_from_script, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(
|
||||
*eval_from_script_position_string,
|
||||
*script_eval_from_script_position,
|
||||
eval_from_script_position_string,
|
||||
script_eval_from_script_position,
|
||||
attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(
|
||||
*eval_from_function_name_string,
|
||||
*script_eval_from_function_name,
|
||||
eval_from_function_name_string,
|
||||
script_eval_from_function_name,
|
||||
attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
@ -1956,17 +1956,18 @@ bool Genesis::InstallNatives() {
|
||||
JSFunction* array_function = native_context()->array_function();
|
||||
Handle<DescriptorArray> array_descriptors(
|
||||
array_function->initial_map()->instance_descriptors());
|
||||
String* length = heap()->length_string();
|
||||
Handle<String> length = factory()->length_string();
|
||||
int old = array_descriptors->SearchWithCache(
|
||||
length, array_function->initial_map());
|
||||
*length, array_function->initial_map());
|
||||
ASSERT(old != DescriptorArray::kNotFound);
|
||||
CallbacksDescriptor desc(length,
|
||||
array_descriptors->GetValue(old),
|
||||
handle(array_descriptors->GetValue(old),
|
||||
isolate()),
|
||||
array_descriptors->GetDetails(old).attributes());
|
||||
initial_map->AppendDescriptor(&desc, witness);
|
||||
}
|
||||
{
|
||||
FieldDescriptor index_field(heap()->index_string(),
|
||||
FieldDescriptor index_field(factory()->index_string(),
|
||||
JSRegExpResult::kIndexIndex,
|
||||
NONE,
|
||||
Representation::Tagged());
|
||||
@ -1974,7 +1975,7 @@ bool Genesis::InstallNatives() {
|
||||
}
|
||||
|
||||
{
|
||||
FieldDescriptor input_field(heap()->input_string(),
|
||||
FieldDescriptor input_field(factory()->input_string(),
|
||||
JSRegExpResult::kInputIndex,
|
||||
NONE,
|
||||
Representation::Tagged());
|
||||
|
@ -1419,13 +1419,14 @@ class DictionaryElementsAccessor
|
||||
|
||||
// Adjusts the length of the dictionary backing store and returns the new
|
||||
// length according to ES5 section 15.4.5.2 behavior.
|
||||
MUST_USE_RESULT static MaybeObject* SetLengthWithoutNormalize(
|
||||
FixedArrayBase* store,
|
||||
JSArray* array,
|
||||
Object* length_object,
|
||||
static Handle<Object> SetLengthWithoutNormalize(
|
||||
Handle<FixedArrayBase> store,
|
||||
Handle<JSArray> array,
|
||||
Handle<Object> length_object,
|
||||
uint32_t length) {
|
||||
SeededNumberDictionary* dict = SeededNumberDictionary::cast(store);
|
||||
Heap* heap = array->GetHeap();
|
||||
Handle<SeededNumberDictionary> dict =
|
||||
Handle<SeededNumberDictionary>::cast(store);
|
||||
Isolate* isolate = array->GetIsolate();
|
||||
int capacity = dict->Capacity();
|
||||
uint32_t new_length = length;
|
||||
uint32_t old_length = static_cast<uint32_t>(array->length()->Number());
|
||||
@ -1433,6 +1434,7 @@ class DictionaryElementsAccessor
|
||||
// Find last non-deletable element in range of elements to be
|
||||
// deleted and adjust range accordingly.
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
Object* key = dict->KeyAt(i);
|
||||
if (key->IsNumber()) {
|
||||
uint32_t number = static_cast<uint32_t>(key->Number());
|
||||
@ -1443,8 +1445,7 @@ class DictionaryElementsAccessor
|
||||
}
|
||||
}
|
||||
if (new_length != length) {
|
||||
MaybeObject* maybe_object = heap->NumberFromUint32(new_length);
|
||||
if (!maybe_object->To(&length_object)) return maybe_object;
|
||||
length_object = isolate->factory()->NewNumberFromUint(new_length);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1452,13 +1453,12 @@ class DictionaryElementsAccessor
|
||||
// If the length of a slow array is reset to zero, we clear
|
||||
// the array and flush backing storage. This has the added
|
||||
// benefit that the array returns to fast mode.
|
||||
Object* obj;
|
||||
MaybeObject* maybe_obj = array->ResetElements();
|
||||
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
|
||||
JSObject::ResetElements(array);
|
||||
} else {
|
||||
DisallowHeapAllocation no_gc;
|
||||
// Remove elements that should be deleted.
|
||||
int removed_entries = 0;
|
||||
Object* the_hole_value = heap->the_hole_value();
|
||||
Object* the_hole_value = isolate->heap()->the_hole_value();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* key = dict->KeyAt(i);
|
||||
if (key->IsNumber()) {
|
||||
@ -1476,18 +1476,6 @@ class DictionaryElementsAccessor
|
||||
return length_object;
|
||||
}
|
||||
|
||||
// TODO(ishell): Temporary wrapper until handlified.
|
||||
MUST_USE_RESULT static Handle<Object> SetLengthWithoutNormalize(
|
||||
Handle<FixedArrayBase> store,
|
||||
Handle<JSArray> array,
|
||||
Handle<Object> length_object,
|
||||
uint32_t length) {
|
||||
CALL_HEAP_FUNCTION(array->GetIsolate(),
|
||||
SetLengthWithoutNormalize(
|
||||
*store, *array, *length_object, length),
|
||||
Object);
|
||||
}
|
||||
|
||||
MUST_USE_RESULT static MaybeObject* DeleteCommon(
|
||||
JSObject* obj,
|
||||
uint32_t key,
|
||||
|
@ -143,6 +143,23 @@ Handle<DescriptorArray> Factory::NewDescriptorArray(int number_of_descriptors,
|
||||
}
|
||||
|
||||
|
||||
Handle<TransitionArray> Factory::NewTransitionArray(int number_of_transitions) {
|
||||
ASSERT(0 <= number_of_transitions);
|
||||
CALL_HEAP_FUNCTION(isolate(),
|
||||
TransitionArray::Allocate(
|
||||
isolate(), number_of_transitions),
|
||||
TransitionArray);
|
||||
}
|
||||
|
||||
|
||||
Handle<TransitionArray> Factory::NewSimpleTransitionArray(Handle<Map> target) {
|
||||
CALL_HEAP_FUNCTION(isolate(),
|
||||
TransitionArray::AllocateSimple(
|
||||
isolate(), *target),
|
||||
TransitionArray);
|
||||
}
|
||||
|
||||
|
||||
Handle<DeoptimizationInputData> Factory::NewDeoptimizationInputData(
|
||||
int deopt_entry_count,
|
||||
PretenureFlag pretenure) {
|
||||
|
@ -57,6 +57,8 @@ class Factory V8_FINAL {
|
||||
|
||||
Handle<DescriptorArray> NewDescriptorArray(int number_of_descriptors,
|
||||
int slack = 0);
|
||||
Handle<TransitionArray> NewTransitionArray(int number_of_transitions);
|
||||
Handle<TransitionArray> NewSimpleTransitionArray(Handle<Map> target);
|
||||
Handle<DeoptimizationInputData> NewDeoptimizationInputData(
|
||||
int deopt_entry_count,
|
||||
PretenureFlag pretenure);
|
||||
|
@ -1750,28 +1750,6 @@ void JSObject::EnsureCanContainElements(Handle<JSObject> object,
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* JSObject::GetElementsTransitionMap(Isolate* isolate,
|
||||
ElementsKind to_kind) {
|
||||
Map* current_map = map();
|
||||
ElementsKind from_kind = current_map->elements_kind();
|
||||
if (from_kind == to_kind) return current_map;
|
||||
|
||||
Context* native_context = isolate->context()->native_context();
|
||||
Object* maybe_array_maps = native_context->js_array_maps();
|
||||
if (maybe_array_maps->IsFixedArray()) {
|
||||
FixedArray* array_maps = FixedArray::cast(maybe_array_maps);
|
||||
if (array_maps->get(from_kind) == current_map) {
|
||||
Object* maybe_transitioned_map = array_maps->get(to_kind);
|
||||
if (maybe_transitioned_map->IsMap()) {
|
||||
return Map::cast(maybe_transitioned_map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GetElementsTransitionMapSlow(to_kind);
|
||||
}
|
||||
|
||||
|
||||
void JSObject::SetMapAndElements(Handle<JSObject> object,
|
||||
Handle<Map> new_map,
|
||||
Handle<FixedArrayBase> value) {
|
||||
@ -1800,50 +1778,8 @@ void JSObject::initialize_properties() {
|
||||
|
||||
|
||||
void JSObject::initialize_elements() {
|
||||
if (map()->has_fast_smi_or_object_elements() ||
|
||||
map()->has_fast_double_elements()) {
|
||||
ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
|
||||
WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array());
|
||||
} else if (map()->has_external_array_elements()) {
|
||||
ExternalArray* empty_array = GetHeap()->EmptyExternalArrayForMap(map());
|
||||
ASSERT(!GetHeap()->InNewSpace(empty_array));
|
||||
WRITE_FIELD(this, kElementsOffset, empty_array);
|
||||
} else if (map()->has_fixed_typed_array_elements()) {
|
||||
FixedTypedArrayBase* empty_array =
|
||||
GetHeap()->EmptyFixedTypedArrayForMap(map());
|
||||
ASSERT(!GetHeap()->InNewSpace(empty_array));
|
||||
WRITE_FIELD(this, kElementsOffset, empty_array);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* JSObject::ResetElements() {
|
||||
if (map()->is_observed()) {
|
||||
// Maintain invariant that observed elements are always in dictionary mode.
|
||||
SeededNumberDictionary* dictionary;
|
||||
MaybeObject* maybe = SeededNumberDictionary::Allocate(GetHeap(), 0);
|
||||
if (!maybe->To(&dictionary)) return maybe;
|
||||
if (map() == GetHeap()->sloppy_arguments_elements_map()) {
|
||||
FixedArray::cast(elements())->set(1, dictionary);
|
||||
} else {
|
||||
set_elements(dictionary);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
ElementsKind elements_kind = GetInitialFastElementsKind();
|
||||
if (!FLAG_smi_only_arrays) {
|
||||
elements_kind = FastSmiToObjectElementsKind(elements_kind);
|
||||
}
|
||||
MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), elements_kind);
|
||||
Map* map;
|
||||
if (!maybe->To(&map)) return maybe;
|
||||
set_map(map);
|
||||
initialize_elements();
|
||||
|
||||
return this;
|
||||
FixedArrayBase* elements = map()->GetInitialElements();
|
||||
WRITE_FIELD(this, kElementsOffset, elements);
|
||||
}
|
||||
|
||||
|
||||
@ -2692,6 +2628,27 @@ void Map::LookupTransition(JSObject* holder,
|
||||
}
|
||||
|
||||
|
||||
FixedArrayBase* Map::GetInitialElements() {
|
||||
if (has_fast_smi_or_object_elements() ||
|
||||
has_fast_double_elements()) {
|
||||
ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
|
||||
return GetHeap()->empty_fixed_array();
|
||||
} else if (has_external_array_elements()) {
|
||||
ExternalArray* empty_array = GetHeap()->EmptyExternalArrayForMap(this);
|
||||
ASSERT(!GetHeap()->InNewSpace(empty_array));
|
||||
return empty_array;
|
||||
} else if (has_fixed_typed_array_elements()) {
|
||||
FixedTypedArrayBase* empty_array =
|
||||
GetHeap()->EmptyFixedTypedArrayForMap(this);
|
||||
ASSERT(!GetHeap()->InNewSpace(empty_array));
|
||||
return empty_array;
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
Object** DescriptorArray::GetKeySlot(int descriptor_number) {
|
||||
ASSERT(descriptor_number < number_of_descriptors());
|
||||
return RawFieldOfElementAt(ToKeyIndex(descriptor_number));
|
||||
@ -2796,8 +2753,8 @@ AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
|
||||
|
||||
|
||||
void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
|
||||
desc->Init(GetKey(descriptor_number),
|
||||
GetValue(descriptor_number),
|
||||
desc->Init(handle(GetKey(descriptor_number), GetIsolate()),
|
||||
handle(GetValue(descriptor_number), GetIsolate()),
|
||||
GetDetails(descriptor_number));
|
||||
}
|
||||
|
||||
@ -2810,10 +2767,10 @@ void DescriptorArray::Set(int descriptor_number,
|
||||
|
||||
NoIncrementalWriteBarrierSet(this,
|
||||
ToKeyIndex(descriptor_number),
|
||||
desc->GetKey());
|
||||
*desc->GetKey());
|
||||
NoIncrementalWriteBarrierSet(this,
|
||||
ToValueIndex(descriptor_number),
|
||||
desc->GetValue());
|
||||
*desc->GetValue());
|
||||
NoIncrementalWriteBarrierSet(this,
|
||||
ToDetailsIndex(descriptor_number),
|
||||
desc->GetDetails().AsSmi());
|
||||
@ -2824,14 +2781,15 @@ void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
|
||||
// Range check.
|
||||
ASSERT(descriptor_number < number_of_descriptors());
|
||||
|
||||
set(ToKeyIndex(descriptor_number), desc->GetKey());
|
||||
set(ToValueIndex(descriptor_number), desc->GetValue());
|
||||
set(ToKeyIndex(descriptor_number), *desc->GetKey());
|
||||
set(ToValueIndex(descriptor_number), *desc->GetValue());
|
||||
set(ToDetailsIndex(descriptor_number), desc->GetDetails().AsSmi());
|
||||
}
|
||||
|
||||
|
||||
void DescriptorArray::Append(Descriptor* desc,
|
||||
const WhitenessWitness& witness) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
int descriptor_number = number_of_descriptors();
|
||||
SetNumberOfDescriptors(descriptor_number + 1);
|
||||
Set(descriptor_number, desc, witness);
|
||||
@ -2851,6 +2809,7 @@ void DescriptorArray::Append(Descriptor* desc,
|
||||
|
||||
|
||||
void DescriptorArray::Append(Descriptor* desc) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
int descriptor_number = number_of_descriptors();
|
||||
SetNumberOfDescriptors(descriptor_number + 1);
|
||||
Set(descriptor_number, desc);
|
||||
@ -5066,14 +5025,6 @@ bool Map::CanHaveMoreTransitions() {
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Map::AddTransition(Name* key,
|
||||
Map* target,
|
||||
SimpleTransitionFlag flag) {
|
||||
if (HasTransitionArray()) return transitions()->CopyInsert(key, target);
|
||||
return TransitionArray::NewWith(flag, key, target, GetBackPointer());
|
||||
}
|
||||
|
||||
|
||||
void Map::SetTransition(int transition_index, Map* target) {
|
||||
transitions()->SetTarget(transition_index, target);
|
||||
}
|
||||
@ -5090,18 +5041,6 @@ int Map::SearchTransition(Name* name) {
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Map::set_elements_transition_map(Map* transitioned_map) {
|
||||
TransitionArray* transitions;
|
||||
MaybeObject* maybe_transitions = AddTransition(
|
||||
GetHeap()->elements_transition_symbol(),
|
||||
transitioned_map,
|
||||
FULL_TRANSITION);
|
||||
if (!maybe_transitions->To(&transitions)) return maybe_transitions;
|
||||
set_transitions(transitions);
|
||||
return transitions;
|
||||
}
|
||||
|
||||
|
||||
FixedArray* Map::GetPrototypeTransitions() {
|
||||
if (!HasTransitionArray()) return GetHeap()->empty_fixed_array();
|
||||
if (!transitions()->HasPrototypeTransitions()) {
|
||||
|
557
src/objects.cc
557
src/objects.cc
@ -2004,35 +2004,20 @@ static Handle<Object> NewStorageFor(Isolate* isolate,
|
||||
}
|
||||
|
||||
|
||||
static MaybeObject* CopyAddFieldDescriptor(Map* map,
|
||||
Name* name,
|
||||
int index,
|
||||
PropertyAttributes attributes,
|
||||
Representation representation,
|
||||
TransitionFlag flag) {
|
||||
Map* new_map;
|
||||
FieldDescriptor new_field_desc(name, index, attributes, representation);
|
||||
MaybeObject* maybe_map = map->CopyAddDescriptor(&new_field_desc, flag);
|
||||
if (!maybe_map->To(&new_map)) return maybe_map;
|
||||
int unused_property_fields = map->unused_property_fields() - 1;
|
||||
if (unused_property_fields < 0) {
|
||||
unused_property_fields += JSObject::kFieldsAdded;
|
||||
}
|
||||
new_map->set_unused_property_fields(unused_property_fields);
|
||||
return new_map;
|
||||
}
|
||||
|
||||
|
||||
static Handle<Map> CopyAddFieldDescriptor(Handle<Map> map,
|
||||
Handle<Name> name,
|
||||
int index,
|
||||
PropertyAttributes attributes,
|
||||
Representation representation,
|
||||
TransitionFlag flag) {
|
||||
CALL_HEAP_FUNCTION(map->GetIsolate(),
|
||||
CopyAddFieldDescriptor(
|
||||
*map, *name, index, attributes, representation, flag),
|
||||
Map);
|
||||
FieldDescriptor new_field_desc(name, index, attributes, representation);
|
||||
Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag);
|
||||
int unused_property_fields = map->unused_property_fields() - 1;
|
||||
if (unused_property_fields < 0) {
|
||||
unused_property_fields += JSObject::kFieldsAdded;
|
||||
}
|
||||
new_map->set_unused_property_fields(unused_property_fields);
|
||||
return new_map;
|
||||
}
|
||||
|
||||
|
||||
@ -2081,25 +2066,13 @@ void JSObject::AddFastProperty(Handle<JSObject> object,
|
||||
}
|
||||
|
||||
|
||||
static MaybeObject* CopyAddConstantDescriptor(Map* map,
|
||||
Name* name,
|
||||
Object* value,
|
||||
PropertyAttributes attributes,
|
||||
TransitionFlag flag) {
|
||||
ConstantDescriptor new_constant_desc(name, value, attributes);
|
||||
return map->CopyAddDescriptor(&new_constant_desc, flag);
|
||||
}
|
||||
|
||||
|
||||
static Handle<Map> CopyAddConstantDescriptor(Handle<Map> map,
|
||||
Handle<Name> name,
|
||||
Handle<Object> value,
|
||||
PropertyAttributes attributes,
|
||||
TransitionFlag flag) {
|
||||
CALL_HEAP_FUNCTION(map->GetIsolate(),
|
||||
CopyAddConstantDescriptor(
|
||||
*map, *name, *value, attributes, flag),
|
||||
Map);
|
||||
ConstantDescriptor new_constant_desc(name, value, attributes);
|
||||
return Map::CopyAddDescriptor(map, &new_constant_desc, flag);
|
||||
}
|
||||
|
||||
|
||||
@ -2392,6 +2365,18 @@ bool Map::InstancesNeedRewriting(Map* target,
|
||||
}
|
||||
|
||||
|
||||
Handle<TransitionArray> Map::SetElementsTransitionMap(
|
||||
Handle<Map> map, Handle<Map> transitioned_map) {
|
||||
Handle<TransitionArray> transitions = Map::AddTransition(
|
||||
map,
|
||||
map->GetIsolate()->factory()->elements_transition_symbol(),
|
||||
transitioned_map,
|
||||
FULL_TRANSITION);
|
||||
map->set_transitions(*transitions);
|
||||
return transitions;
|
||||
}
|
||||
|
||||
|
||||
// To migrate an instance to a map:
|
||||
// - First check whether the instance needs to be rewritten. If not, simply
|
||||
// change the map.
|
||||
@ -2516,9 +2501,11 @@ Handle<TransitionArray> Map::AddTransition(Handle<Map> map,
|
||||
Handle<Name> key,
|
||||
Handle<Map> target,
|
||||
SimpleTransitionFlag flag) {
|
||||
CALL_HEAP_FUNCTION(map->GetIsolate(),
|
||||
map->AddTransition(*key, *target, flag),
|
||||
TransitionArray);
|
||||
if (map->HasTransitionArray()) {
|
||||
return TransitionArray::CopyInsert(map, key, target);
|
||||
}
|
||||
return TransitionArray::NewWith(
|
||||
flag, key, target, handle(map->GetBackPointer(), map->GetIsolate()));
|
||||
}
|
||||
|
||||
|
||||
@ -2556,7 +2543,8 @@ Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map,
|
||||
// Unless the instance is being migrated, ensure that modify_index is a field.
|
||||
PropertyDetails details = descriptors->GetDetails(modify_index);
|
||||
if (store_mode == FORCE_FIELD && details.type() != FIELD) {
|
||||
FieldDescriptor d(descriptors->GetKey(modify_index),
|
||||
FieldDescriptor d(handle(descriptors->GetKey(modify_index),
|
||||
map->GetIsolate()),
|
||||
new_map->NumberOfFields(),
|
||||
attributes,
|
||||
Representation::Tagged());
|
||||
@ -3172,8 +3160,8 @@ static int AppendUniqueCallbacks(NeanderArray* callbacks,
|
||||
// back to front so that the last callback with a given name takes
|
||||
// precedence over previously added callbacks with that name.
|
||||
for (int i = nof_callbacks - 1; i >= 0; i--) {
|
||||
AccessorInfo* entry = AccessorInfo::cast(callbacks->get(i));
|
||||
Name* key = Name::cast(entry->name());
|
||||
Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
|
||||
Handle<Name> key(Name::cast(entry->name()));
|
||||
// Check if a descriptor with this name already exists before writing.
|
||||
if (!T::Contains(key, entry, valid_descriptors, array)) {
|
||||
T::Insert(key, entry, valid_descriptors, array);
|
||||
@ -3186,16 +3174,18 @@ static int AppendUniqueCallbacks(NeanderArray* callbacks,
|
||||
|
||||
struct DescriptorArrayAppender {
|
||||
typedef DescriptorArray Array;
|
||||
static bool Contains(Name* key,
|
||||
AccessorInfo* entry,
|
||||
static bool Contains(Handle<Name> key,
|
||||
Handle<AccessorInfo> entry,
|
||||
int valid_descriptors,
|
||||
Handle<DescriptorArray> array) {
|
||||
return array->Search(key, valid_descriptors) != DescriptorArray::kNotFound;
|
||||
DisallowHeapAllocation no_gc;
|
||||
return array->Search(*key, valid_descriptors) != DescriptorArray::kNotFound;
|
||||
}
|
||||
static void Insert(Name* key,
|
||||
AccessorInfo* entry,
|
||||
static void Insert(Handle<Name> key,
|
||||
Handle<AccessorInfo> entry,
|
||||
int valid_descriptors,
|
||||
Handle<DescriptorArray> array) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
CallbacksDescriptor desc(key, entry, entry->property_attributes());
|
||||
array->Append(&desc);
|
||||
}
|
||||
@ -3204,20 +3194,21 @@ struct DescriptorArrayAppender {
|
||||
|
||||
struct FixedArrayAppender {
|
||||
typedef FixedArray Array;
|
||||
static bool Contains(Name* key,
|
||||
AccessorInfo* entry,
|
||||
static bool Contains(Handle<Name> key,
|
||||
Handle<AccessorInfo> entry,
|
||||
int valid_descriptors,
|
||||
Handle<FixedArray> array) {
|
||||
for (int i = 0; i < valid_descriptors; i++) {
|
||||
if (key == AccessorInfo::cast(array->get(i))->name()) return true;
|
||||
if (*key == AccessorInfo::cast(array->get(i))->name()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static void Insert(Name* key,
|
||||
AccessorInfo* entry,
|
||||
static void Insert(Handle<Name> key,
|
||||
Handle<AccessorInfo> entry,
|
||||
int valid_descriptors,
|
||||
Handle<FixedArray> array) {
|
||||
array->set(valid_descriptors, entry);
|
||||
DisallowHeapAllocation no_gc;
|
||||
array->set(valid_descriptors, *entry);
|
||||
}
|
||||
};
|
||||
|
||||
@ -3335,26 +3326,24 @@ bool Map::IsMapInArrayPrototypeChain() {
|
||||
}
|
||||
|
||||
|
||||
static MaybeObject* AddMissingElementsTransitions(Map* map,
|
||||
ElementsKind to_kind) {
|
||||
static Handle<Map> AddMissingElementsTransitions(Handle<Map> map,
|
||||
ElementsKind to_kind) {
|
||||
ASSERT(IsTransitionElementsKind(map->elements_kind()));
|
||||
|
||||
Map* current_map = map;
|
||||
Handle<Map> current_map = map;
|
||||
|
||||
ElementsKind kind = map->elements_kind();
|
||||
while (kind != to_kind && !IsTerminalElementsKind(kind)) {
|
||||
kind = GetNextTransitionElementsKind(kind);
|
||||
MaybeObject* maybe_next_map =
|
||||
current_map->CopyAsElementsKind(kind, INSERT_TRANSITION);
|
||||
if (!maybe_next_map->To(¤t_map)) return maybe_next_map;
|
||||
current_map = Map::CopyAsElementsKind(
|
||||
current_map, kind, INSERT_TRANSITION);
|
||||
}
|
||||
|
||||
// In case we are exiting the fast elements kind system, just add the map in
|
||||
// the end.
|
||||
if (kind != to_kind) {
|
||||
MaybeObject* maybe_next_map =
|
||||
current_map->CopyAsElementsKind(to_kind, INSERT_TRANSITION);
|
||||
if (!maybe_next_map->To(¤t_map)) return maybe_next_map;
|
||||
current_map = Map::CopyAsElementsKind(
|
||||
current_map, to_kind, INSERT_TRANSITION);
|
||||
}
|
||||
|
||||
ASSERT(current_map->elements_kind() == to_kind);
|
||||
@ -3365,14 +3354,30 @@ static MaybeObject* AddMissingElementsTransitions(Map* map,
|
||||
Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
|
||||
ElementsKind to_kind) {
|
||||
Isolate* isolate = object->GetIsolate();
|
||||
CALL_HEAP_FUNCTION(isolate,
|
||||
object->GetElementsTransitionMap(isolate, to_kind),
|
||||
Map);
|
||||
Handle<Map> current_map(object->map());
|
||||
ElementsKind from_kind = current_map->elements_kind();
|
||||
if (from_kind == to_kind) return current_map;
|
||||
|
||||
Context* native_context = isolate->context()->native_context();
|
||||
Object* maybe_array_maps = native_context->js_array_maps();
|
||||
if (maybe_array_maps->IsFixedArray()) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
FixedArray* array_maps = FixedArray::cast(maybe_array_maps);
|
||||
if (array_maps->get(from_kind) == *current_map) {
|
||||
Object* maybe_transitioned_map = array_maps->get(to_kind);
|
||||
if (maybe_transitioned_map->IsMap()) {
|
||||
return handle(Map::cast(maybe_transitioned_map));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GetElementsTransitionMapSlow(object, to_kind);
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* JSObject::GetElementsTransitionMapSlow(ElementsKind to_kind) {
|
||||
Map* start_map = map();
|
||||
Handle<Map> JSObject::GetElementsTransitionMapSlow(Handle<JSObject> object,
|
||||
ElementsKind to_kind) {
|
||||
Handle<Map> start_map(object->map());
|
||||
ElementsKind from_kind = start_map->elements_kind();
|
||||
|
||||
if (from_kind == to_kind) {
|
||||
@ -3393,24 +3398,16 @@ MaybeObject* JSObject::GetElementsTransitionMapSlow(ElementsKind to_kind) {
|
||||
}
|
||||
|
||||
if (!allow_store_transition) {
|
||||
return start_map->CopyAsElementsKind(to_kind, OMIT_TRANSITION);
|
||||
return Map::CopyAsElementsKind(start_map, to_kind, OMIT_TRANSITION);
|
||||
}
|
||||
|
||||
return start_map->AsElementsKind(to_kind);
|
||||
return Map::AsElementsKind(start_map, to_kind);
|
||||
}
|
||||
|
||||
|
||||
// TODO(ishell): Temporary wrapper until handlified.
|
||||
// static
|
||||
Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) {
|
||||
CALL_HEAP_FUNCTION(map->GetIsolate(),
|
||||
map->AsElementsKind(kind),
|
||||
Map);
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Map::AsElementsKind(ElementsKind kind) {
|
||||
Map* closest_map = FindClosestElementsTransition(this, kind);
|
||||
Handle<Map> closest_map(FindClosestElementsTransition(*map, kind));
|
||||
|
||||
if (closest_map->elements_kind() == kind) {
|
||||
return closest_map;
|
||||
@ -3898,12 +3895,6 @@ MaybeHandle<Object> JSProxy::CallTrap(Handle<JSProxy> proxy,
|
||||
}
|
||||
|
||||
|
||||
// TODO(mstarzinger): Temporary wrapper until handlified.
|
||||
static Handle<Map> MapAsElementsKind(Handle<Map> map, ElementsKind kind) {
|
||||
CALL_HEAP_FUNCTION(map->GetIsolate(), map->AsElementsKind(kind), Map);
|
||||
}
|
||||
|
||||
|
||||
void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
|
||||
ASSERT(object->map()->inobject_properties() == map->inobject_properties());
|
||||
ElementsKind obj_kind = object->map()->elements_kind();
|
||||
@ -3919,7 +3910,7 @@ void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
|
||||
} else {
|
||||
TransitionElementsKind(object, to_kind);
|
||||
}
|
||||
map = MapAsElementsKind(map, to_kind);
|
||||
map = Map::AsElementsKind(map, to_kind);
|
||||
}
|
||||
JSObject::MigrateToMap(object, map);
|
||||
}
|
||||
@ -4758,9 +4749,27 @@ void JSObject::TransformToFastProperties(Handle<JSObject> object,
|
||||
|
||||
|
||||
void JSObject::ResetElements(Handle<JSObject> object) {
|
||||
CALL_HEAP_FUNCTION_VOID(
|
||||
object->GetIsolate(),
|
||||
object->ResetElements());
|
||||
if (object->map()->is_observed()) {
|
||||
// Maintain invariant that observed elements are always in dictionary mode.
|
||||
Factory* factory = object->GetIsolate()->factory();
|
||||
Handle<SeededNumberDictionary> dictionary =
|
||||
factory->NewSeededNumberDictionary(0);
|
||||
if (object->map() == *factory->sloppy_arguments_elements_map()) {
|
||||
FixedArray::cast(object->elements())->set(1, *dictionary);
|
||||
} else {
|
||||
object->set_elements(*dictionary);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ElementsKind elements_kind = GetInitialFastElementsKind();
|
||||
if (!FLAG_smi_only_arrays) {
|
||||
elements_kind = FastSmiToObjectElementsKind(elements_kind);
|
||||
}
|
||||
Handle<Map> map = JSObject::GetElementsTransitionMap(object, elements_kind);
|
||||
DisallowHeapAllocation no_gc;
|
||||
Handle<FixedArrayBase> elements(map->GetInitialElements());
|
||||
JSObject::SetMapAndElements(object, map, elements);
|
||||
}
|
||||
|
||||
|
||||
@ -6489,22 +6498,12 @@ static bool TryAccessorTransition(Handle<JSObject> self,
|
||||
}
|
||||
|
||||
|
||||
static MaybeObject* CopyInsertDescriptor(Map* map,
|
||||
Name* name,
|
||||
AccessorPair* accessors,
|
||||
PropertyAttributes attributes) {
|
||||
CallbacksDescriptor new_accessors_desc(name, accessors, attributes);
|
||||
return map->CopyInsertDescriptor(&new_accessors_desc, INSERT_TRANSITION);
|
||||
}
|
||||
|
||||
|
||||
static Handle<Map> CopyInsertDescriptor(Handle<Map> map,
|
||||
Handle<Name> name,
|
||||
Handle<AccessorPair> accessors,
|
||||
PropertyAttributes attributes) {
|
||||
CALL_HEAP_FUNCTION(map->GetIsolate(),
|
||||
CopyInsertDescriptor(*map, *name, *accessors, attributes),
|
||||
Map);
|
||||
CallbacksDescriptor new_accessors_desc(name, accessors, attributes);
|
||||
return Map::CopyInsertDescriptor(map, &new_accessors_desc, INSERT_TRANSITION);
|
||||
}
|
||||
|
||||
|
||||
@ -6831,42 +6830,38 @@ MaybeObject* Map::CopyDropDescriptors() {
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Map::ShareDescriptor(DescriptorArray* descriptors,
|
||||
Descriptor* descriptor) {
|
||||
Handle<Map> Map::ShareDescriptor(Handle<Map> map,
|
||||
Handle<DescriptorArray> descriptors,
|
||||
Descriptor* descriptor) {
|
||||
// Sanity check. This path is only to be taken if the map owns its descriptor
|
||||
// array, implying that its NumberOfOwnDescriptors equals the number of
|
||||
// descriptors in the descriptor array.
|
||||
ASSERT(NumberOfOwnDescriptors() ==
|
||||
instance_descriptors()->number_of_descriptors());
|
||||
Map* result;
|
||||
MaybeObject* maybe_result = CopyDropDescriptors();
|
||||
if (!maybe_result->To(&result)) return maybe_result;
|
||||
ASSERT(map->NumberOfOwnDescriptors() ==
|
||||
map->instance_descriptors()->number_of_descriptors());
|
||||
Handle<Map> result = Map::CopyDropDescriptors(map);
|
||||
|
||||
Name* name = descriptor->GetKey();
|
||||
Handle<Name> name = descriptor->GetKey();
|
||||
|
||||
TransitionArray* transitions;
|
||||
MaybeObject* maybe_transitions =
|
||||
AddTransition(name, result, SIMPLE_TRANSITION);
|
||||
if (!maybe_transitions->To(&transitions)) return maybe_transitions;
|
||||
|
||||
int old_size = descriptors->number_of_descriptors();
|
||||
|
||||
DescriptorArray* new_descriptors;
|
||||
Handle<TransitionArray> transitions =
|
||||
Map::AddTransition(map, name, result, SIMPLE_TRANSITION);
|
||||
|
||||
if (descriptors->NumberOfSlackDescriptors() > 0) {
|
||||
new_descriptors = descriptors;
|
||||
new_descriptors->Append(descriptor);
|
||||
descriptors->Append(descriptor);
|
||||
result->SetBackPointer(*map);
|
||||
result->InitializeDescriptors(*descriptors);
|
||||
} else {
|
||||
int old_size = descriptors->number_of_descriptors();
|
||||
// Descriptor arrays grow by 50%.
|
||||
MaybeObject* maybe_descriptors = DescriptorArray::Allocate(
|
||||
GetIsolate(), old_size, old_size < 4 ? 1 : old_size / 2);
|
||||
if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
|
||||
Handle<DescriptorArray> new_descriptors =
|
||||
map->GetIsolate()->factory()->NewDescriptorArray(
|
||||
old_size, old_size < 4 ? 1 : old_size / 2);
|
||||
|
||||
DescriptorArray::WhitenessWitness witness(new_descriptors);
|
||||
DisallowHeapAllocation no_gc;
|
||||
DescriptorArray::WhitenessWitness witness(*new_descriptors);
|
||||
|
||||
// Copy the descriptors, inserting a descriptor.
|
||||
for (int i = 0; i < old_size; ++i) {
|
||||
new_descriptors->CopyFrom(i, descriptors, i, witness);
|
||||
new_descriptors->CopyFrom(i, *descriptors, i, witness);
|
||||
}
|
||||
|
||||
new_descriptors->Append(descriptor, witness);
|
||||
@ -6878,31 +6873,32 @@ MaybeObject* Map::ShareDescriptor(DescriptorArray* descriptors,
|
||||
// enumerated descriptors than available in the original cache, the cache
|
||||
// will be lazily replaced by the extended cache when needed.
|
||||
if (descriptors->HasEnumCache()) {
|
||||
new_descriptors->CopyEnumCacheFrom(descriptors);
|
||||
new_descriptors->CopyEnumCacheFrom(*descriptors);
|
||||
}
|
||||
|
||||
Map* map;
|
||||
Map* walk_map;
|
||||
// Replace descriptors by new_descriptors in all maps that share it.
|
||||
|
||||
GetHeap()->incremental_marking()->RecordWrites(descriptors);
|
||||
for (Object* current = GetBackPointer();
|
||||
map->GetHeap()->incremental_marking()->RecordWrites(*descriptors);
|
||||
for (Object* current = map->GetBackPointer();
|
||||
!current->IsUndefined();
|
||||
current = map->GetBackPointer()) {
|
||||
map = Map::cast(current);
|
||||
if (map->instance_descriptors() != descriptors) break;
|
||||
map->set_instance_descriptors(new_descriptors);
|
||||
current = walk_map->GetBackPointer()) {
|
||||
walk_map = Map::cast(current);
|
||||
if (walk_map->instance_descriptors() != *descriptors) break;
|
||||
walk_map->set_instance_descriptors(*new_descriptors);
|
||||
}
|
||||
|
||||
set_instance_descriptors(new_descriptors);
|
||||
map->set_instance_descriptors(*new_descriptors);
|
||||
}
|
||||
|
||||
result->SetBackPointer(*map);
|
||||
result->InitializeDescriptors(*new_descriptors);
|
||||
}
|
||||
|
||||
result->SetBackPointer(this);
|
||||
result->InitializeDescriptors(new_descriptors);
|
||||
ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1);
|
||||
ASSERT(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
|
||||
|
||||
set_transitions(transitions);
|
||||
set_owns_descriptors(false);
|
||||
map->set_transitions(*transitions);
|
||||
map->set_owns_descriptors(false);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -6911,31 +6907,27 @@ MaybeObject* Map::ShareDescriptor(DescriptorArray* descriptors,
|
||||
Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map,
|
||||
Handle<DescriptorArray> descriptors,
|
||||
TransitionFlag flag,
|
||||
Handle<Name> name) {
|
||||
CALL_HEAP_FUNCTION(map->GetIsolate(),
|
||||
map->CopyReplaceDescriptors(*descriptors, flag, *name),
|
||||
Map);
|
||||
SimpleTransitionFlag simple_flag) {
|
||||
return Map::CopyReplaceDescriptors(
|
||||
map, descriptors, flag, Handle<Name>::null(), simple_flag);
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
|
||||
TransitionFlag flag,
|
||||
Name* name,
|
||||
SimpleTransitionFlag simple_flag) {
|
||||
Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map,
|
||||
Handle<DescriptorArray> descriptors,
|
||||
TransitionFlag flag,
|
||||
Handle<Name> name,
|
||||
SimpleTransitionFlag simple_flag) {
|
||||
ASSERT(descriptors->IsSortedNoDuplicates());
|
||||
|
||||
Map* result;
|
||||
MaybeObject* maybe_result = CopyDropDescriptors();
|
||||
if (!maybe_result->To(&result)) return maybe_result;
|
||||
Handle<Map> result = CopyDropDescriptors(map);
|
||||
result->InitializeDescriptors(*descriptors);
|
||||
|
||||
result->InitializeDescriptors(descriptors);
|
||||
|
||||
if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) {
|
||||
TransitionArray* transitions;
|
||||
MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag);
|
||||
if (!maybe_transitions->To(&transitions)) return maybe_transitions;
|
||||
set_transitions(transitions);
|
||||
result->SetBackPointer(this);
|
||||
if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) {
|
||||
Handle<TransitionArray> transitions = Map::AddTransition(
|
||||
map, name, result, simple_flag);
|
||||
map->set_transitions(*transitions);
|
||||
result->SetBackPointer(*map);
|
||||
} else {
|
||||
descriptors->InitializeRepresentations(Representation::Tagged());
|
||||
}
|
||||
@ -6978,52 +6970,48 @@ Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map,
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) {
|
||||
Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
|
||||
TransitionFlag flag) {
|
||||
if (flag == INSERT_TRANSITION) {
|
||||
ASSERT(!HasElementsTransition() ||
|
||||
((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS ||
|
||||
ASSERT(!map->HasElementsTransition() ||
|
||||
((map->elements_transition_map()->elements_kind() ==
|
||||
DICTIONARY_ELEMENTS ||
|
||||
IsExternalArrayElementsKind(
|
||||
elements_transition_map()->elements_kind())) &&
|
||||
map->elements_transition_map()->elements_kind())) &&
|
||||
(kind == DICTIONARY_ELEMENTS ||
|
||||
IsExternalArrayElementsKind(kind))));
|
||||
ASSERT(!IsFastElementsKind(kind) ||
|
||||
IsMoreGeneralElementsKindTransition(elements_kind(), kind));
|
||||
ASSERT(kind != elements_kind());
|
||||
IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
|
||||
ASSERT(kind != map->elements_kind());
|
||||
}
|
||||
|
||||
bool insert_transition =
|
||||
flag == INSERT_TRANSITION && !HasElementsTransition();
|
||||
flag == INSERT_TRANSITION && !map->HasElementsTransition();
|
||||
|
||||
if (insert_transition && owns_descriptors()) {
|
||||
if (insert_transition && map->owns_descriptors()) {
|
||||
// In case the map owned its own descriptors, share the descriptors and
|
||||
// transfer ownership to the new map.
|
||||
Map* new_map;
|
||||
MaybeObject* maybe_new_map = CopyDropDescriptors();
|
||||
if (!maybe_new_map->To(&new_map)) return maybe_new_map;
|
||||
Handle<Map> new_map = Map::CopyDropDescriptors(map);
|
||||
|
||||
MaybeObject* added_elements = set_elements_transition_map(new_map);
|
||||
if (added_elements->IsFailure()) return added_elements;
|
||||
SetElementsTransitionMap(map, new_map);
|
||||
|
||||
new_map->set_elements_kind(kind);
|
||||
new_map->InitializeDescriptors(instance_descriptors());
|
||||
new_map->SetBackPointer(this);
|
||||
set_owns_descriptors(false);
|
||||
new_map->InitializeDescriptors(map->instance_descriptors());
|
||||
new_map->SetBackPointer(*map);
|
||||
map->set_owns_descriptors(false);
|
||||
return new_map;
|
||||
}
|
||||
|
||||
// In case the map did not own its own descriptors, a split is forced by
|
||||
// copying the map; creating a new descriptor array cell.
|
||||
// Create a new free-floating map only if we are not allowed to store it.
|
||||
Map* new_map;
|
||||
MaybeObject* maybe_new_map = Copy();
|
||||
if (!maybe_new_map->To(&new_map)) return maybe_new_map;
|
||||
Handle<Map> new_map = Map::Copy(map);
|
||||
|
||||
new_map->set_elements_kind(kind);
|
||||
|
||||
if (insert_transition) {
|
||||
MaybeObject* added_elements = set_elements_transition_map(new_map);
|
||||
if (added_elements->IsFailure()) return added_elements;
|
||||
new_map->SetBackPointer(this);
|
||||
SetElementsTransitionMap(map, new_map);
|
||||
new_map->SetBackPointer(*map);
|
||||
}
|
||||
|
||||
return new_map;
|
||||
@ -7063,19 +7051,11 @@ Handle<Map> Map::CopyForObserved(Handle<Map> map) {
|
||||
|
||||
|
||||
Handle<Map> Map::Copy(Handle<Map> map) {
|
||||
CALL_HEAP_FUNCTION(map->GetIsolate(), map->Copy(), Map);
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Map::Copy() {
|
||||
DescriptorArray* descriptors = instance_descriptors();
|
||||
DescriptorArray* new_descriptors;
|
||||
int number_of_own_descriptors = NumberOfOwnDescriptors();
|
||||
MaybeObject* maybe_descriptors =
|
||||
descriptors->CopyUpTo(number_of_own_descriptors);
|
||||
if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
|
||||
|
||||
return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION);
|
||||
Handle<DescriptorArray> descriptors(map->instance_descriptors());
|
||||
int number_of_own_descriptors = map->NumberOfOwnDescriptors();
|
||||
Handle<DescriptorArray> new_descriptors =
|
||||
DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
|
||||
return Map::CopyReplaceDescriptors(map, new_descriptors, OMIT_TRANSITION);
|
||||
}
|
||||
|
||||
|
||||
@ -7108,33 +7088,31 @@ Handle<Map> Map::Create(Handle<JSFunction> constructor,
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor,
|
||||
TransitionFlag flag) {
|
||||
DescriptorArray* descriptors = instance_descriptors();
|
||||
Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
|
||||
Descriptor* descriptor,
|
||||
TransitionFlag flag) {
|
||||
Handle<DescriptorArray> descriptors(map->instance_descriptors());
|
||||
|
||||
// Ensure the key is unique.
|
||||
MaybeObject* maybe_failure = descriptor->KeyToUniqueName();
|
||||
if (maybe_failure->IsFailure()) return maybe_failure;
|
||||
descriptor->KeyToUniqueName();
|
||||
|
||||
int old_size = NumberOfOwnDescriptors();
|
||||
int old_size = map->NumberOfOwnDescriptors();
|
||||
int new_size = old_size + 1;
|
||||
|
||||
if (flag == INSERT_TRANSITION &&
|
||||
owns_descriptors() &&
|
||||
CanHaveMoreTransitions()) {
|
||||
return ShareDescriptor(descriptors, descriptor);
|
||||
map->owns_descriptors() &&
|
||||
map->CanHaveMoreTransitions()) {
|
||||
return Map::ShareDescriptor(map, descriptors, descriptor);
|
||||
}
|
||||
|
||||
DescriptorArray* new_descriptors;
|
||||
MaybeObject* maybe_descriptors =
|
||||
DescriptorArray::Allocate(GetIsolate(), old_size, 1);
|
||||
if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
|
||||
Handle<DescriptorArray> new_descriptors =
|
||||
map->GetIsolate()->factory()->NewDescriptorArray(old_size, 1);
|
||||
|
||||
DescriptorArray::WhitenessWitness witness(new_descriptors);
|
||||
DescriptorArray::WhitenessWitness witness(*new_descriptors);
|
||||
|
||||
// Copy the descriptors, inserting a descriptor.
|
||||
for (int i = 0; i < old_size; ++i) {
|
||||
new_descriptors->CopyFrom(i, descriptors, i, witness);
|
||||
new_descriptors->CopyFrom(i, *descriptors, i, witness);
|
||||
}
|
||||
|
||||
if (old_size != descriptors->number_of_descriptors()) {
|
||||
@ -7145,25 +7123,36 @@ MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor,
|
||||
new_descriptors->Append(descriptor, witness);
|
||||
}
|
||||
|
||||
Name* key = descriptor->GetKey();
|
||||
return CopyReplaceDescriptors(new_descriptors, flag, key, SIMPLE_TRANSITION);
|
||||
Handle<Name> key = descriptor->GetKey();
|
||||
return Map::CopyReplaceDescriptors(
|
||||
map, new_descriptors, flag, key, SIMPLE_TRANSITION);
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor,
|
||||
TransitionFlag flag) {
|
||||
DescriptorArray* old_descriptors = instance_descriptors();
|
||||
Handle<Map> Map::CopyInsertDescriptor(Handle<Map> map,
|
||||
Descriptor* descriptor,
|
||||
TransitionFlag flag) {
|
||||
Handle<DescriptorArray> old_descriptors(map->instance_descriptors());
|
||||
|
||||
// Ensure the key is unique.
|
||||
MaybeObject* maybe_result = descriptor->KeyToUniqueName();
|
||||
if (maybe_result->IsFailure()) return maybe_result;
|
||||
descriptor->KeyToUniqueName();
|
||||
|
||||
// We replace the key if it is already present.
|
||||
int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this);
|
||||
int index = old_descriptors->SearchWithCache(*descriptor->GetKey(), *map);
|
||||
if (index != DescriptorArray::kNotFound) {
|
||||
return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag);
|
||||
return Map::CopyReplaceDescriptor(
|
||||
map, old_descriptors, descriptor, index, flag);
|
||||
}
|
||||
return CopyAddDescriptor(descriptor, flag);
|
||||
return Map::CopyAddDescriptor(map, descriptor, flag);
|
||||
}
|
||||
|
||||
|
||||
Handle<DescriptorArray> DescriptorArray::CopyUpTo(
|
||||
Handle<DescriptorArray> desc,
|
||||
int enumeration_index) {
|
||||
return DescriptorArray::CopyUpToAddAttributes(desc,
|
||||
enumeration_index,
|
||||
NONE);
|
||||
}
|
||||
|
||||
|
||||
@ -7171,27 +7160,20 @@ Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
|
||||
Handle<DescriptorArray> desc,
|
||||
int enumeration_index,
|
||||
PropertyAttributes attributes) {
|
||||
CALL_HEAP_FUNCTION(desc->GetIsolate(),
|
||||
desc->CopyUpToAddAttributes(enumeration_index, attributes),
|
||||
DescriptorArray);
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* DescriptorArray::CopyUpToAddAttributes(
|
||||
int enumeration_index, PropertyAttributes attributes) {
|
||||
if (enumeration_index == 0) return GetHeap()->empty_descriptor_array();
|
||||
if (enumeration_index == 0) {
|
||||
return desc->GetIsolate()->factory()->empty_descriptor_array();
|
||||
}
|
||||
|
||||
int size = enumeration_index;
|
||||
|
||||
DescriptorArray* descriptors;
|
||||
MaybeObject* maybe_descriptors = Allocate(GetIsolate(), size);
|
||||
if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors;
|
||||
DescriptorArray::WhitenessWitness witness(descriptors);
|
||||
Handle<DescriptorArray> descriptors =
|
||||
desc->GetIsolate()->factory()->NewDescriptorArray(size);
|
||||
DescriptorArray::WhitenessWitness witness(*descriptors);
|
||||
|
||||
if (attributes != NONE) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
Object* value = GetValue(i);
|
||||
PropertyDetails details = GetDetails(i);
|
||||
Object* value = desc->GetValue(i);
|
||||
PropertyDetails details = desc->GetDetails(i);
|
||||
int mask = DONT_DELETE | DONT_ENUM;
|
||||
// READ_ONLY is an invalid attribute for JS setters/getters.
|
||||
if (details.type() != CALLBACKS || !value->IsAccessorPair()) {
|
||||
@ -7199,59 +7181,59 @@ MaybeObject* DescriptorArray::CopyUpToAddAttributes(
|
||||
}
|
||||
details = details.CopyAddAttributes(
|
||||
static_cast<PropertyAttributes>(attributes & mask));
|
||||
Descriptor desc(GetKey(i), value, details);
|
||||
descriptors->Set(i, &desc, witness);
|
||||
Descriptor inner_desc(handle(desc->GetKey(i)),
|
||||
handle(value, desc->GetIsolate()),
|
||||
details);
|
||||
descriptors->Set(i, &inner_desc, witness);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
descriptors->CopyFrom(i, this, i, witness);
|
||||
descriptors->CopyFrom(i, *desc, i, witness);
|
||||
}
|
||||
}
|
||||
|
||||
if (number_of_descriptors() != enumeration_index) descriptors->Sort();
|
||||
if (desc->number_of_descriptors() != enumeration_index) descriptors->Sort();
|
||||
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Map::CopyReplaceDescriptor(DescriptorArray* descriptors,
|
||||
Descriptor* descriptor,
|
||||
int insertion_index,
|
||||
TransitionFlag flag) {
|
||||
Handle<Map> Map::CopyReplaceDescriptor(Handle<Map> map,
|
||||
Handle<DescriptorArray> descriptors,
|
||||
Descriptor* descriptor,
|
||||
int insertion_index,
|
||||
TransitionFlag flag) {
|
||||
// Ensure the key is unique.
|
||||
MaybeObject* maybe_failure = descriptor->KeyToUniqueName();
|
||||
if (maybe_failure->IsFailure()) return maybe_failure;
|
||||
descriptor->KeyToUniqueName();
|
||||
|
||||
Name* key = descriptor->GetKey();
|
||||
ASSERT(key == descriptors->GetKey(insertion_index));
|
||||
Handle<Name> key = descriptor->GetKey();
|
||||
ASSERT(*key == descriptors->GetKey(insertion_index));
|
||||
|
||||
int new_size = NumberOfOwnDescriptors();
|
||||
int new_size = map->NumberOfOwnDescriptors();
|
||||
ASSERT(0 <= insertion_index && insertion_index < new_size);
|
||||
|
||||
ASSERT_LT(insertion_index, new_size);
|
||||
|
||||
DescriptorArray* new_descriptors;
|
||||
MaybeObject* maybe_descriptors =
|
||||
DescriptorArray::Allocate(GetIsolate(), new_size);
|
||||
if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
|
||||
DescriptorArray::WhitenessWitness witness(new_descriptors);
|
||||
Handle<DescriptorArray> new_descriptors =
|
||||
map->GetIsolate()->factory()->NewDescriptorArray(new_size);
|
||||
DescriptorArray::WhitenessWitness witness(*new_descriptors);
|
||||
|
||||
for (int i = 0; i < new_size; ++i) {
|
||||
if (i == insertion_index) {
|
||||
new_descriptors->Set(i, descriptor, witness);
|
||||
} else {
|
||||
new_descriptors->CopyFrom(i, descriptors, i, witness);
|
||||
new_descriptors->CopyFrom(i, *descriptors, i, witness);
|
||||
}
|
||||
}
|
||||
|
||||
// Re-sort if descriptors were removed.
|
||||
if (new_size != descriptors->length()) new_descriptors->Sort();
|
||||
new_descriptors->Sort();
|
||||
|
||||
SimpleTransitionFlag simple_flag =
|
||||
(insertion_index == descriptors->number_of_descriptors() - 1)
|
||||
? SIMPLE_TRANSITION
|
||||
: FULL_TRANSITION;
|
||||
return CopyReplaceDescriptors(new_descriptors, flag, key, simple_flag);
|
||||
return Map::CopyReplaceDescriptors(
|
||||
map, new_descriptors, flag, key, simple_flag);
|
||||
}
|
||||
|
||||
|
||||
@ -8095,7 +8077,9 @@ void DescriptorArray::CopyFrom(int dst_index,
|
||||
const WhitenessWitness& witness) {
|
||||
Object* value = src->GetValue(src_index);
|
||||
PropertyDetails details = src->GetDetails(src_index);
|
||||
Descriptor desc(src->GetKey(src_index), value, details);
|
||||
Descriptor desc(handle(src->GetKey(src_index)),
|
||||
handle(value, src->GetIsolate()),
|
||||
details);
|
||||
Set(dst_index, &desc, witness);
|
||||
}
|
||||
|
||||
@ -8138,8 +8122,8 @@ Handle<DescriptorArray> DescriptorArray::Merge(Handle<Map> left_map,
|
||||
int current_offset = 0;
|
||||
for (descriptor = 0; descriptor < verbatim; descriptor++) {
|
||||
if (left->GetDetails(descriptor).type() == FIELD) current_offset++;
|
||||
Descriptor d(right->GetKey(descriptor),
|
||||
right->GetValue(descriptor),
|
||||
Descriptor d(handle(right->GetKey(descriptor)),
|
||||
handle(right->GetValue(descriptor), right->GetIsolate()),
|
||||
right->GetDetails(descriptor));
|
||||
result->Set(descriptor, &d);
|
||||
}
|
||||
@ -8155,14 +8139,14 @@ Handle<DescriptorArray> DescriptorArray::Merge(Handle<Map> left_map,
|
||||
left->GetValue(descriptor) != right->GetValue(descriptor))) {
|
||||
Representation representation = left_details.representation().generalize(
|
||||
right_details.representation());
|
||||
FieldDescriptor d(left->GetKey(descriptor),
|
||||
FieldDescriptor d(handle(left->GetKey(descriptor)),
|
||||
current_offset++,
|
||||
right_details.attributes(),
|
||||
representation);
|
||||
result->Set(descriptor, &d);
|
||||
} else {
|
||||
Descriptor d(right->GetKey(descriptor),
|
||||
right->GetValue(descriptor),
|
||||
Descriptor d(handle(right->GetKey(descriptor)),
|
||||
handle(right->GetValue(descriptor), right->GetIsolate()),
|
||||
right_details);
|
||||
result->Set(descriptor, &d);
|
||||
}
|
||||
@ -8173,14 +8157,14 @@ Handle<DescriptorArray> DescriptorArray::Merge(Handle<Map> left_map,
|
||||
PropertyDetails right_details = right->GetDetails(descriptor);
|
||||
if (right_details.type() == FIELD ||
|
||||
(store_mode == FORCE_FIELD && descriptor == modify_index)) {
|
||||
FieldDescriptor d(right->GetKey(descriptor),
|
||||
FieldDescriptor d(handle(right->GetKey(descriptor)),
|
||||
current_offset++,
|
||||
right_details.attributes(),
|
||||
right_details.representation());
|
||||
result->Set(descriptor, &d);
|
||||
} else {
|
||||
Descriptor d(right->GetKey(descriptor),
|
||||
right->GetValue(descriptor),
|
||||
Descriptor d(handle(right->GetKey(descriptor)),
|
||||
handle(right->GetValue(descriptor), right->GetIsolate()),
|
||||
right_details);
|
||||
result->Set(descriptor, &d);
|
||||
}
|
||||
@ -9784,48 +9768,37 @@ void JSObject::OptimizeAsPrototype(Handle<JSObject> object) {
|
||||
}
|
||||
|
||||
|
||||
static MUST_USE_RESULT MaybeObject* CacheInitialJSArrayMaps(
|
||||
Context* native_context, Map* initial_map) {
|
||||
Handle<Object> CacheInitialJSArrayMaps(
|
||||
Handle<Context> native_context, Handle<Map> initial_map) {
|
||||
// Replace all of the cached initial array maps in the native context with
|
||||
// the appropriate transitioned elements kind maps.
|
||||
Heap* heap = native_context->GetHeap();
|
||||
MaybeObject* maybe_maps =
|
||||
heap->AllocateFixedArrayWithHoles(kElementsKindCount, TENURED);
|
||||
FixedArray* maps;
|
||||
if (!maybe_maps->To(&maps)) return maybe_maps;
|
||||
Factory* factory = native_context->GetIsolate()->factory();
|
||||
Handle<FixedArray> maps = factory->NewFixedArrayWithHoles(
|
||||
kElementsKindCount, TENURED);
|
||||
|
||||
Map* current_map = initial_map;
|
||||
Handle<Map> current_map = initial_map;
|
||||
ElementsKind kind = current_map->elements_kind();
|
||||
ASSERT(kind == GetInitialFastElementsKind());
|
||||
maps->set(kind, current_map);
|
||||
maps->set(kind, *current_map);
|
||||
for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
|
||||
i < kFastElementsKindCount; ++i) {
|
||||
Map* new_map;
|
||||
Handle<Map> new_map;
|
||||
ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i);
|
||||
if (current_map->HasElementsTransition()) {
|
||||
new_map = current_map->elements_transition_map();
|
||||
new_map = handle(current_map->elements_transition_map());
|
||||
ASSERT(new_map->elements_kind() == next_kind);
|
||||
} else {
|
||||
MaybeObject* maybe_new_map =
|
||||
current_map->CopyAsElementsKind(next_kind, INSERT_TRANSITION);
|
||||
if (!maybe_new_map->To(&new_map)) return maybe_new_map;
|
||||
new_map = Map::CopyAsElementsKind(
|
||||
current_map, next_kind, INSERT_TRANSITION);
|
||||
}
|
||||
maps->set(next_kind, new_map);
|
||||
maps->set(next_kind, *new_map);
|
||||
current_map = new_map;
|
||||
}
|
||||
native_context->set_js_array_maps(maps);
|
||||
native_context->set_js_array_maps(*maps);
|
||||
return initial_map;
|
||||
}
|
||||
|
||||
|
||||
Handle<Object> CacheInitialJSArrayMaps(Handle<Context> native_context,
|
||||
Handle<Map> initial_map) {
|
||||
CALL_HEAP_FUNCTION(native_context->GetIsolate(),
|
||||
CacheInitialJSArrayMaps(*native_context, *initial_map),
|
||||
Object);
|
||||
}
|
||||
|
||||
|
||||
void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
|
||||
Handle<Object> value) {
|
||||
ASSERT(value->IsJSReceiver());
|
||||
@ -15716,7 +15689,9 @@ MaybeObject* NameDictionary::TransformPropertiesToFastFor(
|
||||
PropertyType type = details.type();
|
||||
|
||||
if (value->IsJSFunction()) {
|
||||
ConstantDescriptor d(key, value, details.attributes());
|
||||
ConstantDescriptor d(handle(key),
|
||||
handle(value, GetIsolate()),
|
||||
details.attributes());
|
||||
descriptors->Set(enumeration_index - 1, &d, witness);
|
||||
} else if (type == NORMAL) {
|
||||
if (current_offset < inobject_props) {
|
||||
@ -15727,15 +15702,15 @@ MaybeObject* NameDictionary::TransformPropertiesToFastFor(
|
||||
int offset = current_offset - inobject_props;
|
||||
fields->set(offset, value);
|
||||
}
|
||||
FieldDescriptor d(key,
|
||||
FieldDescriptor d(handle(key),
|
||||
current_offset++,
|
||||
details.attributes(),
|
||||
// TODO(verwaest): value->OptimalRepresentation();
|
||||
Representation::Tagged());
|
||||
descriptors->Set(enumeration_index - 1, &d, witness);
|
||||
} else if (type == CALLBACKS) {
|
||||
CallbacksDescriptor d(key,
|
||||
value,
|
||||
CallbacksDescriptor d(handle(key),
|
||||
handle(value, GetIsolate()),
|
||||
details.attributes());
|
||||
descriptors->Set(enumeration_index - 1, &d, witness);
|
||||
} else {
|
||||
|
@ -2186,7 +2186,6 @@ class JSObject: public JSReceiver {
|
||||
// arguments object.
|
||||
DECL_ACCESSORS(elements, FixedArrayBase)
|
||||
inline void initialize_elements();
|
||||
MUST_USE_RESULT inline MaybeObject* ResetElements();
|
||||
static void ResetElements(Handle<JSObject> object);
|
||||
static inline void SetMapAndElements(Handle<JSObject> object,
|
||||
Handle<Map> map,
|
||||
@ -2580,11 +2579,8 @@ class JSObject: public JSReceiver {
|
||||
// map and the ElementsKind set.
|
||||
static Handle<Map> GetElementsTransitionMap(Handle<JSObject> object,
|
||||
ElementsKind to_kind);
|
||||
inline MUST_USE_RESULT MaybeObject* GetElementsTransitionMap(
|
||||
Isolate* isolate,
|
||||
ElementsKind elements_kind);
|
||||
MUST_USE_RESULT MaybeObject* GetElementsTransitionMapSlow(
|
||||
ElementsKind elements_kind);
|
||||
static Handle<Map> GetElementsTransitionMapSlow(Handle<JSObject> object,
|
||||
ElementsKind elements_kind);
|
||||
|
||||
static void TransitionElementsKind(Handle<JSObject> object,
|
||||
ElementsKind to_kind);
|
||||
@ -3481,17 +3477,13 @@ class DescriptorArray: public FixedArray {
|
||||
int new_size,
|
||||
DescriptorArray* other);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* CopyUpTo(int enumeration_index) {
|
||||
return CopyUpToAddAttributes(enumeration_index, NONE);
|
||||
}
|
||||
static Handle<DescriptorArray> CopyUpTo(Handle<DescriptorArray> desc,
|
||||
int enumeration_index);
|
||||
|
||||
static Handle<DescriptorArray> CopyUpToAddAttributes(
|
||||
Handle<DescriptorArray> desc,
|
||||
int enumeration_index,
|
||||
PropertyAttributes attributes);
|
||||
MUST_USE_RESULT MaybeObject* CopyUpToAddAttributes(
|
||||
int enumeration_index,
|
||||
PropertyAttributes attributes);
|
||||
|
||||
// Sort the instance descriptors by the hash codes of their keys.
|
||||
void Sort();
|
||||
@ -6172,20 +6164,17 @@ class Map: public HeapObject {
|
||||
inline bool HasTransitionArray();
|
||||
inline bool HasElementsTransition();
|
||||
inline Map* elements_transition_map();
|
||||
MUST_USE_RESULT inline MaybeObject* set_elements_transition_map(
|
||||
Map* transitioned_map);
|
||||
static Handle<TransitionArray> SetElementsTransitionMap(
|
||||
Handle<Map> map, Handle<Map> transitioned_map);
|
||||
inline void SetTransition(int transition_index, Map* target);
|
||||
inline Map* GetTransition(int transition_index);
|
||||
inline int SearchTransition(Name* name);
|
||||
inline FixedArrayBase* GetInitialElements();
|
||||
|
||||
static Handle<TransitionArray> AddTransition(Handle<Map> map,
|
||||
Handle<Name> key,
|
||||
Handle<Map> target,
|
||||
SimpleTransitionFlag flag);
|
||||
|
||||
MUST_USE_RESULT inline MaybeObject* AddTransition(Name* key,
|
||||
Map* target,
|
||||
SimpleTransitionFlag flag);
|
||||
DECL_ACCESSORS(transitions, TransitionArray)
|
||||
inline void ClearTransitions(Heap* heap,
|
||||
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
||||
@ -6391,37 +6380,42 @@ class Map: public HeapObject {
|
||||
MUST_USE_RESULT MaybeObject* RawCopy(int instance_size);
|
||||
static Handle<Map> CopyDropDescriptors(Handle<Map> map);
|
||||
MUST_USE_RESULT MaybeObject* CopyDropDescriptors();
|
||||
static Handle<Map> CopyReplaceDescriptors(Handle<Map> map,
|
||||
Handle<DescriptorArray> descriptors,
|
||||
TransitionFlag flag,
|
||||
Handle<Name> name);
|
||||
MUST_USE_RESULT MaybeObject* CopyReplaceDescriptors(
|
||||
DescriptorArray* descriptors,
|
||||
static Handle<Map> CopyReplaceDescriptors(
|
||||
Handle<Map> map,
|
||||
Handle<DescriptorArray> descriptors,
|
||||
TransitionFlag flag,
|
||||
Handle<Name> name,
|
||||
SimpleTransitionFlag simple_flag = FULL_TRANSITION);
|
||||
static Handle<Map> CopyReplaceDescriptors(
|
||||
Handle<Map> map,
|
||||
Handle<DescriptorArray> descriptors,
|
||||
TransitionFlag flag,
|
||||
Name* name = NULL,
|
||||
SimpleTransitionFlag simple_flag = FULL_TRANSITION);
|
||||
static Handle<Map> CopyInstallDescriptors(
|
||||
Handle<Map> map,
|
||||
int new_descriptor,
|
||||
Handle<DescriptorArray> descriptors);
|
||||
MUST_USE_RESULT MaybeObject* ShareDescriptor(DescriptorArray* descriptors,
|
||||
Descriptor* descriptor);
|
||||
MUST_USE_RESULT MaybeObject* CopyAddDescriptor(Descriptor* descriptor,
|
||||
TransitionFlag flag);
|
||||
MUST_USE_RESULT MaybeObject* CopyInsertDescriptor(Descriptor* descriptor,
|
||||
TransitionFlag flag);
|
||||
MUST_USE_RESULT MaybeObject* CopyReplaceDescriptor(
|
||||
DescriptorArray* descriptors,
|
||||
static Handle<Map> ShareDescriptor(Handle<Map> map,
|
||||
Handle<DescriptorArray> descriptors,
|
||||
Descriptor* descriptor);
|
||||
static Handle<Map> CopyAddDescriptor(Handle<Map> map,
|
||||
Descriptor* descriptor,
|
||||
TransitionFlag flag);
|
||||
static Handle<Map> CopyInsertDescriptor(Handle<Map> map,
|
||||
Descriptor* descriptor,
|
||||
TransitionFlag flag);
|
||||
static Handle<Map> CopyReplaceDescriptor(
|
||||
Handle<Map> map,
|
||||
Handle<DescriptorArray> descriptors,
|
||||
Descriptor* descriptor,
|
||||
int index,
|
||||
TransitionFlag flag);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* AsElementsKind(ElementsKind kind);
|
||||
|
||||
static Handle<Map> AsElementsKind(Handle<Map> map, ElementsKind kind);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* CopyAsElementsKind(ElementsKind kind,
|
||||
TransitionFlag flag);
|
||||
static Handle<Map> CopyAsElementsKind(Handle<Map> map,
|
||||
ElementsKind kind,
|
||||
TransitionFlag flag);
|
||||
|
||||
static Handle<Map> CopyForObserved(Handle<Map> map);
|
||||
|
||||
@ -6437,7 +6431,6 @@ class Map: public HeapObject {
|
||||
static Handle<Map> Copy(Handle<Map> map);
|
||||
static Handle<Map> Create(Handle<JSFunction> constructor,
|
||||
int extra_inobject_properties);
|
||||
MUST_USE_RESULT MaybeObject* Copy();
|
||||
|
||||
// Returns the next free property index (only valid for FAST MODE).
|
||||
int NextFreePropertyIndex();
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define V8_PROPERTY_H_
|
||||
|
||||
#include "isolate.h"
|
||||
#include "factory.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -17,17 +18,15 @@ namespace internal {
|
||||
// optionally a piece of data.
|
||||
class Descriptor BASE_EMBEDDED {
|
||||
public:
|
||||
MUST_USE_RESULT MaybeObject* KeyToUniqueName() {
|
||||
void KeyToUniqueName() {
|
||||
if (!key_->IsUniqueName()) {
|
||||
MaybeObject* maybe_result =
|
||||
key_->GetIsolate()->heap()->InternalizeString(String::cast(key_));
|
||||
if (!maybe_result->To(&key_)) return maybe_result;
|
||||
key_ = key_->GetIsolate()->factory()->InternalizeString(
|
||||
Handle<String>::cast(key_));
|
||||
}
|
||||
return key_;
|
||||
}
|
||||
|
||||
Name* GetKey() { return key_; }
|
||||
Object* GetValue() { return value_; }
|
||||
Handle<Name> GetKey() { return key_; }
|
||||
Handle<Object> GetValue() { return value_; }
|
||||
PropertyDetails GetDetails() { return details_; }
|
||||
|
||||
#ifdef OBJECT_PRINT
|
||||
@ -37,26 +36,26 @@ class Descriptor BASE_EMBEDDED {
|
||||
void SetSortedKeyIndex(int index) { details_ = details_.set_pointer(index); }
|
||||
|
||||
private:
|
||||
Name* key_;
|
||||
Object* value_;
|
||||
Handle<Name> key_;
|
||||
Handle<Object> value_;
|
||||
PropertyDetails details_;
|
||||
|
||||
protected:
|
||||
Descriptor() : details_(Smi::FromInt(0)) {}
|
||||
|
||||
void Init(Name* key, Object* value, PropertyDetails details) {
|
||||
void Init(Handle<Name> key, Handle<Object> value, PropertyDetails details) {
|
||||
key_ = key;
|
||||
value_ = value;
|
||||
details_ = details;
|
||||
}
|
||||
|
||||
Descriptor(Name* key, Object* value, PropertyDetails details)
|
||||
Descriptor(Handle<Name> key, Handle<Object> value, PropertyDetails details)
|
||||
: key_(key),
|
||||
value_(value),
|
||||
details_(details) { }
|
||||
|
||||
Descriptor(Name* key,
|
||||
Object* value,
|
||||
Descriptor(Handle<Name> key,
|
||||
Handle<Object> value,
|
||||
PropertyAttributes attributes,
|
||||
PropertyType type,
|
||||
Representation representation,
|
||||
@ -71,19 +70,19 @@ class Descriptor BASE_EMBEDDED {
|
||||
|
||||
class FieldDescriptor V8_FINAL : public Descriptor {
|
||||
public:
|
||||
FieldDescriptor(Name* key,
|
||||
FieldDescriptor(Handle<Name> key,
|
||||
int field_index,
|
||||
PropertyAttributes attributes,
|
||||
Representation representation)
|
||||
: Descriptor(key, Smi::FromInt(0), attributes,
|
||||
: Descriptor(key, handle(Smi::FromInt(0), key->GetIsolate()), attributes,
|
||||
FIELD, representation, field_index) {}
|
||||
};
|
||||
|
||||
|
||||
class ConstantDescriptor V8_FINAL : public Descriptor {
|
||||
public:
|
||||
ConstantDescriptor(Name* key,
|
||||
Object* value,
|
||||
ConstantDescriptor(Handle<Name> key,
|
||||
Handle<Object> value,
|
||||
PropertyAttributes attributes)
|
||||
: Descriptor(key, value, attributes, CONSTANT,
|
||||
value->OptimalRepresentation()) {}
|
||||
@ -92,8 +91,8 @@ class ConstantDescriptor V8_FINAL : public Descriptor {
|
||||
|
||||
class CallbacksDescriptor V8_FINAL : public Descriptor {
|
||||
public:
|
||||
CallbacksDescriptor(Name* key,
|
||||
Object* foreign,
|
||||
CallbacksDescriptor(Handle<Name> key,
|
||||
Handle<Object> foreign,
|
||||
PropertyAttributes attributes)
|
||||
: Descriptor(key, foreign, attributes, CALLBACKS,
|
||||
Representation::Tagged()) {}
|
||||
|
@ -2944,32 +2944,32 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
|
||||
RUNTIME_ASSERT(args.length() == 1);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
|
||||
|
||||
String* name = isolate->heap()->prototype_string();
|
||||
Handle<String> name = isolate->factory()->prototype_string();
|
||||
|
||||
if (function->HasFastProperties()) {
|
||||
// Construct a new field descriptor with updated attributes.
|
||||
DescriptorArray* instance_desc = function->map()->instance_descriptors();
|
||||
Handle<DescriptorArray> instance_desc =
|
||||
handle(function->map()->instance_descriptors());
|
||||
|
||||
int index = instance_desc->SearchWithCache(name, function->map());
|
||||
int index = instance_desc->SearchWithCache(*name, function->map());
|
||||
ASSERT(index != DescriptorArray::kNotFound);
|
||||
PropertyDetails details = instance_desc->GetDetails(index);
|
||||
|
||||
CallbacksDescriptor new_desc(name,
|
||||
instance_desc->GetValue(index),
|
||||
CallbacksDescriptor new_desc(
|
||||
name,
|
||||
handle(instance_desc->GetValue(index), isolate),
|
||||
static_cast<PropertyAttributes>(details.attributes() | READ_ONLY));
|
||||
|
||||
// Create a new map featuring the new field descriptors array.
|
||||
Map* new_map;
|
||||
MaybeObject* maybe_map =
|
||||
function->map()->CopyReplaceDescriptor(
|
||||
instance_desc, &new_desc, index, OMIT_TRANSITION);
|
||||
if (!maybe_map->To(&new_map)) return maybe_map;
|
||||
Handle<Map> map = handle(function->map());
|
||||
Handle<Map> new_map = Map::CopyReplaceDescriptor(
|
||||
map, instance_desc, &new_desc, index, OMIT_TRANSITION);
|
||||
|
||||
JSObject::MigrateToMap(function, handle(new_map));
|
||||
JSObject::MigrateToMap(function, new_map);
|
||||
} else { // Dictionary properties.
|
||||
// Directly manipulate the property details.
|
||||
DisallowHeapAllocation no_gc;
|
||||
int entry = function->property_dictionary()->FindEntry(name);
|
||||
int entry = function->property_dictionary()->FindEntry(*name);
|
||||
ASSERT(entry != NameDictionary::kNotFound);
|
||||
PropertyDetails details = function->property_dictionary()->DetailsAt(entry);
|
||||
PropertyDetails new_details(
|
||||
|
@ -55,6 +55,17 @@ MaybeObject* TransitionArray::Allocate(Isolate* isolate,
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* TransitionArray::AllocateSimple(Isolate* isolate,
|
||||
Map* target) {
|
||||
FixedArray* array;
|
||||
MaybeObject* maybe_array =
|
||||
AllocateRaw(isolate, kSimpleTransitionSize);
|
||||
if (!maybe_array->To(&array)) return maybe_array;
|
||||
array->set(kSimpleTransitionTarget, target);
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
void TransitionArray::NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin,
|
||||
int origin_transition,
|
||||
int target_transition) {
|
||||
@ -69,23 +80,20 @@ static bool InsertionPointFound(Name* key1, Name* key2) {
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* TransitionArray::NewWith(SimpleTransitionFlag flag,
|
||||
Name* key,
|
||||
Map* target,
|
||||
Object* back_pointer) {
|
||||
TransitionArray* result;
|
||||
MaybeObject* maybe_result;
|
||||
Handle<TransitionArray> TransitionArray::NewWith(SimpleTransitionFlag flag,
|
||||
Handle<Name> key,
|
||||
Handle<Map> target,
|
||||
Handle<Object> back_pointer) {
|
||||
Handle<TransitionArray> result;
|
||||
Factory* factory = key->GetIsolate()->factory();
|
||||
|
||||
if (flag == SIMPLE_TRANSITION) {
|
||||
maybe_result = AllocateRaw(target->GetIsolate(), kSimpleTransitionSize);
|
||||
if (!maybe_result->To(&result)) return maybe_result;
|
||||
result->set(kSimpleTransitionTarget, target);
|
||||
result = factory->NewSimpleTransitionArray(target);
|
||||
} else {
|
||||
maybe_result = Allocate(target->GetIsolate(), 1);
|
||||
if (!maybe_result->To(&result)) return maybe_result;
|
||||
result->NoIncrementalWriteBarrierSet(0, key, target);
|
||||
result = factory->NewTransitionArray(1);
|
||||
result->NoIncrementalWriteBarrierSet(0, *key, *target);
|
||||
}
|
||||
result->set_back_pointer_storage(back_pointer);
|
||||
result->set_back_pointer_storage(*back_pointer);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -106,49 +114,67 @@ MaybeObject* TransitionArray::ExtendToFullTransitionArray() {
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* TransitionArray::CopyInsert(Name* name, Map* target) {
|
||||
TransitionArray* result;
|
||||
Handle<TransitionArray> TransitionArray::CopyInsert(Handle<Map> map,
|
||||
Handle<Name> name,
|
||||
Handle<Map> target) {
|
||||
ASSERT(map->HasTransitionArray());
|
||||
Handle<TransitionArray> result;
|
||||
|
||||
int number_of_transitions = this->number_of_transitions();
|
||||
int number_of_transitions = map->transitions()->number_of_transitions();
|
||||
int new_size = number_of_transitions;
|
||||
|
||||
int insertion_index = this->Search(name);
|
||||
int insertion_index = map->transitions()->Search(*name);
|
||||
if (insertion_index == kNotFound) ++new_size;
|
||||
|
||||
MaybeObject* maybe_array;
|
||||
maybe_array = TransitionArray::Allocate(GetIsolate(), new_size);
|
||||
if (!maybe_array->To(&result)) return maybe_array;
|
||||
result = map->GetIsolate()->factory()->NewTransitionArray(new_size);
|
||||
|
||||
if (HasPrototypeTransitions()) {
|
||||
result->SetPrototypeTransitions(GetPrototypeTransitions());
|
||||
// The map's transition array may have grown smaller during the allocation
|
||||
// above as it was weakly traversed. Trim the result copy if needed, and
|
||||
// recompute variables.
|
||||
DisallowHeapAllocation no_gc;
|
||||
TransitionArray* array = map->transitions();
|
||||
if (array->number_of_transitions() != number_of_transitions) {
|
||||
ASSERT(array->number_of_transitions() < number_of_transitions);
|
||||
|
||||
number_of_transitions = array->number_of_transitions();
|
||||
new_size = number_of_transitions;
|
||||
|
||||
insertion_index = array->Search(*name);
|
||||
if (insertion_index == kNotFound) ++new_size;
|
||||
|
||||
result->Shrink(new_size);
|
||||
}
|
||||
|
||||
if (array->HasPrototypeTransitions()) {
|
||||
result->SetPrototypeTransitions(array->GetPrototypeTransitions());
|
||||
}
|
||||
|
||||
if (insertion_index != kNotFound) {
|
||||
for (int i = 0; i < number_of_transitions; ++i) {
|
||||
if (i != insertion_index) {
|
||||
result->NoIncrementalWriteBarrierCopyFrom(this, i, i);
|
||||
result->NoIncrementalWriteBarrierCopyFrom(array, i, i);
|
||||
}
|
||||
}
|
||||
result->NoIncrementalWriteBarrierSet(insertion_index, name, target);
|
||||
result->set_back_pointer_storage(back_pointer_storage());
|
||||
result->NoIncrementalWriteBarrierSet(insertion_index, *name, *target);
|
||||
result->set_back_pointer_storage(array->back_pointer_storage());
|
||||
return result;
|
||||
}
|
||||
|
||||
insertion_index = 0;
|
||||
for (; insertion_index < number_of_transitions; ++insertion_index) {
|
||||
if (InsertionPointFound(GetKey(insertion_index), name)) break;
|
||||
if (InsertionPointFound(array->GetKey(insertion_index), *name)) break;
|
||||
result->NoIncrementalWriteBarrierCopyFrom(
|
||||
this, insertion_index, insertion_index);
|
||||
array, insertion_index, insertion_index);
|
||||
}
|
||||
|
||||
result->NoIncrementalWriteBarrierSet(insertion_index, name, target);
|
||||
result->NoIncrementalWriteBarrierSet(insertion_index, *name, *target);
|
||||
|
||||
for (; insertion_index < number_of_transitions; ++insertion_index) {
|
||||
result->NoIncrementalWriteBarrierCopyFrom(
|
||||
this, insertion_index, insertion_index + 1);
|
||||
array, insertion_index, insertion_index + 1);
|
||||
}
|
||||
|
||||
result->set_back_pointer_storage(back_pointer_storage());
|
||||
result->set_back_pointer_storage(array->back_pointer_storage());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -96,18 +96,19 @@ class TransitionArray: public FixedArray {
|
||||
inline int number_of_entries() { return number_of_transitions(); }
|
||||
|
||||
// Allocate a new transition array with a single entry.
|
||||
static MUST_USE_RESULT MaybeObject* NewWith(
|
||||
SimpleTransitionFlag flag,
|
||||
Name* key,
|
||||
Map* target,
|
||||
Object* back_pointer);
|
||||
static Handle<TransitionArray> NewWith(SimpleTransitionFlag flag,
|
||||
Handle<Name> key,
|
||||
Handle<Map> target,
|
||||
Handle<Object> back_pointer);
|
||||
|
||||
MUST_USE_RESULT MaybeObject* ExtendToFullTransitionArray();
|
||||
|
||||
// Copy the transition array, inserting a new transition.
|
||||
// TODO(verwaest): This should not cause an existing transition to be
|
||||
// overwritten.
|
||||
MUST_USE_RESULT MaybeObject* CopyInsert(Name* name, Map* target);
|
||||
static Handle<TransitionArray> CopyInsert(Handle<Map> map,
|
||||
Handle<Name> name,
|
||||
Handle<Map> target);
|
||||
|
||||
// Copy a single transition from the origin array.
|
||||
inline void NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin,
|
||||
@ -121,6 +122,9 @@ class TransitionArray: public FixedArray {
|
||||
MUST_USE_RESULT static MaybeObject* Allocate(
|
||||
Isolate* isolate, int number_of_transitions);
|
||||
|
||||
MUST_USE_RESULT static MaybeObject* AllocateSimple(
|
||||
Isolate* isolate, Map* target);
|
||||
|
||||
bool IsSimpleTransition() {
|
||||
return length() == kSimpleTransitionSize &&
|
||||
get(kSimpleTransitionTarget)->IsHeapObject() &&
|
||||
|
@ -142,8 +142,8 @@ TEST(StressJS) {
|
||||
v8::internal::DescriptorArray::WhitenessWitness witness(*new_descriptors);
|
||||
map->set_instance_descriptors(*new_descriptors);
|
||||
|
||||
CallbacksDescriptor d(*name,
|
||||
*foreign,
|
||||
CallbacksDescriptor d(name,
|
||||
foreign,
|
||||
static_cast<PropertyAttributes>(0));
|
||||
map->AppendDescriptor(&d, witness);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user