OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 4330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4341 if (pt->IsJSProxy()) { | 4341 if (pt->IsJSProxy()) { |
4342 // We need to follow the spec and simulate a call to [[GetOwnProperty]]. | 4342 // We need to follow the spec and simulate a call to [[GetOwnProperty]]. |
4343 return JSProxy::cast(pt)->GetElementAttributeWithHandler(receiver, index); | 4343 return JSProxy::cast(pt)->GetElementAttributeWithHandler(receiver, index); |
4344 } | 4344 } |
4345 if (pt->IsNull()) return ABSENT; | 4345 if (pt->IsNull()) return ABSENT; |
4346 return JSObject::cast(pt)->GetElementAttributeWithReceiver( | 4346 return JSObject::cast(pt)->GetElementAttributeWithReceiver( |
4347 receiver, index, true); | 4347 receiver, index, true); |
4348 } | 4348 } |
4349 | 4349 |
4350 | 4350 |
4351 MaybeObject* NormalizedMapCache::Get(JSObject* obj, | 4351 Handle<Map> NormalizedMapCache::Get(Handle<NormalizedMapCache> cache, |
4352 PropertyNormalizationMode mode) { | 4352 Handle<JSObject> obj, |
4353 Isolate* isolate = obj->GetIsolate(); | 4353 PropertyNormalizationMode mode) { |
4354 Map* fast = obj->map(); | 4354 Map* fast = obj->map(); |
4355 int index = fast->Hash() % kEntries; | 4355 int index = fast->Hash() % kEntries; |
4356 Object* result = get(index); | 4356 Object* result = cache->get(index); |
4357 if (result->IsMap() && | 4357 if (result->IsMap() && |
4358 Map::cast(result)->EquivalentToForNormalization(fast, mode)) { | 4358 Map::cast(result)->EquivalentToForNormalization(fast, mode)) { |
4359 #ifdef VERIFY_HEAP | 4359 #ifdef VERIFY_HEAP |
4360 if (FLAG_verify_heap) { | 4360 if (FLAG_verify_heap) { |
4361 Map::cast(result)->SharedMapVerify(); | 4361 Map::cast(result)->SharedMapVerify(); |
4362 } | 4362 } |
4363 #endif | 4363 #endif |
4364 #ifdef DEBUG | 4364 #ifdef DEBUG |
4365 if (FLAG_enable_slow_asserts) { | 4365 if (FLAG_enable_slow_asserts) { |
4366 // The cached map should match newly created normalized map bit-by-bit, | 4366 // The cached map should match newly created normalized map bit-by-bit, |
4367 // except for the code cache, which can contain some ics which can be | 4367 // except for the code cache, which can contain some ics which can be |
4368 // applied to the shared map. | 4368 // applied to the shared map. |
4369 Object* fresh; | 4369 Object* fresh; |
4370 MaybeObject* maybe_fresh = | 4370 MaybeObject* maybe_fresh = |
4371 fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP); | 4371 fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP); |
4372 if (maybe_fresh->ToObject(&fresh)) { | 4372 if (maybe_fresh->ToObject(&fresh)) { |
4373 ASSERT(memcmp(Map::cast(fresh)->address(), | 4373 ASSERT(memcmp(Map::cast(fresh)->address(), |
4374 Map::cast(result)->address(), | 4374 Map::cast(result)->address(), |
4375 Map::kCodeCacheOffset) == 0); | 4375 Map::kCodeCacheOffset) == 0); |
4376 STATIC_ASSERT(Map::kDependentCodeOffset == | 4376 STATIC_ASSERT(Map::kDependentCodeOffset == |
4377 Map::kCodeCacheOffset + kPointerSize); | 4377 Map::kCodeCacheOffset + kPointerSize); |
4378 int offset = Map::kDependentCodeOffset + kPointerSize; | 4378 int offset = Map::kDependentCodeOffset + kPointerSize; |
4379 ASSERT(memcmp(Map::cast(fresh)->address() + offset, | 4379 ASSERT(memcmp(Map::cast(fresh)->address() + offset, |
4380 Map::cast(result)->address() + offset, | 4380 Map::cast(result)->address() + offset, |
4381 Map::kSize - offset) == 0); | 4381 Map::kSize - offset) == 0); |
4382 } | 4382 } |
4383 } | 4383 } |
4384 #endif | 4384 #endif |
4385 return result; | 4385 return handle(Map::cast(result)); |
4386 } | 4386 } |
4387 | 4387 |
4388 { MaybeObject* maybe_result = | 4388 Isolate* isolate = cache->GetIsolate(); |
4389 fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP); | 4389 Handle<Map> map = Map::CopyNormalized(handle(fast), mode, |
4390 if (!maybe_result->ToObject(&result)) return maybe_result; | 4390 SHARED_NORMALIZED_MAP); |
4391 } | 4391 ASSERT(map->is_dictionary_map()); |
4392 ASSERT(Map::cast(result)->is_dictionary_map()); | 4392 cache->set(index, *map); |
4393 set(index, result); | |
4394 isolate->counters()->normalized_maps()->Increment(); | 4393 isolate->counters()->normalized_maps()->Increment(); |
4395 | 4394 |
4396 return result; | 4395 return map; |
4397 } | 4396 } |
4398 | 4397 |
4399 | 4398 |
4400 void NormalizedMapCache::Clear() { | 4399 void NormalizedMapCache::Clear() { |
4401 int entries = length(); | 4400 int entries = length(); |
4402 for (int i = 0; i != entries; i++) { | 4401 for (int i = 0; i != entries; i++) { |
4403 set_undefined(i); | 4402 set_undefined(i); |
4404 } | 4403 } |
4405 } | 4404 } |
4406 | 4405 |
(...skipping 12 matching lines...) Expand all Loading... | |
4419 receiver->GetIsolate()->counters()->normalized_maps()->Increment(); | 4418 receiver->GetIsolate()->counters()->normalized_maps()->Increment(); |
4420 receiver->set_map(*map); | 4419 receiver->set_map(*map); |
4421 } | 4420 } |
4422 Map::UpdateCodeCache(map, name, code); | 4421 Map::UpdateCodeCache(map, name, code); |
4423 } | 4422 } |
4424 | 4423 |
4425 | 4424 |
4426 void JSObject::NormalizeProperties(Handle<JSObject> object, | 4425 void JSObject::NormalizeProperties(Handle<JSObject> object, |
4427 PropertyNormalizationMode mode, | 4426 PropertyNormalizationMode mode, |
4428 int expected_additional_properties) { | 4427 int expected_additional_properties) { |
4429 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), | 4428 if (!object->HasFastProperties()) return; |
4430 object->NormalizeProperties( | |
4431 mode, expected_additional_properties)); | |
4432 } | |
4433 | |
4434 | |
4435 MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode, | |
4436 int expected_additional_properties) { | |
4437 if (!HasFastProperties()) return this; | |
4438 | 4429 |
4439 // The global object is always normalized. | 4430 // The global object is always normalized. |
4440 ASSERT(!IsGlobalObject()); | 4431 ASSERT(!object->IsGlobalObject()); |
4441 // JSGlobalProxy must never be normalized | 4432 // JSGlobalProxy must never be normalized |
4442 ASSERT(!IsJSGlobalProxy()); | 4433 ASSERT(!object->IsJSGlobalProxy()); |
4443 | 4434 |
4444 Map* map_of_this = map(); | 4435 Isolate* isolate = object->GetIsolate(); |
4436 Map* map(object->map()); | |
Toon Verwaest
2013/09/20 09:32:41
Handle<Map>
Michael Starzinger
2013/09/20 10:46:31
Done.
| |
4445 | 4437 |
Toon Verwaest
2013/09/20 09:32:41
Given that no handle escapes this method, and sinc
Michael Starzinger
2013/09/20 10:46:31
Done.
| |
4446 // Allocate new content. | 4438 // Allocate new content. |
4447 int real_size = map_of_this->NumberOfOwnDescriptors(); | 4439 int real_size = map->NumberOfOwnDescriptors(); |
4448 int property_count = real_size; | 4440 int property_count = real_size; |
4449 if (expected_additional_properties > 0) { | 4441 if (expected_additional_properties > 0) { |
4450 property_count += expected_additional_properties; | 4442 property_count += expected_additional_properties; |
4451 } else { | 4443 } else { |
4452 property_count += 2; // Make space for two more properties. | 4444 property_count += 2; // Make space for two more properties. |
4453 } | 4445 } |
4454 NameDictionary* dictionary; | 4446 Handle<NameDictionary> dictionary = |
4455 MaybeObject* maybe_dictionary = | 4447 isolate->factory()->NewNameDictionary(property_count); |
4456 NameDictionary::Allocate(GetHeap(), property_count); | |
4457 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; | |
4458 | 4448 |
4459 DescriptorArray* descs = map_of_this->instance_descriptors(); | 4449 Handle<DescriptorArray> descs(map->instance_descriptors()); |
4460 for (int i = 0; i < real_size; i++) { | 4450 for (int i = 0; i < real_size; i++) { |
4461 PropertyDetails details = descs->GetDetails(i); | 4451 PropertyDetails details = descs->GetDetails(i); |
4462 switch (details.type()) { | 4452 switch (details.type()) { |
4463 case CONSTANT: { | 4453 case CONSTANT: { |
4454 Handle<Name> key(descs->GetKey(i)); | |
4455 Handle<Object> value(descs->GetConstant(i), isolate); | |
4464 PropertyDetails d = PropertyDetails( | 4456 PropertyDetails d = PropertyDetails( |
4465 details.attributes(), NORMAL, i + 1); | 4457 details.attributes(), NORMAL, i + 1); |
4466 Object* value = descs->GetConstant(i); | 4458 dictionary = NameDictionaryAdd(dictionary, key, value, d); |
4467 MaybeObject* maybe_dictionary = | |
4468 dictionary->Add(descs->GetKey(i), value, d); | |
4469 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; | |
4470 break; | 4459 break; |
4471 } | 4460 } |
4472 case FIELD: { | 4461 case FIELD: { |
4462 Handle<Name> key(descs->GetKey(i)); | |
4463 Handle<Object> value( | |
4464 object->RawFastPropertyAt(descs->GetFieldIndex(i)), isolate); | |
4473 PropertyDetails d = | 4465 PropertyDetails d = |
4474 PropertyDetails(details.attributes(), NORMAL, i + 1); | 4466 PropertyDetails(details.attributes(), NORMAL, i + 1); |
4475 Object* value = RawFastPropertyAt(descs->GetFieldIndex(i)); | 4467 dictionary = NameDictionaryAdd(dictionary, key, value, d); |
4476 MaybeObject* maybe_dictionary = | |
4477 dictionary->Add(descs->GetKey(i), value, d); | |
4478 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; | |
4479 break; | 4468 break; |
4480 } | 4469 } |
4481 case CALLBACKS: { | 4470 case CALLBACKS: { |
4482 Object* value = descs->GetCallbacksObject(i); | 4471 Handle<Name> key(descs->GetKey(i)); |
4472 Handle<Object> value(descs->GetCallbacksObject(i), isolate); | |
4483 PropertyDetails d = PropertyDetails( | 4473 PropertyDetails d = PropertyDetails( |
4484 details.attributes(), CALLBACKS, i + 1); | 4474 details.attributes(), CALLBACKS, i + 1); |
4485 MaybeObject* maybe_dictionary = | 4475 dictionary = NameDictionaryAdd(dictionary, key, value, d); |
4486 dictionary->Add(descs->GetKey(i), value, d); | |
4487 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; | |
4488 break; | 4476 break; |
4489 } | 4477 } |
4490 case INTERCEPTOR: | 4478 case INTERCEPTOR: |
4491 break; | 4479 break; |
4492 case HANDLER: | 4480 case HANDLER: |
4493 case NORMAL: | 4481 case NORMAL: |
4494 case TRANSITION: | 4482 case TRANSITION: |
4495 case NONEXISTENT: | 4483 case NONEXISTENT: |
4496 UNREACHABLE(); | 4484 UNREACHABLE(); |
4497 break; | 4485 break; |
4498 } | 4486 } |
4499 } | 4487 } |
4500 | 4488 |
4501 Heap* current_heap = GetHeap(); | |
4502 | |
4503 // Copy the next enumeration index from instance descriptor. | 4489 // Copy the next enumeration index from instance descriptor. |
4504 dictionary->SetNextEnumerationIndex(real_size + 1); | 4490 dictionary->SetNextEnumerationIndex(real_size + 1); |
4505 | 4491 |
4506 Map* new_map; | 4492 Handle<NormalizedMapCache> cache( |
4507 MaybeObject* maybe_map = | 4493 isolate->context()->native_context()->normalized_map_cache()); |
4508 current_heap->isolate()->context()->native_context()-> | 4494 Handle<Map> new_map = NormalizedMapCache::Get(cache, object, mode); |
4509 normalized_map_cache()->Get(this, mode); | |
4510 if (!maybe_map->To(&new_map)) return maybe_map; | |
4511 ASSERT(new_map->is_dictionary_map()); | 4495 ASSERT(new_map->is_dictionary_map()); |
4512 | 4496 |
4513 // We have now successfully allocated all the necessary objects. | 4497 // From here on we cannot fail and we shouldn't GC anymore. |
Toon Verwaest
2013/09/20 09:32:41
What about putting this into
{ DisallowHeapAlloca
Michael Starzinger
2013/09/20 10:46:31
Done. Good point!
| |
4514 // Changes can now be made with the guarantee that all of them take effect. | |
4515 | 4498 |
4516 // Resize the object in the heap if necessary. | 4499 // Resize the object in the heap if necessary. |
4517 int new_instance_size = new_map->instance_size(); | 4500 int new_instance_size = new_map->instance_size(); |
4518 int instance_size_delta = map_of_this->instance_size() - new_instance_size; | 4501 int instance_size_delta = map->instance_size() - new_instance_size; |
4519 ASSERT(instance_size_delta >= 0); | 4502 ASSERT(instance_size_delta >= 0); |
4520 current_heap->CreateFillerObjectAt(this->address() + new_instance_size, | 4503 isolate->heap()->CreateFillerObjectAt(object->address() + new_instance_size, |
4521 instance_size_delta); | 4504 instance_size_delta); |
4522 if (Marking::IsBlack(Marking::MarkBitFrom(this))) { | 4505 if (Marking::IsBlack(Marking::MarkBitFrom(*object))) { |
4523 MemoryChunk::IncrementLiveBytesFromMutator(this->address(), | 4506 MemoryChunk::IncrementLiveBytesFromMutator(object->address(), |
4524 -instance_size_delta); | 4507 -instance_size_delta); |
4525 } | 4508 } |
4526 | 4509 |
4527 set_map(new_map); | 4510 object->set_map(*new_map); |
4528 map_of_this->NotifyLeafMapLayoutChange(); | 4511 map->NotifyLeafMapLayoutChange(); |
4529 | 4512 |
4530 set_properties(dictionary); | 4513 object->set_properties(*dictionary); |
4531 | 4514 |
4532 current_heap->isolate()->counters()->props_to_dictionary()->Increment(); | 4515 isolate->counters()->props_to_dictionary()->Increment(); |
4533 | 4516 |
4534 #ifdef DEBUG | 4517 #ifdef DEBUG |
4535 if (FLAG_trace_normalization) { | 4518 if (FLAG_trace_normalization) { |
4536 PrintF("Object properties have been normalized:\n"); | 4519 PrintF("Object properties have been normalized:\n"); |
4537 Print(); | 4520 object->Print(); |
4538 } | 4521 } |
4539 #endif | 4522 #endif |
4540 return this; | |
4541 } | 4523 } |
4542 | 4524 |
4543 | 4525 |
4544 void JSObject::TransformToFastProperties(Handle<JSObject> object, | 4526 void JSObject::TransformToFastProperties(Handle<JSObject> object, |
4545 int unused_property_fields) { | 4527 int unused_property_fields) { |
4528 if (object->HasFastProperties()) return; | |
4529 ASSERT(!object->IsGlobalObject()); | |
4546 CALL_HEAP_FUNCTION_VOID( | 4530 CALL_HEAP_FUNCTION_VOID( |
4547 object->GetIsolate(), | 4531 object->GetIsolate(), |
4548 object->TransformToFastProperties(unused_property_fields)); | 4532 object->property_dictionary()->TransformPropertiesToFastFor( |
4533 *object, unused_property_fields)); | |
4549 } | 4534 } |
4550 | 4535 |
4551 | 4536 |
4552 MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) { | |
4553 if (HasFastProperties()) return this; | |
4554 ASSERT(!IsGlobalObject()); | |
4555 return property_dictionary()-> | |
4556 TransformPropertiesToFastFor(this, unused_property_fields); | |
4557 } | |
4558 | |
4559 | |
4560 static MUST_USE_RESULT MaybeObject* CopyFastElementsToDictionary( | 4537 static MUST_USE_RESULT MaybeObject* CopyFastElementsToDictionary( |
4561 Isolate* isolate, | 4538 Isolate* isolate, |
4562 FixedArrayBase* array, | 4539 FixedArrayBase* array, |
4563 int length, | 4540 int length, |
4564 SeededNumberDictionary* dictionary) { | 4541 SeededNumberDictionary* dictionary) { |
4565 Heap* heap = isolate->heap(); | 4542 Heap* heap = isolate->heap(); |
4566 bool has_double_elements = array->IsFixedDoubleArray(); | 4543 bool has_double_elements = array->IsFixedDoubleArray(); |
4567 for (int i = 0; i < length; i++) { | 4544 for (int i = 0; i < length; i++) { |
4568 Object* value = NULL; | 4545 Object* value = NULL; |
4569 if (has_double_elements) { | 4546 if (has_double_elements) { |
(...skipping 11538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
16108 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16085 #define ERROR_MESSAGES_TEXTS(C, T) T, |
16109 static const char* error_messages_[] = { | 16086 static const char* error_messages_[] = { |
16110 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16087 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
16111 }; | 16088 }; |
16112 #undef ERROR_MESSAGES_TEXTS | 16089 #undef ERROR_MESSAGES_TEXTS |
16113 return error_messages_[reason]; | 16090 return error_messages_[reason]; |
16114 } | 16091 } |
16115 | 16092 |
16116 | 16093 |
16117 } } // namespace v8::internal | 16094 } } // namespace v8::internal |
OLD | NEW |