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 HandleScope scope(isolate); |
| 4437 Handle<Map> map(object->map()); |
4445 | 4438 |
4446 // Allocate new content. | 4439 // Allocate new content. |
4447 int real_size = map_of_this->NumberOfOwnDescriptors(); | 4440 int real_size = map->NumberOfOwnDescriptors(); |
4448 int property_count = real_size; | 4441 int property_count = real_size; |
4449 if (expected_additional_properties > 0) { | 4442 if (expected_additional_properties > 0) { |
4450 property_count += expected_additional_properties; | 4443 property_count += expected_additional_properties; |
4451 } else { | 4444 } else { |
4452 property_count += 2; // Make space for two more properties. | 4445 property_count += 2; // Make space for two more properties. |
4453 } | 4446 } |
4454 NameDictionary* dictionary; | 4447 Handle<NameDictionary> dictionary = |
4455 MaybeObject* maybe_dictionary = | 4448 isolate->factory()->NewNameDictionary(property_count); |
4456 NameDictionary::Allocate(GetHeap(), property_count); | |
4457 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; | |
4458 | 4449 |
4459 DescriptorArray* descs = map_of_this->instance_descriptors(); | 4450 Handle<DescriptorArray> descs(map->instance_descriptors()); |
4460 for (int i = 0; i < real_size; i++) { | 4451 for (int i = 0; i < real_size; i++) { |
4461 PropertyDetails details = descs->GetDetails(i); | 4452 PropertyDetails details = descs->GetDetails(i); |
4462 switch (details.type()) { | 4453 switch (details.type()) { |
4463 case CONSTANT: { | 4454 case CONSTANT: { |
| 4455 Handle<Name> key(descs->GetKey(i)); |
| 4456 Handle<Object> value(descs->GetConstant(i), isolate); |
4464 PropertyDetails d = PropertyDetails( | 4457 PropertyDetails d = PropertyDetails( |
4465 details.attributes(), NORMAL, i + 1); | 4458 details.attributes(), NORMAL, i + 1); |
4466 Object* value = descs->GetConstant(i); | 4459 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; | 4460 break; |
4471 } | 4461 } |
4472 case FIELD: { | 4462 case FIELD: { |
| 4463 Handle<Name> key(descs->GetKey(i)); |
| 4464 Handle<Object> value( |
| 4465 object->RawFastPropertyAt(descs->GetFieldIndex(i)), isolate); |
4473 PropertyDetails d = | 4466 PropertyDetails d = |
4474 PropertyDetails(details.attributes(), NORMAL, i + 1); | 4467 PropertyDetails(details.attributes(), NORMAL, i + 1); |
4475 Object* value = RawFastPropertyAt(descs->GetFieldIndex(i)); | 4468 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; | 4469 break; |
4480 } | 4470 } |
4481 case CALLBACKS: { | 4471 case CALLBACKS: { |
4482 Object* value = descs->GetCallbacksObject(i); | 4472 Handle<Name> key(descs->GetKey(i)); |
| 4473 Handle<Object> value(descs->GetCallbacksObject(i), isolate); |
4483 PropertyDetails d = PropertyDetails( | 4474 PropertyDetails d = PropertyDetails( |
4484 details.attributes(), CALLBACKS, i + 1); | 4475 details.attributes(), CALLBACKS, i + 1); |
4485 MaybeObject* maybe_dictionary = | 4476 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; | 4477 break; |
4489 } | 4478 } |
4490 case INTERCEPTOR: | 4479 case INTERCEPTOR: |
4491 break; | 4480 break; |
4492 case HANDLER: | 4481 case HANDLER: |
4493 case NORMAL: | 4482 case NORMAL: |
4494 case TRANSITION: | 4483 case TRANSITION: |
4495 case NONEXISTENT: | 4484 case NONEXISTENT: |
4496 UNREACHABLE(); | 4485 UNREACHABLE(); |
4497 break; | 4486 break; |
4498 } | 4487 } |
4499 } | 4488 } |
4500 | 4489 |
4501 Heap* current_heap = GetHeap(); | |
4502 | |
4503 // Copy the next enumeration index from instance descriptor. | 4490 // Copy the next enumeration index from instance descriptor. |
4504 dictionary->SetNextEnumerationIndex(real_size + 1); | 4491 dictionary->SetNextEnumerationIndex(real_size + 1); |
4505 | 4492 |
4506 Map* new_map; | 4493 Handle<NormalizedMapCache> cache( |
4507 MaybeObject* maybe_map = | 4494 isolate->context()->native_context()->normalized_map_cache()); |
4508 current_heap->isolate()->context()->native_context()-> | 4495 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()); | 4496 ASSERT(new_map->is_dictionary_map()); |
4512 | 4497 |
4513 // We have now successfully allocated all the necessary objects. | 4498 // From here on we cannot fail and we shouldn't GC anymore. |
4514 // Changes can now be made with the guarantee that all of them take effect. | 4499 DisallowHeapAllocation no_allocation; |
4515 | 4500 |
4516 // Resize the object in the heap if necessary. | 4501 // Resize the object in the heap if necessary. |
4517 int new_instance_size = new_map->instance_size(); | 4502 int new_instance_size = new_map->instance_size(); |
4518 int instance_size_delta = map_of_this->instance_size() - new_instance_size; | 4503 int instance_size_delta = map->instance_size() - new_instance_size; |
4519 ASSERT(instance_size_delta >= 0); | 4504 ASSERT(instance_size_delta >= 0); |
4520 current_heap->CreateFillerObjectAt(this->address() + new_instance_size, | 4505 isolate->heap()->CreateFillerObjectAt(object->address() + new_instance_size, |
4521 instance_size_delta); | 4506 instance_size_delta); |
4522 if (Marking::IsBlack(Marking::MarkBitFrom(this))) { | 4507 if (Marking::IsBlack(Marking::MarkBitFrom(*object))) { |
4523 MemoryChunk::IncrementLiveBytesFromMutator(this->address(), | 4508 MemoryChunk::IncrementLiveBytesFromMutator(object->address(), |
4524 -instance_size_delta); | 4509 -instance_size_delta); |
4525 } | 4510 } |
4526 | 4511 |
4527 set_map(new_map); | 4512 object->set_map(*new_map); |
4528 map_of_this->NotifyLeafMapLayoutChange(); | 4513 map->NotifyLeafMapLayoutChange(); |
4529 | 4514 |
4530 set_properties(dictionary); | 4515 object->set_properties(*dictionary); |
4531 | 4516 |
4532 current_heap->isolate()->counters()->props_to_dictionary()->Increment(); | 4517 isolate->counters()->props_to_dictionary()->Increment(); |
4533 | 4518 |
4534 #ifdef DEBUG | 4519 #ifdef DEBUG |
4535 if (FLAG_trace_normalization) { | 4520 if (FLAG_trace_normalization) { |
4536 PrintF("Object properties have been normalized:\n"); | 4521 PrintF("Object properties have been normalized:\n"); |
4537 Print(); | 4522 object->Print(); |
4538 } | 4523 } |
4539 #endif | 4524 #endif |
4540 return this; | |
4541 } | 4525 } |
4542 | 4526 |
4543 | 4527 |
4544 void JSObject::TransformToFastProperties(Handle<JSObject> object, | 4528 void JSObject::TransformToFastProperties(Handle<JSObject> object, |
4545 int unused_property_fields) { | 4529 int unused_property_fields) { |
| 4530 if (object->HasFastProperties()) return; |
| 4531 ASSERT(!object->IsGlobalObject()); |
4546 CALL_HEAP_FUNCTION_VOID( | 4532 CALL_HEAP_FUNCTION_VOID( |
4547 object->GetIsolate(), | 4533 object->GetIsolate(), |
4548 object->TransformToFastProperties(unused_property_fields)); | 4534 object->property_dictionary()->TransformPropertiesToFastFor( |
| 4535 *object, unused_property_fields)); |
4549 } | 4536 } |
4550 | 4537 |
4551 | 4538 |
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( | 4539 static MUST_USE_RESULT MaybeObject* CopyFastElementsToDictionary( |
4561 Isolate* isolate, | 4540 Isolate* isolate, |
4562 FixedArrayBase* array, | 4541 FixedArrayBase* array, |
4563 int length, | 4542 int length, |
4564 SeededNumberDictionary* dictionary) { | 4543 SeededNumberDictionary* dictionary) { |
4565 Heap* heap = isolate->heap(); | 4544 Heap* heap = isolate->heap(); |
4566 bool has_double_elements = array->IsFixedDoubleArray(); | 4545 bool has_double_elements = array->IsFixedDoubleArray(); |
4567 for (int i = 0; i < length; i++) { | 4546 for (int i = 0; i < length; i++) { |
4568 Object* value = NULL; | 4547 Object* value = NULL; |
4569 if (has_double_elements) { | 4548 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, | 16087 #define ERROR_MESSAGES_TEXTS(C, T) T, |
16109 static const char* error_messages_[] = { | 16088 static const char* error_messages_[] = { |
16110 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16089 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
16111 }; | 16090 }; |
16112 #undef ERROR_MESSAGES_TEXTS | 16091 #undef ERROR_MESSAGES_TEXTS |
16113 return error_messages_[reason]; | 16092 return error_messages_[reason]; |
16114 } | 16093 } |
16115 | 16094 |
16116 | 16095 |
16117 } } // namespace v8::internal | 16096 } } // namespace v8::internal |
OLD | NEW |