Revision f230a1cf deps/v8/src/objects.cc
deps/v8/src/objects.cc | ||
---|---|---|
28 | 28 |
#include "v8.h" |
29 | 29 |
|
30 | 30 |
#include "accessors.h" |
31 |
#include "allocation-site-scopes.h" |
|
31 | 32 |
#include "api.h" |
32 | 33 |
#include "arguments.h" |
33 | 34 |
#include "bootstrapper.h" |
... | ... | |
142 | 143 |
} |
143 | 144 |
|
144 | 145 |
|
146 |
Handle<Object> Object::GetPropertyWithReceiver( |
|
147 |
Handle<Object> object, |
|
148 |
Handle<Object> receiver, |
|
149 |
Handle<Name> name, |
|
150 |
PropertyAttributes* attributes) { |
|
151 |
LookupResult lookup(name->GetIsolate()); |
|
152 |
object->Lookup(*name, &lookup); |
|
153 |
Handle<Object> result = |
|
154 |
GetProperty(object, receiver, &lookup, name, attributes); |
|
155 |
ASSERT(*attributes <= ABSENT); |
|
156 |
return result; |
|
157 |
} |
|
158 |
|
|
159 |
|
|
145 | 160 |
MaybeObject* Object::GetPropertyWithReceiver(Object* receiver, |
146 | 161 |
Name* name, |
147 | 162 |
PropertyAttributes* attributes) { |
... | ... | |
328 | 343 |
} |
329 | 344 |
|
330 | 345 |
|
331 |
MaybeObject* JSObject::GetPropertyWithCallback(Object* receiver, |
|
332 |
Object* structure, |
|
333 |
Name* name) { |
|
346 |
Handle<FixedArray> JSObject::EnsureWritableFastElements( |
|
347 |
Handle<JSObject> object) { |
|
348 |
CALL_HEAP_FUNCTION(object->GetIsolate(), |
|
349 |
object->EnsureWritableFastElements(), |
|
350 |
FixedArray); |
|
351 |
} |
|
352 |
|
|
353 |
|
|
354 |
Handle<Object> JSObject::GetPropertyWithCallback(Handle<JSObject> object, |
|
355 |
Handle<Object> receiver, |
|
356 |
Handle<Object> structure, |
|
357 |
Handle<Name> name) { |
|
334 | 358 |
Isolate* isolate = name->GetIsolate(); |
335 | 359 |
// To accommodate both the old and the new api we switch on the |
336 | 360 |
// data structure used to store the callbacks. Eventually foreign |
... | ... | |
338 | 362 |
if (structure->IsForeign()) { |
339 | 363 |
AccessorDescriptor* callback = |
340 | 364 |
reinterpret_cast<AccessorDescriptor*>( |
341 |
Foreign::cast(structure)->foreign_address());
|
|
342 |
MaybeObject* value = (callback->getter)(isolate, receiver, callback->data);
|
|
343 |
RETURN_IF_SCHEDULED_EXCEPTION(isolate);
|
|
344 |
return value;
|
|
365 |
Handle<Foreign>::cast(structure)->foreign_address());
|
|
366 |
CALL_HEAP_FUNCTION(isolate,
|
|
367 |
(callback->getter)(isolate, *receiver, callback->data),
|
|
368 |
Object);
|
|
345 | 369 |
} |
346 | 370 |
|
347 | 371 |
// api style callbacks. |
348 | 372 |
if (structure->IsAccessorInfo()) { |
349 |
if (!AccessorInfo::cast(structure)->IsCompatibleReceiver(receiver)) { |
|
350 |
Handle<Object> name_handle(name, isolate); |
|
351 |
Handle<Object> receiver_handle(receiver, isolate); |
|
352 |
Handle<Object> args[2] = { name_handle, receiver_handle }; |
|
373 |
Handle<AccessorInfo> accessor_info = Handle<AccessorInfo>::cast(structure); |
|
374 |
if (!accessor_info->IsCompatibleReceiver(*receiver)) { |
|
375 |
Handle<Object> args[2] = { name, receiver }; |
|
353 | 376 |
Handle<Object> error = |
354 | 377 |
isolate->factory()->NewTypeError("incompatible_method_receiver", |
355 | 378 |
HandleVector(args, |
356 | 379 |
ARRAY_SIZE(args))); |
357 |
return isolate->Throw(*error); |
|
380 |
isolate->Throw(*error); |
|
381 |
return Handle<Object>::null(); |
|
358 | 382 |
} |
359 | 383 |
// TODO(rossberg): Handling symbols in the API requires changing the API, |
360 | 384 |
// so we do not support it for now. |
361 |
if (name->IsSymbol()) return isolate->heap()->undefined_value();
|
|
385 |
if (name->IsSymbol()) return isolate->factory()->undefined_value();
|
|
362 | 386 |
if (structure->IsDeclaredAccessorInfo()) { |
363 |
return GetDeclaredAccessorProperty(receiver, |
|
364 |
DeclaredAccessorInfo::cast(structure), |
|
365 |
isolate); |
|
387 |
CALL_HEAP_FUNCTION( |
|
388 |
isolate, |
|
389 |
GetDeclaredAccessorProperty(*receiver, |
|
390 |
DeclaredAccessorInfo::cast(*structure), |
|
391 |
isolate), |
|
392 |
Object); |
|
366 | 393 |
} |
367 |
ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(structure); |
|
368 |
Object* fun_obj = data->getter(); |
|
394 |
|
|
395 |
Handle<ExecutableAccessorInfo> data = |
|
396 |
Handle<ExecutableAccessorInfo>::cast(structure); |
|
369 | 397 |
v8::AccessorGetterCallback call_fun = |
370 |
v8::ToCData<v8::AccessorGetterCallback>(fun_obj); |
|
371 |
if (call_fun == NULL) return isolate->heap()->undefined_value(); |
|
398 |
v8::ToCData<v8::AccessorGetterCallback>(data->getter()); |
|
399 |
if (call_fun == NULL) return isolate->factory()->undefined_value(); |
|
400 |
|
|
372 | 401 |
HandleScope scope(isolate); |
373 |
JSObject* self = JSObject::cast(receiver);
|
|
374 |
Handle<String> key(String::cast(name));
|
|
375 |
LOG(isolate, ApiNamedPropertyAccess("load", self, name));
|
|
376 |
PropertyCallbackArguments args(isolate, data->data(), self, this);
|
|
402 |
Handle<JSObject> self = Handle<JSObject>::cast(receiver);
|
|
403 |
Handle<String> key = Handle<String>::cast(name);
|
|
404 |
LOG(isolate, ApiNamedPropertyAccess("load", *self, *name));
|
|
405 |
PropertyCallbackArguments args(isolate, data->data(), *self, *object);
|
|
377 | 406 |
v8::Handle<v8::Value> result = |
378 | 407 |
args.Call(call_fun, v8::Utils::ToLocal(key)); |
379 |
RETURN_IF_SCHEDULED_EXCEPTION(isolate);
|
|
408 |
RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
|
380 | 409 |
if (result.IsEmpty()) { |
381 |
return isolate->heap()->undefined_value();
|
|
410 |
return isolate->factory()->undefined_value();
|
|
382 | 411 |
} |
383 |
Object* return_value = *v8::Utils::OpenHandle(*result);
|
|
412 |
Handle<Object> return_value = v8::Utils::OpenHandle(*result);
|
|
384 | 413 |
return_value->VerifyApiCallResultType(); |
385 |
return return_value;
|
|
414 |
return scope.CloseAndEscape(return_value);
|
|
386 | 415 |
} |
387 | 416 |
|
388 | 417 |
// __defineGetter__ callback |
389 |
if (structure->IsAccessorPair()) { |
|
390 |
Object* getter = AccessorPair::cast(structure)->getter(); |
|
391 |
if (getter->IsSpecFunction()) { |
|
392 |
// TODO(rossberg): nicer would be to cast to some JSCallable here... |
|
393 |
return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter)); |
|
394 |
} |
|
395 |
// Getter is not a function. |
|
396 |
return isolate->heap()->undefined_value(); |
|
418 |
Handle<Object> getter(Handle<AccessorPair>::cast(structure)->getter(), |
|
419 |
isolate); |
|
420 |
if (getter->IsSpecFunction()) { |
|
421 |
// TODO(rossberg): nicer would be to cast to some JSCallable here... |
|
422 |
CALL_HEAP_FUNCTION( |
|
423 |
isolate, |
|
424 |
object->GetPropertyWithDefinedGetter(*receiver, |
|
425 |
JSReceiver::cast(*getter)), |
|
426 |
Object); |
|
397 | 427 |
} |
398 |
|
|
399 |
UNREACHABLE(); |
|
400 |
return NULL; |
|
428 |
// Getter is not a function. |
|
429 |
return isolate->factory()->undefined_value(); |
|
401 | 430 |
} |
402 | 431 |
|
403 | 432 |
|
... | ... | |
455 | 484 |
StrictModeFlag strict_mode) { |
456 | 485 |
Isolate* isolate = proxy->GetIsolate(); |
457 | 486 |
Handle<String> name = isolate->factory()->Uint32ToString(index); |
458 |
CALL_HEAP_FUNCTION(isolate, |
|
459 |
proxy->SetPropertyWithHandler( |
|
460 |
*receiver, *name, *value, NONE, strict_mode), |
|
461 |
Object); |
|
487 |
return SetPropertyWithHandler( |
|
488 |
proxy, receiver, name, value, NONE, strict_mode); |
|
462 | 489 |
} |
463 | 490 |
|
464 | 491 |
|
465 |
bool JSProxy::HasElementWithHandler(uint32_t index) { |
|
466 |
String* name; |
|
467 |
MaybeObject* maybe = GetHeap()->Uint32ToString(index); |
|
468 |
if (!maybe->To<String>(&name)) return maybe; |
|
469 |
return HasPropertyWithHandler(name); |
|
492 |
bool JSProxy::HasElementWithHandler(Handle<JSProxy> proxy, uint32_t index) { |
|
493 |
Isolate* isolate = proxy->GetIsolate(); |
|
494 |
Handle<String> name = isolate->factory()->Uint32ToString(index); |
|
495 |
return HasPropertyWithHandler(proxy, name); |
|
470 | 496 |
} |
471 | 497 |
|
472 | 498 |
|
... | ... | |
496 | 522 |
|
497 | 523 |
|
498 | 524 |
// Only deal with CALLBACKS and INTERCEPTOR |
499 |
MaybeObject* JSObject::GetPropertyWithFailedAccessCheck( |
|
500 |
Object* receiver, |
|
525 |
Handle<Object> JSObject::GetPropertyWithFailedAccessCheck( |
|
526 |
Handle<JSObject> object, |
|
527 |
Handle<Object> receiver, |
|
501 | 528 |
LookupResult* result, |
502 |
Name* name,
|
|
529 |
Handle<Name> name,
|
|
503 | 530 |
PropertyAttributes* attributes) { |
531 |
Isolate* isolate = name->GetIsolate(); |
|
504 | 532 |
if (result->IsProperty()) { |
505 | 533 |
switch (result->type()) { |
506 | 534 |
case CALLBACKS: { |
507 | 535 |
// Only allow API accessors. |
508 |
Object* obj = result->GetCallbackObject(); |
|
509 |
if (obj->IsAccessorInfo()) { |
|
510 |
AccessorInfo* info = AccessorInfo::cast(obj); |
|
511 |
if (info->all_can_read()) { |
|
512 |
*attributes = result->GetAttributes(); |
|
513 |
return result->holder()->GetPropertyWithCallback( |
|
514 |
receiver, result->GetCallbackObject(), name); |
|
515 |
} |
|
516 |
} else if (obj->IsAccessorPair()) { |
|
517 |
AccessorPair* pair = AccessorPair::cast(obj); |
|
518 |
if (pair->all_can_read()) { |
|
519 |
return result->holder()->GetPropertyWithCallback( |
|
520 |
receiver, result->GetCallbackObject(), name); |
|
521 |
} |
|
536 |
Handle<Object> callback_obj(result->GetCallbackObject(), isolate); |
|
537 |
if (callback_obj->IsAccessorInfo()) { |
|
538 |
if (!AccessorInfo::cast(*callback_obj)->all_can_read()) break; |
|
539 |
*attributes = result->GetAttributes(); |
|
540 |
// Fall through to GetPropertyWithCallback. |
|
541 |
} else if (callback_obj->IsAccessorPair()) { |
|
542 |
if (!AccessorPair::cast(*callback_obj)->all_can_read()) break; |
|
543 |
// Fall through to GetPropertyWithCallback. |
|
544 |
} else { |
|
545 |
break; |
|
522 | 546 |
} |
523 |
break; |
|
547 |
Handle<JSObject> holder(result->holder(), isolate); |
|
548 |
return GetPropertyWithCallback(holder, receiver, callback_obj, name); |
|
524 | 549 |
} |
525 | 550 |
case NORMAL: |
526 | 551 |
case FIELD: |
527 | 552 |
case CONSTANT: { |
528 | 553 |
// Search ALL_CAN_READ accessors in prototype chain. |
529 |
LookupResult r(GetIsolate());
|
|
530 |
result->holder()->LookupRealNamedPropertyInPrototypes(name, &r); |
|
554 |
LookupResult r(isolate);
|
|
555 |
result->holder()->LookupRealNamedPropertyInPrototypes(*name, &r);
|
|
531 | 556 |
if (r.IsProperty()) { |
532 |
return GetPropertyWithFailedAccessCheck(receiver, |
|
533 |
&r, |
|
534 |
name, |
|
535 |
attributes); |
|
557 |
return GetPropertyWithFailedAccessCheck( |
|
558 |
object, receiver, &r, name, attributes); |
|
536 | 559 |
} |
537 | 560 |
break; |
538 | 561 |
} |
539 | 562 |
case INTERCEPTOR: { |
540 | 563 |
// If the object has an interceptor, try real named properties. |
541 | 564 |
// No access check in GetPropertyAttributeWithInterceptor. |
542 |
LookupResult r(GetIsolate());
|
|
543 |
result->holder()->LookupRealNamedProperty(name, &r); |
|
565 |
LookupResult r(isolate);
|
|
566 |
result->holder()->LookupRealNamedProperty(*name, &r);
|
|
544 | 567 |
if (r.IsProperty()) { |
545 |
return GetPropertyWithFailedAccessCheck(receiver, |
|
546 |
&r, |
|
547 |
name, |
|
548 |
attributes); |
|
568 |
return GetPropertyWithFailedAccessCheck( |
|
569 |
object, receiver, &r, name, attributes); |
|
549 | 570 |
} |
550 | 571 |
break; |
551 | 572 |
} |
... | ... | |
556 | 577 |
|
557 | 578 |
// No accessible property found. |
558 | 579 |
*attributes = ABSENT; |
559 |
Heap* heap = name->GetHeap(); |
|
560 |
Isolate* isolate = heap->isolate(); |
|
561 |
isolate->ReportFailedAccessCheck(this, v8::ACCESS_GET); |
|
562 |
RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
|
563 |
return heap->undefined_value(); |
|
580 |
isolate->ReportFailedAccessCheck(*object, v8::ACCESS_GET); |
|
581 |
RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
|
582 |
return isolate->factory()->undefined_value(); |
|
564 | 583 |
} |
565 | 584 |
|
566 | 585 |
|
... | ... | |
643 | 662 |
} |
644 | 663 |
|
645 | 664 |
|
646 |
Handle<Object> JSObject::SetNormalizedProperty(Handle<JSObject> object, |
|
647 |
LookupResult* result, |
|
648 |
Handle<Object> value) { |
|
649 |
CALL_HEAP_FUNCTION(object->GetIsolate(), |
|
650 |
object->SetNormalizedProperty(result, *value), |
|
651 |
Object); |
|
652 |
} |
|
653 |
|
|
654 |
|
|
655 |
MaybeObject* JSObject::SetNormalizedProperty(LookupResult* result, |
|
656 |
Object* value) { |
|
657 |
ASSERT(!HasFastProperties()); |
|
658 |
if (IsGlobalObject()) { |
|
659 |
PropertyCell* cell = PropertyCell::cast( |
|
660 |
property_dictionary()->ValueAt(result->GetDictionaryEntry())); |
|
661 |
MaybeObject* maybe_type = cell->SetValueInferType(value); |
|
662 |
if (maybe_type->IsFailure()) return maybe_type; |
|
665 |
void JSObject::SetNormalizedProperty(Handle<JSObject> object, |
|
666 |
LookupResult* result, |
|
667 |
Handle<Object> value) { |
|
668 |
ASSERT(!object->HasFastProperties()); |
|
669 |
NameDictionary* property_dictionary = object->property_dictionary(); |
|
670 |
if (object->IsGlobalObject()) { |
|
671 |
Handle<PropertyCell> cell(PropertyCell::cast( |
|
672 |
property_dictionary->ValueAt(result->GetDictionaryEntry()))); |
|
673 |
PropertyCell::SetValueInferType(cell, value); |
|
663 | 674 |
} else { |
664 |
property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value);
|
|
675 |
property_dictionary->ValueAtPut(result->GetDictionaryEntry(), *value);
|
|
665 | 676 |
} |
666 |
return value; |
|
667 | 677 |
} |
668 | 678 |
|
669 | 679 |
|
670 |
Handle<Object> JSObject::SetNormalizedProperty(Handle<JSObject> object, |
|
671 |
Handle<Name> key, |
|
672 |
Handle<Object> value, |
|
673 |
PropertyDetails details) { |
|
674 |
CALL_HEAP_FUNCTION(object->GetIsolate(), |
|
675 |
object->SetNormalizedProperty(*key, *value, details), |
|
676 |
Object); |
|
680 |
// TODO(mstarzinger): Temporary wrapper until handlified. |
|
681 |
static Handle<NameDictionary> NameDictionaryAdd(Handle<NameDictionary> dict, |
|
682 |
Handle<Name> name, |
|
683 |
Handle<Object> value, |
|
684 |
PropertyDetails details) { |
|
685 |
CALL_HEAP_FUNCTION(dict->GetIsolate(), |
|
686 |
dict->Add(*name, *value, details), |
|
687 |
NameDictionary); |
|
677 | 688 |
} |
678 | 689 |
|
679 | 690 |
|
680 |
MaybeObject* JSObject::SetNormalizedProperty(Name* name, |
|
681 |
Object* value, |
|
682 |
PropertyDetails details) { |
|
683 |
ASSERT(!HasFastProperties()); |
|
684 |
int entry = property_dictionary()->FindEntry(name); |
|
691 |
void JSObject::SetNormalizedProperty(Handle<JSObject> object, |
|
692 |
Handle<Name> name, |
|
693 |
Handle<Object> value, |
|
694 |
PropertyDetails details) { |
|
695 |
ASSERT(!object->HasFastProperties()); |
|
696 |
Handle<NameDictionary> property_dictionary(object->property_dictionary()); |
|
697 |
|
|
698 |
if (!name->IsUniqueName()) { |
|
699 |
name = object->GetIsolate()->factory()->InternalizedStringFromString( |
|
700 |
Handle<String>::cast(name)); |
|
701 |
} |
|
702 |
|
|
703 |
int entry = property_dictionary->FindEntry(*name); |
|
685 | 704 |
if (entry == NameDictionary::kNotFound) { |
686 |
Object* store_value = value; |
|
687 |
if (IsGlobalObject()) { |
|
688 |
Heap* heap = name->GetHeap(); |
|
689 |
MaybeObject* maybe_store_value = heap->AllocatePropertyCell(value); |
|
690 |
if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; |
|
691 |
} |
|
692 |
Object* dict; |
|
693 |
{ MaybeObject* maybe_dict = |
|
694 |
property_dictionary()->Add(name, store_value, details); |
|
695 |
if (!maybe_dict->ToObject(&dict)) return maybe_dict; |
|
705 |
Handle<Object> store_value = value; |
|
706 |
if (object->IsGlobalObject()) { |
|
707 |
store_value = object->GetIsolate()->factory()->NewPropertyCell(value); |
|
696 | 708 |
} |
697 |
set_properties(NameDictionary::cast(dict)); |
|
698 |
return value; |
|
709 |
|
|
710 |
property_dictionary = |
|
711 |
NameDictionaryAdd(property_dictionary, name, store_value, details); |
|
712 |
object->set_properties(*property_dictionary); |
|
713 |
return; |
|
699 | 714 |
} |
700 | 715 |
|
701 |
PropertyDetails original_details = property_dictionary()->DetailsAt(entry);
|
|
716 |
PropertyDetails original_details = property_dictionary->DetailsAt(entry); |
|
702 | 717 |
int enumeration_index; |
703 | 718 |
// Preserve the enumeration index unless the property was deleted. |
704 | 719 |
if (original_details.IsDeleted()) { |
705 |
enumeration_index = property_dictionary()->NextEnumerationIndex();
|
|
706 |
property_dictionary()->SetNextEnumerationIndex(enumeration_index + 1);
|
|
720 |
enumeration_index = property_dictionary->NextEnumerationIndex(); |
|
721 |
property_dictionary->SetNextEnumerationIndex(enumeration_index + 1); |
|
707 | 722 |
} else { |
708 | 723 |
enumeration_index = original_details.dictionary_index(); |
709 | 724 |
ASSERT(enumeration_index > 0); |
... | ... | |
712 | 727 |
details = PropertyDetails( |
713 | 728 |
details.attributes(), details.type(), enumeration_index); |
714 | 729 |
|
715 |
if (IsGlobalObject()) { |
|
716 |
PropertyCell* cell = |
|
717 |
PropertyCell::cast(property_dictionary()->ValueAt(entry)); |
|
718 |
MaybeObject* maybe_type = cell->SetValueInferType(value); |
|
719 |
if (maybe_type->IsFailure()) return maybe_type; |
|
730 |
if (object->IsGlobalObject()) { |
|
731 |
Handle<PropertyCell> cell( |
|
732 |
PropertyCell::cast(property_dictionary->ValueAt(entry))); |
|
733 |
PropertyCell::SetValueInferType(cell, value); |
|
720 | 734 |
// Please note we have to update the property details. |
721 |
property_dictionary()->DetailsAtPut(entry, details);
|
|
735 |
property_dictionary->DetailsAtPut(entry, details); |
|
722 | 736 |
} else { |
723 |
property_dictionary()->SetEntry(entry, name, value, details);
|
|
737 |
property_dictionary->SetEntry(entry, *name, *value, details);
|
|
724 | 738 |
} |
725 |
return value; |
|
726 | 739 |
} |
727 | 740 |
|
728 | 741 |
|
... | ... | |
733 | 746 |
} |
734 | 747 |
|
735 | 748 |
|
736 |
static void CellSetValueInferType(Handle<PropertyCell> cell, |
|
737 |
Handle<Object> value) { |
|
738 |
CALL_HEAP_FUNCTION_VOID(cell->GetIsolate(), cell->SetValueInferType(*value)); |
|
739 |
} |
|
740 |
|
|
741 |
|
|
742 | 749 |
Handle<Object> JSObject::DeleteNormalizedProperty(Handle<JSObject> object, |
743 | 750 |
Handle<Name> name, |
744 | 751 |
DeleteMode mode) { |
... | ... | |
761 | 768 |
object->set_map(*new_map); |
762 | 769 |
} |
763 | 770 |
Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); |
764 |
CellSetValueInferType(cell, isolate->factory()->the_hole_value()); |
|
771 |
Handle<Object> value = isolate->factory()->the_hole_value(); |
|
772 |
PropertyCell::SetValueInferType(cell, value); |
|
765 | 773 |
dictionary->DetailsAtPut(entry, details.AsDeleted()); |
766 | 774 |
} else { |
767 | 775 |
Handle<Object> deleted(dictionary->DeleteProperty(entry, mode), isolate); |
... | ... | |
817 | 825 |
} |
818 | 826 |
|
819 | 827 |
|
828 |
// TODO(yangguo): handlify this and get rid of. |
|
820 | 829 |
MaybeObject* Object::GetProperty(Object* receiver, |
821 | 830 |
LookupResult* result, |
822 | 831 |
Name* name, |
823 | 832 |
PropertyAttributes* attributes) { |
824 |
// Make sure that the top context does not change when doing |
|
825 |
// callbacks or interceptor calls. |
|
826 |
AssertNoContextChangeWithHandleScope ncc; |
|
827 |
|
|
828 | 833 |
Isolate* isolate = name->GetIsolate(); |
829 | 834 |
Heap* heap = isolate->heap(); |
830 | 835 |
|
836 |
#ifdef DEBUG |
|
837 |
// TODO(mstarzinger): Only because of the AssertNoContextChange, drop as soon |
|
838 |
// as this method has been fully handlified. |
|
839 |
HandleScope scope(isolate); |
|
840 |
#endif |
|
841 |
|
|
842 |
// Make sure that the top context does not change when doing |
|
843 |
// callbacks or interceptor calls. |
|
844 |
AssertNoContextChange ncc(isolate); |
|
845 |
|
|
831 | 846 |
// Traverse the prototype chain from the current object (this) to |
832 | 847 |
// the holder and check for access rights. This avoids traversing the |
833 | 848 |
// objects more than once in case of interceptors, because the |
... | ... | |
849 | 864 |
// property from the current object, we still check that we have |
850 | 865 |
// access to it. |
851 | 866 |
JSObject* checked = JSObject::cast(current); |
852 |
if (!heap->isolate()->MayNamedAccess(checked, name, v8::ACCESS_GET)) { |
|
853 |
return checked->GetPropertyWithFailedAccessCheck(receiver, |
|
854 |
result, |
|
855 |
name, |
|
856 |
attributes); |
|
867 |
if (!isolate->MayNamedAccess(checked, name, v8::ACCESS_GET)) { |
|
868 |
HandleScope scope(isolate); |
|
869 |
Handle<Object> value = JSObject::GetPropertyWithFailedAccessCheck( |
|
870 |
handle(checked, isolate), |
|
871 |
handle(receiver, isolate), |
|
872 |
result, |
|
873 |
handle(name, isolate), |
|
874 |
attributes); |
|
875 |
RETURN_IF_EMPTY_HANDLE(isolate, value); |
|
876 |
return *value; |
|
857 | 877 |
} |
858 | 878 |
} |
859 | 879 |
// Stop traversing the chain once we reach the last object in the |
... | ... | |
884 | 904 |
} |
885 | 905 |
case CONSTANT: |
886 | 906 |
return result->GetConstant(); |
887 |
case CALLBACKS: |
|
888 |
return result->holder()->GetPropertyWithCallback( |
|
889 |
receiver, result->GetCallbackObject(), name); |
|
907 |
case CALLBACKS: { |
|
908 |
HandleScope scope(isolate); |
|
909 |
Handle<Object> value = JSObject::GetPropertyWithCallback( |
|
910 |
handle(result->holder(), isolate), |
|
911 |
handle(receiver, isolate), |
|
912 |
handle(result->GetCallbackObject(), isolate), |
|
913 |
handle(name, isolate)); |
|
914 |
RETURN_IF_EMPTY_HANDLE(isolate, value); |
|
915 |
return *value; |
|
916 |
} |
|
890 | 917 |
case HANDLER: |
891 | 918 |
return result->proxy()->GetPropertyWithHandler(receiver, name); |
892 |
case INTERCEPTOR: |
|
893 |
return result->holder()->GetPropertyWithInterceptor( |
|
894 |
receiver, name, attributes); |
|
919 |
case INTERCEPTOR: { |
|
920 |
HandleScope scope(isolate); |
|
921 |
Handle<Object> value = JSObject::GetPropertyWithInterceptor( |
|
922 |
handle(result->holder(), isolate), |
|
923 |
handle(receiver, isolate), |
|
924 |
handle(name, isolate), |
|
925 |
attributes); |
|
926 |
RETURN_IF_EMPTY_HANDLE(isolate, value); |
|
927 |
return *value; |
|
928 |
} |
|
895 | 929 |
case TRANSITION: |
896 | 930 |
case NONEXISTENT: |
897 | 931 |
UNREACHABLE(); |
... | ... | |
1026 | 1060 |
if (IsNumber() && other->IsNumber()) { |
1027 | 1061 |
double this_value = Number(); |
1028 | 1062 |
double other_value = other->Number(); |
1029 |
return (this_value == other_value) || |
|
1030 |
(std::isnan(this_value) && std::isnan(other_value)); |
|
1063 |
bool equal = this_value == other_value; |
|
1064 |
// SameValue(NaN, NaN) is true. |
|
1065 |
if (!equal) return std::isnan(this_value) && std::isnan(other_value); |
|
1066 |
// SameValue(0.0, -0.0) is false. |
|
1067 |
return (this_value != 0) || ((1 / this_value) == (1 / other_value)); |
|
1031 | 1068 |
} |
1032 | 1069 |
if (IsString() && other->IsString()) { |
1033 | 1070 |
return String::cast(this)->Equals(String::cast(other)); |
... | ... | |
1167 | 1204 |
// Externalizing twice leaks the external resource, so it's |
1168 | 1205 |
// prohibited by the API. |
1169 | 1206 |
ASSERT(!this->IsExternalString()); |
1170 |
#ifdef DEBUG
|
|
1207 |
#ifdef ENABLE_SLOW_ASSERTS
|
|
1171 | 1208 |
if (FLAG_enable_slow_asserts) { |
1172 | 1209 |
// Assert that the resource and the string are equivalent. |
1173 | 1210 |
ASSERT(static_cast<size_t>(this->length()) == resource->length()); |
... | ... | |
1224 | 1261 |
|
1225 | 1262 |
|
1226 | 1263 |
bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) { |
1227 |
#ifdef DEBUG
|
|
1264 |
#ifdef ENABLE_SLOW_ASSERTS
|
|
1228 | 1265 |
if (FLAG_enable_slow_asserts) { |
1229 | 1266 |
// Assert that the resource and the string are equivalent. |
1230 | 1267 |
ASSERT(static_cast<size_t>(this->length()) == resource->length()); |
... | ... | |
1709 | 1746 |
case FIXED_ARRAY_TYPE: |
1710 | 1747 |
FixedArray::BodyDescriptor::IterateBody(this, object_size, v); |
1711 | 1748 |
break; |
1749 |
case CONSTANT_POOL_ARRAY_TYPE: |
|
1750 |
reinterpret_cast<ConstantPoolArray*>(this)->ConstantPoolIterateBody(v); |
|
1751 |
break; |
|
1712 | 1752 |
case FIXED_DOUBLE_ARRAY_TYPE: |
1713 | 1753 |
break; |
1714 | 1754 |
case JS_OBJECT_TYPE: |
... | ... | |
1871 | 1911 |
} |
1872 | 1912 |
|
1873 | 1913 |
|
1874 |
MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, |
|
1875 |
Name* name, |
|
1876 |
Object* value, |
|
1877 |
int field_index, |
|
1878 |
Representation representation) { |
|
1914 |
// TODO(mstarzinger): Temporary wrapper until handlified. |
|
1915 |
static Handle<Object> NewStorageFor(Isolate* isolate, |
|
1916 |
Handle<Object> object, |
|
1917 |
Representation representation) { |
|
1918 |
Heap* heap = isolate->heap(); |
|
1919 |
CALL_HEAP_FUNCTION(isolate, |
|
1920 |
object->AllocateNewStorageFor(heap, representation), |
|
1921 |
Object); |
|
1922 |
} |
|
1923 |
|
|
1924 |
|
|
1925 |
void JSObject::AddFastPropertyUsingMap(Handle<JSObject> object, |
|
1926 |
Handle<Map> new_map, |
|
1927 |
Handle<Name> name, |
|
1928 |
Handle<Object> value, |
|
1929 |
int field_index, |
|
1930 |
Representation representation) { |
|
1931 |
Isolate* isolate = object->GetIsolate(); |
|
1932 |
|
|
1879 | 1933 |
// This method is used to transition to a field. If we are transitioning to a |
1880 | 1934 |
// double field, allocate new storage. |
1881 |
Object* storage; |
|
1882 |
MaybeObject* maybe_storage = |
|
1883 |
value->AllocateNewStorageFor(GetHeap(), representation); |
|
1884 |
if (!maybe_storage->To(&storage)) return maybe_storage; |
|
1935 |
Handle<Object> storage = NewStorageFor(isolate, value, representation); |
|
1885 | 1936 |
|
1886 |
if (map()->unused_property_fields() == 0) { |
|
1937 |
if (object->map()->unused_property_fields() == 0) {
|
|
1887 | 1938 |
int new_unused = new_map->unused_property_fields(); |
1888 |
FixedArray* values; |
|
1889 |
MaybeObject* maybe_values = |
|
1890 |
properties()->CopySize(properties()->length() + new_unused + 1); |
|
1891 |
if (!maybe_values->To(&values)) return maybe_values; |
|
1939 |
Handle<FixedArray> properties(object->properties()); |
|
1940 |
Handle<FixedArray> values = isolate->factory()->CopySizeFixedArray( |
|
1941 |
properties, properties->length() + new_unused + 1); |
|
1942 |
object->set_properties(*values); |
|
1943 |
} |
|
1944 |
|
|
1945 |
object->set_map(*new_map); |
|
1946 |
object->FastPropertyAtPut(field_index, *storage); |
|
1947 |
} |
|
1892 | 1948 |
|
1893 |
set_properties(values); |
|
1949 |
|
|
1950 |
static MaybeObject* CopyAddFieldDescriptor(Map* map, |
|
1951 |
Name* name, |
|
1952 |
int index, |
|
1953 |
PropertyAttributes attributes, |
|
1954 |
Representation representation, |
|
1955 |
TransitionFlag flag) { |
|
1956 |
Map* new_map; |
|
1957 |
FieldDescriptor new_field_desc(name, index, attributes, representation); |
|
1958 |
MaybeObject* maybe_map = map->CopyAddDescriptor(&new_field_desc, flag); |
|
1959 |
if (!maybe_map->To(&new_map)) return maybe_map; |
|
1960 |
int unused_property_fields = map->unused_property_fields() - 1; |
|
1961 |
if (unused_property_fields < 0) { |
|
1962 |
unused_property_fields += JSObject::kFieldsAdded; |
|
1894 | 1963 |
} |
1964 |
new_map->set_unused_property_fields(unused_property_fields); |
|
1965 |
return new_map; |
|
1966 |
} |
|
1895 | 1967 |
|
1896 |
set_map(new_map); |
|
1897 | 1968 |
|
1898 |
FastPropertyAtPut(field_index, storage); |
|
1899 |
return value; |
|
1969 |
static Handle<Map> CopyAddFieldDescriptor(Handle<Map> map, |
|
1970 |
Handle<Name> name, |
|
1971 |
int index, |
|
1972 |
PropertyAttributes attributes, |
|
1973 |
Representation representation, |
|
1974 |
TransitionFlag flag) { |
|
1975 |
CALL_HEAP_FUNCTION(map->GetIsolate(), |
|
1976 |
CopyAddFieldDescriptor( |
|
1977 |
*map, *name, index, attributes, representation, flag), |
|
1978 |
Map); |
|
1900 | 1979 |
} |
1901 | 1980 |
|
1902 | 1981 |
|
1903 |
MaybeObject* JSObject::AddFastProperty(Name* name, |
|
1904 |
Object* value, |
|
1905 |
PropertyAttributes attributes, |
|
1906 |
StoreFromKeyed store_mode, |
|
1907 |
ValueType value_type, |
|
1908 |
TransitionFlag flag) { |
|
1909 |
ASSERT(!IsJSGlobalProxy()); |
|
1982 |
void JSObject::AddFastProperty(Handle<JSObject> object, |
|
1983 |
Handle<Name> name, |
|
1984 |
Handle<Object> value, |
|
1985 |
PropertyAttributes attributes, |
|
1986 |
StoreFromKeyed store_mode, |
|
1987 |
ValueType value_type, |
|
1988 |
TransitionFlag flag) { |
|
1989 |
ASSERT(!object->IsJSGlobalProxy()); |
|
1910 | 1990 |
ASSERT(DescriptorArray::kNotFound == |
1911 |
map()->instance_descriptors()->Search( |
|
1912 |
name, map()->NumberOfOwnDescriptors()));
|
|
1991 |
object->map()->instance_descriptors()->Search(
|
|
1992 |
*name, object->map()->NumberOfOwnDescriptors()));
|
|
1913 | 1993 |
|
1914 | 1994 |
// Normalize the object if the name is an actual name (not the |
1915 | 1995 |
// hidden strings) and is not a real identifier. |
1916 | 1996 |
// Normalize the object if it will have too many fast properties. |
1917 |
Isolate* isolate = GetHeap()->isolate();
|
|
1918 |
if (!name->IsCacheable(isolate) || TooManyFastProperties(store_mode)) {
|
|
1919 |
MaybeObject* maybe_failure =
|
|
1920 |
NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
|
|
1921 |
if (maybe_failure->IsFailure()) return maybe_failure;
|
|
1922 |
return AddSlowProperty(name, value, attributes);
|
|
1997 |
Isolate* isolate = object->GetIsolate();
|
|
1998 |
if (!name->IsCacheable(isolate) || |
|
1999 |
object->TooManyFastProperties(store_mode)) {
|
|
2000 |
NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
|
|
2001 |
AddSlowProperty(object, name, value, attributes);
|
|
2002 |
return; |
|
1923 | 2003 |
} |
1924 | 2004 |
|
1925 | 2005 |
// Compute the new index for new field. |
1926 |
int index = map()->NextFreePropertyIndex(); |
|
2006 |
int index = object->map()->NextFreePropertyIndex();
|
|
1927 | 2007 |
|
1928 | 2008 |
// Allocate new instance descriptors with (name, index) added |
1929 |
if (IsJSContextExtensionObject()) value_type = FORCE_TAGGED; |
|
2009 |
if (object->IsJSContextExtensionObject()) value_type = FORCE_TAGGED;
|
|
1930 | 2010 |
Representation representation = value->OptimalRepresentation(value_type); |
2011 |
Handle<Map> new_map = CopyAddFieldDescriptor( |
|
2012 |
handle(object->map()), name, index, attributes, representation, flag); |
|
1931 | 2013 |
|
1932 |
FieldDescriptor new_field(name, index, attributes, representation); |
|
1933 |
|
|
1934 |
Map* new_map; |
|
1935 |
MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&new_field, flag); |
|
1936 |
if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
|
2014 |
AddFastPropertyUsingMap(object, new_map, name, value, index, representation); |
|
2015 |
} |
|
1937 | 2016 |
|
1938 |
int unused_property_fields = map()->unused_property_fields() - 1; |
|
1939 |
if (unused_property_fields < 0) { |
|
1940 |
unused_property_fields += kFieldsAdded; |
|
1941 |
} |
|
1942 |
new_map->set_unused_property_fields(unused_property_fields); |
|
1943 | 2017 |
|
1944 |
return AddFastPropertyUsingMap(new_map, name, value, index, representation); |
|
2018 |
static MaybeObject* CopyAddConstantDescriptor(Map* map, |
|
2019 |
Name* name, |
|
2020 |
Object* value, |
|
2021 |
PropertyAttributes attributes, |
|
2022 |
TransitionFlag flag) { |
|
2023 |
ConstantDescriptor new_constant_desc(name, value, attributes); |
|
2024 |
return map->CopyAddDescriptor(&new_constant_desc, flag); |
|
1945 | 2025 |
} |
1946 | 2026 |
|
1947 | 2027 |
|
1948 |
MaybeObject* JSObject::AddConstantProperty( |
|
1949 |
Name* name, |
|
1950 |
Object* constant, |
|
1951 |
PropertyAttributes attributes, |
|
1952 |
TransitionFlag initial_flag) { |
|
1953 |
// Allocate new instance descriptors with (name, constant) added |
|
1954 |
ConstantDescriptor d(name, constant, attributes); |
|
2028 |
static Handle<Map> CopyAddConstantDescriptor(Handle<Map> map, |
|
2029 |
Handle<Name> name, |
|
2030 |
Handle<Object> value, |
|
2031 |
PropertyAttributes attributes, |
|
2032 |
TransitionFlag flag) { |
|
2033 |
CALL_HEAP_FUNCTION(map->GetIsolate(), |
|
2034 |
CopyAddConstantDescriptor( |
|
2035 |
*map, *name, *value, attributes, flag), |
|
2036 |
Map); |
|
2037 |
} |
|
1955 | 2038 |
|
2039 |
|
|
2040 |
void JSObject::AddConstantProperty(Handle<JSObject> object, |
|
2041 |
Handle<Name> name, |
|
2042 |
Handle<Object> constant, |
|
2043 |
PropertyAttributes attributes, |
|
2044 |
TransitionFlag initial_flag) { |
|
1956 | 2045 |
TransitionFlag flag = |
1957 | 2046 |
// Do not add transitions to global objects. |
1958 |
(IsGlobalObject() || |
|
2047 |
(object->IsGlobalObject() ||
|
|
1959 | 2048 |
// Don't add transitions to special properties with non-trivial |
1960 | 2049 |
// attributes. |
1961 | 2050 |
attributes != NONE) |
1962 | 2051 |
? OMIT_TRANSITION |
1963 | 2052 |
: initial_flag; |
1964 | 2053 |
|
1965 |
Map* new_map;
|
|
1966 |
MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&d, flag);
|
|
1967 |
if (!maybe_new_map->To(&new_map)) return maybe_new_map;
|
|
2054 |
// Allocate new instance descriptors with (name, constant) added.
|
|
2055 |
Handle<Map> new_map = CopyAddConstantDescriptor(
|
|
2056 |
handle(object->map()), name, constant, attributes, flag);
|
|
1968 | 2057 |
|
1969 |
set_map(new_map); |
|
1970 |
return constant; |
|
2058 |
object->set_map(*new_map); |
|
1971 | 2059 |
} |
1972 | 2060 |
|
1973 | 2061 |
|
1974 |
// Add property in slow mode
|
|
1975 |
MaybeObject* JSObject::AddSlowProperty(Name* name,
|
|
1976 |
Object* value,
|
|
1977 |
PropertyAttributes attributes) {
|
|
1978 |
ASSERT(!HasFastProperties()); |
|
1979 |
NameDictionary* dict = property_dictionary();
|
|
1980 |
Object* store_value = value;
|
|
1981 |
if (IsGlobalObject()) { |
|
2062 |
void JSObject::AddSlowProperty(Handle<JSObject> object,
|
|
2063 |
Handle<Name> name,
|
|
2064 |
Handle<Object> value,
|
|
2065 |
PropertyAttributes attributes) { |
|
2066 |
ASSERT(!object->HasFastProperties());
|
|
2067 |
Isolate* isolate = object->GetIsolate();
|
|
2068 |
Handle<NameDictionary> dict(object->property_dictionary());
|
|
2069 |
if (object->IsGlobalObject()) {
|
|
1982 | 2070 |
// In case name is an orphaned property reuse the cell. |
1983 |
int entry = dict->FindEntry(name); |
|
2071 |
int entry = dict->FindEntry(*name);
|
|
1984 | 2072 |
if (entry != NameDictionary::kNotFound) { |
1985 |
store_value = dict->ValueAt(entry); |
|
1986 |
MaybeObject* maybe_type = |
|
1987 |
PropertyCell::cast(store_value)->SetValueInferType(value); |
|
1988 |
if (maybe_type->IsFailure()) return maybe_type; |
|
2073 |
Handle<PropertyCell> cell(PropertyCell::cast(dict->ValueAt(entry))); |
|
2074 |
PropertyCell::SetValueInferType(cell, value); |
|
1989 | 2075 |
// Assign an enumeration index to the property and update |
1990 | 2076 |
// SetNextEnumerationIndex. |
1991 | 2077 |
int index = dict->NextEnumerationIndex(); |
1992 | 2078 |
PropertyDetails details = PropertyDetails(attributes, NORMAL, index); |
1993 | 2079 |
dict->SetNextEnumerationIndex(index + 1); |
1994 |
dict->SetEntry(entry, name, store_value, details); |
|
1995 |
return value; |
|
1996 |
} |
|
1997 |
Heap* heap = GetHeap(); |
|
1998 |
{ MaybeObject* maybe_store_value = |
|
1999 |
heap->AllocatePropertyCell(value); |
|
2000 |
if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; |
|
2080 |
dict->SetEntry(entry, *name, *cell, details); |
|
2081 |
return; |
|
2001 | 2082 |
} |
2002 |
MaybeObject* maybe_type =
|
|
2003 |
PropertyCell::cast(store_value)->SetValueInferType(value);
|
|
2004 |
if (maybe_type->IsFailure()) return maybe_type;
|
|
2083 |
Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell(value);
|
|
2084 |
PropertyCell::SetValueInferType(cell, value);
|
|
2085 |
value = cell;
|
|
2005 | 2086 |
} |
2006 | 2087 |
PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); |
2007 |
Object* result; |
|
2008 |
{ MaybeObject* maybe_result = dict->Add(name, store_value, details); |
|
2009 |
if (!maybe_result->ToObject(&result)) return maybe_result; |
|
2010 |
} |
|
2011 |
if (dict != result) set_properties(NameDictionary::cast(result)); |
|
2012 |
return value; |
|
2088 |
Handle<NameDictionary> result = NameDictionaryAdd(dict, name, value, details); |
|
2089 |
if (*dict != *result) object->set_properties(*result); |
|
2013 | 2090 |
} |
2014 | 2091 |
|
2015 | 2092 |
|
2016 |
MaybeObject* JSObject::AddProperty(Name* name, |
|
2017 |
Object* value, |
|
2018 |
PropertyAttributes attributes, |
|
2019 |
StrictModeFlag strict_mode, |
|
2020 |
JSReceiver::StoreFromKeyed store_mode, |
|
2021 |
ExtensibilityCheck extensibility_check, |
|
2022 |
ValueType value_type, |
|
2023 |
StoreMode mode, |
|
2024 |
TransitionFlag transition_flag) { |
|
2025 |
ASSERT(!IsJSGlobalProxy()); |
|
2026 |
Map* map_of_this = map(); |
|
2027 |
Heap* heap = GetHeap(); |
|
2028 |
Isolate* isolate = heap->isolate(); |
|
2029 |
MaybeObject* result; |
|
2093 |
Handle<Object> JSObject::AddProperty(Handle<JSObject> object, |
|
2094 |
Handle<Name> name, |
|
2095 |
Handle<Object> value, |
|
2096 |
PropertyAttributes attributes, |
|
2097 |
StrictModeFlag strict_mode, |
|
2098 |
JSReceiver::StoreFromKeyed store_mode, |
|
2099 |
ExtensibilityCheck extensibility_check, |
|
2100 |
ValueType value_type, |
|
2101 |
StoreMode mode, |
|
2102 |
TransitionFlag transition_flag) { |
|
2103 |
ASSERT(!object->IsJSGlobalProxy()); |
|
2104 |
Isolate* isolate = object->GetIsolate(); |
|
2105 |
|
|
2106 |
if (!name->IsUniqueName()) { |
|
2107 |
name = isolate->factory()->InternalizedStringFromString( |
|
2108 |
Handle<String>::cast(name)); |
|
2109 |
} |
|
2110 |
|
|
2030 | 2111 |
if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK && |
2031 |
!map_of_this->is_extensible()) {
|
|
2112 |
!object->map()->is_extensible()) {
|
|
2032 | 2113 |
if (strict_mode == kNonStrictMode) { |
2033 | 2114 |
return value; |
2034 | 2115 |
} else { |
2035 |
Handle<Object> args[1] = {Handle<Name>(name)}; |
|
2036 |
return isolate->Throw( |
|
2037 |
*isolate->factory()->NewTypeError("object_not_extensible", |
|
2038 |
HandleVector(args, 1))); |
|
2116 |
Handle<Object> args[1] = { name }; |
|
2117 |
Handle<Object> error = isolate->factory()->NewTypeError( |
|
2118 |
"object_not_extensible", HandleVector(args, ARRAY_SIZE(args))); |
|
2119 |
isolate->Throw(*error); |
|
2120 |
return Handle<Object>(); |
|
2039 | 2121 |
} |
2040 | 2122 |
} |
2041 | 2123 |
|
2042 |
if (HasFastProperties()) { |
|
2124 |
if (object->HasFastProperties()) {
|
|
2043 | 2125 |
// Ensure the descriptor array does not get too big. |
2044 |
if (map_of_this->NumberOfOwnDescriptors() <
|
|
2126 |
if (object->map()->NumberOfOwnDescriptors() <
|
|
2045 | 2127 |
DescriptorArray::kMaxNumberOfDescriptors) { |
2046 | 2128 |
// TODO(verwaest): Support other constants. |
2047 | 2129 |
// if (mode == ALLOW_AS_CONSTANT && |
2048 | 2130 |
// !value->IsTheHole() && |
2049 | 2131 |
// !value->IsConsString()) { |
2050 | 2132 |
if (value->IsJSFunction()) { |
2051 |
result = AddConstantProperty(name, value, attributes, transition_flag);
|
|
2133 |
AddConstantProperty(object, name, value, attributes, transition_flag);
|
|
2052 | 2134 |
} else { |
2053 |
result = AddFastProperty(
|
|
2054 |
name, value, attributes, store_mode, value_type, transition_flag);
|
|
2135 |
AddFastProperty(object, name, value, attributes, store_mode,
|
|
2136 |
value_type, transition_flag);
|
|
2055 | 2137 |
} |
2056 | 2138 |
} else { |
2057 | 2139 |
// Normalize the object to prevent very large instance descriptors. |
2058 | 2140 |
// This eliminates unwanted N^2 allocation and lookup behavior. |
2059 |
Object* obj; |
|
2060 |
MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
|
2061 |
if (!maybe->To(&obj)) return maybe; |
|
2062 |
result = AddSlowProperty(name, value, attributes); |
|
2141 |
NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
|
2142 |
AddSlowProperty(object, name, value, attributes); |
|
2063 | 2143 |
} |
2064 | 2144 |
} else { |
2065 |
result = AddSlowProperty(name, value, attributes);
|
|
2145 |
AddSlowProperty(object, name, value, attributes);
|
|
2066 | 2146 |
} |
2067 | 2147 |
|
2068 |
Handle<Object> hresult; |
|
2069 |
if (!result->ToHandle(&hresult, isolate)) return result; |
|
2070 |
|
|
2071 |
if (FLAG_harmony_observation && map()->is_observed()) { |
|
2072 |
EnqueueChangeRecord(handle(this, isolate), |
|
2073 |
"new", |
|
2074 |
handle(name, isolate), |
|
2075 |
handle(heap->the_hole_value(), isolate)); |
|
2148 |
if (FLAG_harmony_observation && |
|
2149 |
object->map()->is_observed() && |
|
2150 |
*name != isolate->heap()->hidden_string()) { |
|
2151 |
Handle<Object> old_value = isolate->factory()->the_hole_value(); |
|
2152 |
EnqueueChangeRecord(object, "new", name, old_value); |
|
2076 | 2153 |
} |
2077 | 2154 |
|
2078 |
return *hresult;
|
|
2155 |
return value;
|
|
2079 | 2156 |
} |
2080 | 2157 |
|
2081 | 2158 |
|
... | ... | |
2115 | 2192 |
} |
2116 | 2193 |
|
2117 | 2194 |
|
2118 |
MaybeObject* JSObject::SetPropertyPostInterceptor( |
|
2119 |
Name* name, |
|
2120 |
Object* value, |
|
2195 |
Handle<Object> JSObject::SetPropertyPostInterceptor( |
|
2196 |
Handle<JSObject> object, |
|
2197 |
Handle<Name> name, |
|
2198 |
Handle<Object> value, |
|
2121 | 2199 |
PropertyAttributes attributes, |
2122 |
StrictModeFlag strict_mode, |
|
2123 |
StoreMode mode) { |
|
2200 |
StrictModeFlag strict_mode) { |
|
2124 | 2201 |
// Check local property, ignore interceptor. |
2125 |
LookupResult result(GetIsolate()); |
|
2126 |
LocalLookupRealNamedProperty(name, &result); |
|
2127 |
if (!result.IsFound()) map()->LookupTransition(this, name, &result); |
|
2202 |
LookupResult result(object->GetIsolate()); |
|
2203 |
object->LocalLookupRealNamedProperty(*name, &result); |
|
2204 |
if (!result.IsFound()) { |
|
2205 |
object->map()->LookupTransition(*object, *name, &result); |
|
2206 |
} |
|
2128 | 2207 |
if (result.IsFound()) { |
2129 | 2208 |
// An existing property or a map transition was found. Use set property to |
2130 | 2209 |
// handle all these cases. |
2131 |
return SetProperty(&result, name, value, attributes, strict_mode); |
|
2210 |
return SetPropertyForResult(object, &result, name, value, attributes, |
|
2211 |
strict_mode, MAY_BE_STORE_FROM_KEYED); |
|
2132 | 2212 |
} |
2133 | 2213 |
bool done = false; |
2134 |
MaybeObject* result_object =
|
|
2135 |
SetPropertyViaPrototypes(name, value, attributes, strict_mode, &done);
|
|
2214 |
Handle<Object> result_object = SetPropertyViaPrototypes(
|
|
2215 |
object, name, value, attributes, strict_mode, &done);
|
|
2136 | 2216 |
if (done) return result_object; |
2137 | 2217 |
// Add a new real property. |
2138 |
return AddProperty(name, value, attributes, strict_mode, |
|
2139 |
MAY_BE_STORE_FROM_KEYED, PERFORM_EXTENSIBILITY_CHECK, |
|
2140 |
OPTIMAL_REPRESENTATION, mode); |
|
2218 |
return AddProperty(object, name, value, attributes, strict_mode); |
|
2141 | 2219 |
} |
2142 | 2220 |
|
2143 | 2221 |
|
2144 |
MaybeObject* JSObject::ReplaceSlowProperty(Name* name, |
|
2145 |
Object* value, |
|
2146 |
PropertyAttributes attributes) { |
|
2147 |
NameDictionary* dictionary = property_dictionary(); |
|
2148 |
int old_index = dictionary->FindEntry(name); |
|
2222 |
static void ReplaceSlowProperty(Handle<JSObject> object, |
|
2223 |
Handle<Name> name, |
|
2224 |
Handle<Object> value, |
|
2225 |
PropertyAttributes attributes) { |
|
2226 |
NameDictionary* dictionary = object->property_dictionary(); |
|
2227 |
int old_index = dictionary->FindEntry(*name); |
|
2149 | 2228 |
int new_enumeration_index = 0; // 0 means "Use the next available index." |
2150 | 2229 |
if (old_index != -1) { |
2151 | 2230 |
// All calls to ReplaceSlowProperty have had all transitions removed. |
... | ... | |
2153 | 2232 |
} |
2154 | 2233 |
|
2155 | 2234 |
PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); |
2156 |
return SetNormalizedProperty(name, value, new_details);
|
|
2235 |
JSObject::SetNormalizedProperty(object, name, value, new_details);
|
|
2157 | 2236 |
} |
2158 | 2237 |
|
2159 | 2238 |
|
... | ... | |
2219 | 2298 |
MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta); |
2220 | 2299 |
} |
2221 | 2300 |
} |
2301 |
|
|
2302 |
// The array may not be moved during GC, |
|
2303 |
// and size has to be adjusted nevertheless. |
|
2304 |
HeapProfiler* profiler = heap->isolate()->heap_profiler(); |
|
2305 |
if (profiler->is_tracking_allocations()) { |
|
2306 |
profiler->UpdateObjectSizeEvent(elms->address(), elms->Size()); |
|
2307 |
} |
|
2222 | 2308 |
} |
2223 | 2309 |
|
2224 | 2310 |
|
... | ... | |
2275 | 2361 |
// to temporarily store the inobject properties. |
2276 | 2362 |
// * If there are properties left in the backing store, install the backing |
2277 | 2363 |
// store. |
2278 |
MaybeObject* JSObject::MigrateToMap(Map* new_map) {
|
|
2279 |
Heap* heap = GetHeap();
|
|
2280 |
Map* old_map = map();
|
|
2364 |
void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
|
|
2365 |
Isolate* isolate = object->GetIsolate();
|
|
2366 |
Handle<Map> old_map(object->map());
|
|
2281 | 2367 |
int number_of_fields = new_map->NumberOfFields(); |
2282 | 2368 |
int inobject = new_map->inobject_properties(); |
2283 | 2369 |
int unused = new_map->unused_property_fields(); |
2284 | 2370 |
|
2285 |
// Nothing to do if no functions were converted to fields. |
|
2371 |
// Nothing to do if no functions were converted to fields and no smis were |
|
2372 |
// converted to doubles. |
|
2286 | 2373 |
if (!old_map->InstancesNeedRewriting( |
2287 |
new_map, number_of_fields, inobject, unused)) { |
|
2288 |
set_map(new_map);
|
|
2289 |
return this;
|
|
2374 |
*new_map, number_of_fields, inobject, unused)) {
|
|
2375 |
object->set_map(*new_map);
|
|
2376 |
return; |
|
2290 | 2377 |
} |
2291 | 2378 |
|
2292 | 2379 |
int total_size = number_of_fields + unused; |
2293 | 2380 |
int external = total_size - inobject; |
2294 |
FixedArray* array; |
|
2295 |
MaybeObject* maybe_array = heap->AllocateFixedArray(total_size); |
|
2296 |
if (!maybe_array->To(&array)) return maybe_array; |
|
2381 |
Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size); |
|
2297 | 2382 |
|
2298 |
DescriptorArray* old_descriptors = old_map->instance_descriptors();
|
|
2299 |
DescriptorArray* new_descriptors = new_map->instance_descriptors();
|
|
2383 |
Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
|
|
2384 |
Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors());
|
|
2300 | 2385 |
int descriptors = new_map->NumberOfOwnDescriptors(); |
2301 | 2386 |
|
2302 | 2387 |
for (int i = 0; i < descriptors; i++) { |
... | ... | |
2309 | 2394 |
} |
2310 | 2395 |
ASSERT(old_details.type() == CONSTANT || |
2311 | 2396 |
old_details.type() == FIELD); |
2312 |
Object* value = old_details.type() == CONSTANT |
|
2397 |
Object* raw_value = old_details.type() == CONSTANT
|
|
2313 | 2398 |
? old_descriptors->GetValue(i) |
2314 |
: RawFastPropertyAt(old_descriptors->GetFieldIndex(i)); |
|
2399 |
: object->RawFastPropertyAt(old_descriptors->GetFieldIndex(i)); |
|
2400 |
Handle<Object> value(raw_value, isolate); |
|
2315 | 2401 |
if (FLAG_track_double_fields && |
2316 | 2402 |
!old_details.representation().IsDouble() && |
2317 | 2403 |
details.representation().IsDouble()) { |
2318 |
if (old_details.representation().IsNone()) value = Smi::FromInt(0); |
|
2319 |
// Objects must be allocated in the old object space, since the |
|
2320 |
// overall number of HeapNumbers needed for the conversion might |
|
2321 |
// exceed the capacity of new space, and we would fail repeatedly |
|
2322 |
// trying to migrate the instance. |
|
2323 |
MaybeObject* maybe_storage = |
|
2324 |
value->AllocateNewStorageFor(heap, details.representation(), TENURED); |
|
2325 |
if (!maybe_storage->To(&value)) return maybe_storage; |
|
2404 |
if (old_details.representation().IsNone()) { |
|
2405 |
value = handle(Smi::FromInt(0), isolate); |
|
2406 |
} |
|
2407 |
value = NewStorageFor(isolate, value, details.representation()); |
|
2326 | 2408 |
} |
2327 | 2409 |
ASSERT(!(FLAG_track_double_fields && |
2328 | 2410 |
details.representation().IsDouble() && |
2329 | 2411 |
value->IsSmi())); |
2330 | 2412 |
int target_index = new_descriptors->GetFieldIndex(i) - inobject; |
2331 | 2413 |
if (target_index < 0) target_index += total_size; |
2332 |
array->set(target_index, value); |
|
2414 |
array->set(target_index, *value);
|
|
2333 | 2415 |
} |
2334 | 2416 |
|
2335 |
// From here on we cannot fail anymore. |
|
2417 |
// From here on we cannot fail and we shouldn't GC anymore. |
|
2418 |
DisallowHeapAllocation no_allocation; |
|
2336 | 2419 |
|
2337 | 2420 |
// Copy (real) inobject properties. If necessary, stop at number_of_fields to |
2338 | 2421 |
// avoid overwriting |one_pointer_filler_map|. |
2339 | 2422 |
int limit = Min(inobject, number_of_fields); |
2340 | 2423 |
for (int i = 0; i < limit; i++) { |
2341 |
FastPropertyAtPut(i, array->get(external + i)); |
|
2424 |
object->FastPropertyAtPut(i, array->get(external + i));
|
|
2342 | 2425 |
} |
2343 | 2426 |
|
2344 | 2427 |
// Create filler object past the new instance size. |
2345 | 2428 |
int new_instance_size = new_map->instance_size(); |
2346 | 2429 |
int instance_size_delta = old_map->instance_size() - new_instance_size; |
2347 | 2430 |
ASSERT(instance_size_delta >= 0); |
2348 |
Address address = this->address() + new_instance_size;
|
|
2349 |
heap->CreateFillerObjectAt(address, instance_size_delta);
|
|
2431 |
Address address = object->address() + new_instance_size;
|
|
2432 |
isolate->heap()->CreateFillerObjectAt(address, instance_size_delta);
|
|
2350 | 2433 |
|
2351 | 2434 |
// If there are properties in the new backing store, trim it to the correct |
2352 | 2435 |
// size and install the backing store into the object. |
2353 | 2436 |
if (external > 0) { |
2354 |
RightTrimFixedArray<FROM_MUTATOR>(heap, array, inobject);
|
|
2355 |
set_properties(array);
|
|
2437 |
RightTrimFixedArray<FROM_MUTATOR>(isolate->heap(), *array, inobject);
|
|
2438 |
object->set_properties(*array);
|
|
2356 | 2439 |
} |
2357 | 2440 |
|
2358 |
set_map(new_map); |
|
2359 |
|
|
2360 |
return this; |
|
2441 |
object->set_map(*new_map); |
|
2361 | 2442 |
} |
2362 | 2443 |
|
2363 | 2444 |
|
2364 |
MaybeObject* JSObject::GeneralizeFieldRepresentation(
|
|
2365 |
int modify_index,
|
|
2366 |
Representation new_representation,
|
|
2367 |
StoreMode store_mode) {
|
|
2368 |
Map* new_map;
|
|
2369 |
MaybeObject* maybe_new_map = map()->GeneralizeRepresentation(
|
|
2370 |
modify_index, new_representation, store_mode);
|
|
2371 |
if (!maybe_new_map->To(&new_map)) return maybe_new_map;
|
|
2372 |
if (map() == new_map) return this; |
|
2445 |
Handle<TransitionArray> Map::AddTransition(Handle<Map> map,
|
|
2446 |
Handle<Name> key,
|
|
2447 |
Handle<Map> target,
|
|
2448 |
SimpleTransitionFlag flag) {
|
|
2449 |
CALL_HEAP_FUNCTION(map->GetIsolate(),
|
|
2450 |
map->AddTransition(*key, *target, flag),
|
|
2451 |
TransitionArray);
|
|
2452 |
}
|
|
2453 |
|
|
2373 | 2454 |
|
2374 |
return MigrateToMap(new_map); |
|
2455 |
void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, |
|
2456 |
int modify_index, |
|
2457 |
Representation new_representation, |
|
2458 |
StoreMode store_mode) { |
|
2459 |
Handle<Map> new_map = Map::GeneralizeRepresentation( |
|
2460 |
handle(object->map()), modify_index, new_representation, store_mode); |
|
2461 |
if (object->map() == *new_map) return; |
|
2462 |
return MigrateToMap(object, new_map); |
|
2375 | 2463 |
} |
2376 | 2464 |
|
2377 | 2465 |
|
... | ... | |
2385 | 2473 |
} |
2386 | 2474 |
|
2387 | 2475 |
|
2388 |
MaybeObject* Map::CopyGeneralizeAllRepresentations( |
|
2389 |
int modify_index, |
|
2390 |
StoreMode store_mode, |
|
2391 |
PropertyAttributes attributes, |
|
2392 |
const char* reason) { |
|
2393 |
Map* new_map; |
|
2394 |
MaybeObject* maybe_map = this->Copy(); |
|
2395 |
if (!maybe_map->To(&new_map)) return maybe_map; |
|
2476 |
Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map, |
|
2477 |
int modify_index, |
|
2478 |
StoreMode store_mode, |
|
2479 |
PropertyAttributes attributes, |
|
2480 |
const char* reason) { |
|
2481 |
Handle<Map> new_map = Copy(map); |
|
2396 | 2482 |
|
2397 | 2483 |
DescriptorArray* descriptors = new_map->instance_descriptors(); |
2398 | 2484 |
descriptors->InitializeRepresentations(Representation::Tagged()); |
... | ... | |
2414 | 2500 |
} |
2415 | 2501 |
|
2416 | 2502 |
if (FLAG_trace_generalization) { |
2417 |
PrintGeneralization(stdout, reason, modify_index, |
|
2503 |
map->PrintGeneralization(stdout, reason, modify_index,
|
|
2418 | 2504 |
new_map->NumberOfOwnDescriptors(), |
2419 | 2505 |
new_map->NumberOfOwnDescriptors(), |
2420 | 2506 |
details.type() == CONSTANT && store_mode == FORCE_FIELD, |
... | ... | |
2562 | 2648 |
// - If |updated| == |split_map|, |updated| is in the expected state. Return it. |
2563 | 2649 |
// - Otherwise, invalidate the outdated transition target from |updated|, and |
2564 | 2650 |
// replace its transition tree with a new branch for the updated descriptors. |
2565 |
MaybeObject* Map::GeneralizeRepresentation(int modify_index,
|
|
2566 |
Representation new_representation,
|
|
2567 |
StoreMode store_mode) {
|
|
2568 |
Map* old_map = this;
|
|
2569 |
DescriptorArray* old_descriptors = old_map->instance_descriptors();
|
|
2651 |
Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
|
|
2652 |
int modify_index,
|
|
2653 |
Representation new_representation,
|
|
2654 |
StoreMode store_mode) {
|
|
2655 |
Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
|
|
2570 | 2656 |
PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
2571 | 2657 |
Representation old_representation = old_details.representation(); |
2572 | 2658 |
|
... | ... | |
2582 | 2668 |
} |
2583 | 2669 |
|
2584 | 2670 |
int descriptors = old_map->NumberOfOwnDescriptors(); |
2585 |
Map* root_map = old_map->FindRootMap();
|
|
2671 |
Handle<Map> root_map(old_map->FindRootMap());
|
|
2586 | 2672 |
|
2587 | 2673 |
// Check the state of the root map. |
2588 |
if (!old_map->EquivalentToForTransition(root_map)) { |
|
2589 |
return CopyGeneralizeAllRepresentations( |
|
2590 |
modify_index, store_mode, old_details.attributes(), "not equivalent");
|
|
2674 |
if (!old_map->EquivalentToForTransition(*root_map)) {
|
|
2675 |
return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
|
|
2676 |
old_details.attributes(), "not equivalent"); |
|
2591 | 2677 |
} |
2592 | 2678 |
|
2593 | 2679 |
int verbatim = root_map->NumberOfOwnDescriptors(); |
2594 | 2680 |
|
2595 | 2681 |
if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) { |
2596 |
return CopyGeneralizeAllRepresentations( |
|
2597 |
modify_index, store_mode, |
|
2682 |
return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
|
2598 | 2683 |
old_details.attributes(), "root modification"); |
2599 | 2684 |
} |
2600 | 2685 |
|
2601 |
Map* updated = root_map->FindUpdatedMap( |
|
2602 |
verbatim, descriptors, old_descriptors); |
|
2603 |
if (updated == NULL) { |
|
2604 |
return CopyGeneralizeAllRepresentations( |
|
2605 |
modify_index, store_mode, old_details.attributes(), "incompatible");
|
|
2686 |
Map* raw_updated = root_map->FindUpdatedMap(
|
|
2687 |
verbatim, descriptors, *old_descriptors);
|
|
2688 |
if (raw_updated == NULL) {
|
|
2689 |
return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
|
|
2690 |
old_details.attributes(), "incompatible"); |
|
2606 | 2691 |
} |
2607 | 2692 |
|
2608 |
DescriptorArray* updated_descriptors = updated->instance_descriptors(); |
|
2693 |
Handle<Map> updated(raw_updated); |
|
2694 |
Handle<DescriptorArray> updated_descriptors(updated->instance_descriptors()); |
|
2609 | 2695 |
|
2610 | 2696 |
int valid = updated->NumberOfOwnDescriptors(); |
2611 | 2697 |
|
2612 | 2698 |
// Directly change the map if the target map is more general. Ensure that the |
2613 | 2699 |
// target type of the modify_index is a FIELD, unless we are migrating. |
2614 | 2700 |
if (updated_descriptors->IsMoreGeneralThan( |
2615 |
verbatim, valid, descriptors, old_descriptors) && |
|
2701 |
verbatim, valid, descriptors, *old_descriptors) &&
|
|
2616 | 2702 |
(store_mode == ALLOW_AS_CONSTANT || |
2617 | 2703 |
updated_descriptors->GetDetails(modify_index).type() == FIELD)) { |
2618 | 2704 |
Representation updated_representation = |
... | ... | |
2620 | 2706 |
if (new_representation.fits_into(updated_representation)) return updated; |
2621 | 2707 |
} |
2622 | 2708 |
|
2623 |
DescriptorArray* new_descriptors; |
|
2624 |
MaybeObject* maybe_descriptors = updated_descriptors->Merge( |
|
2625 |
verbatim, valid, descriptors, modify_index, store_mode, old_descriptors); |
|
2626 |
if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
|
2709 |
Handle<DescriptorArray> new_descriptors = DescriptorArray::Merge( |
|
2710 |
updated_descriptors, verbatim, valid, descriptors, modify_index, |
|
2711 |
store_mode, old_descriptors); |
|
2627 | 2712 |
ASSERT(store_mode == ALLOW_AS_CONSTANT || |
2628 | 2713 |
new_descriptors->GetDetails(modify_index).type() == FIELD); |
2629 | 2714 |
|
... | ... | |
2635 | 2720 |
new_descriptors->SetRepresentation(modify_index, updated_representation); |
2636 | 2721 |
} |
2637 | 2722 |
|
2638 |
Map* split_map = root_map->FindLastMatchMap(
|
|
2639 |
verbatim, descriptors, new_descriptors);
|
|
2723 |
Handle<Map> split_map(root_map->FindLastMatchMap(
|
|
2724 |
verbatim, descriptors, *new_descriptors));
|
|
2640 | 2725 |
|
2641 | 2726 |
int split_descriptors = split_map->NumberOfOwnDescriptors(); |
2642 | 2727 |
// This is shadowed by |updated_descriptors| being more general than |
... | ... | |
2645 | 2730 |
|
2646 | 2731 |
int descriptor = split_descriptors; |
2647 | 2732 |
split_map->DeprecateTarget( |
2648 |
old_descriptors->GetKey(descriptor), new_descriptors); |
|
2733 |
old_descriptors->GetKey(descriptor), *new_descriptors);
|
|
2649 | 2734 |
|
2650 | 2735 |
if (FLAG_trace_generalization) { |
2651 |
PrintGeneralization( |
|
2736 |
old_map->PrintGeneralization(
|
|
2652 | 2737 |
stdout, "", modify_index, descriptor, descriptors, |
2653 | 2738 |
old_descriptors->GetDetails(modify_index).type() == CONSTANT && |
2654 | 2739 |
store_mode == FORCE_FIELD, |
2655 | 2740 |
old_representation, updated_representation); |
2656 | 2741 |
} |
2657 | 2742 |
|
2658 |
Map* new_map = split_map; |
|
2659 | 2743 |
// Add missing transitions. |
2744 |
Handle<Map> new_map = split_map; |
|
2660 | 2745 |
for (; descriptor < descriptors; descriptor++) { |
2661 |
MaybeObject* maybe_map = new_map->CopyInstallDescriptors( |
|
2662 |
descriptor, new_descriptors); |
|
2663 |
if (!maybe_map->To(&new_map)) { |
|
2664 |
// Create a handle for the last created map to ensure it stays alive |
|
2665 |
// during GC. Its descriptor array is too large, but it will be |
|
2666 |
// overwritten during retry anyway. |
|
2667 |
Handle<Map>(new_map); |
|
2668 |
return maybe_map; |
|
2669 |
} |
|
2746 |
new_map = Map::CopyInstallDescriptors(new_map, descriptor, new_descriptors); |
|
2670 | 2747 |
new_map->set_migration_target(true); |
2671 | 2748 |
} |
2672 | 2749 |
|
... | ... | |
2675 | 2752 |
} |
2676 | 2753 |
|
2677 | 2754 |
|
2678 |
Map* Map::CurrentMapForDeprecated() { |
|
2755 |
// Generalize the representation of all FIELD descriptors. |
|
2756 |
Handle<Map> Map::GeneralizeAllFieldRepresentations( |
|
2757 |
Handle<Map> map, |
|
2758 |
Representation new_representation) { |
|
2759 |
Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
|
2760 |
for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { |
|
2761 |
PropertyDetails details = descriptors->GetDetails(i); |
|
2762 |
if (details.type() == FIELD) { |
|
2763 |
map = GeneralizeRepresentation(map, i, new_representation, FORCE_FIELD); |
|
2764 |
} |
|
2765 |
} |
|
2766 |
return map; |
|
2767 |
} |
|
2768 |
|
|
2769 |
|
|
2770 |
Map* Map::CurrentMapForDeprecated() { |
|
2679 | 2771 |
DisallowHeapAllocation no_allocation; |
2680 | 2772 |
if (!is_deprecated()) return this; |
2681 | 2773 |
|
... | ... | |
2703 | 2795 |
} |
2704 | 2796 |
|
2705 | 2797 |
|
2706 |
MaybeObject* JSObject::SetPropertyWithInterceptor( |
|
2707 |
Name* name, |
|
2708 |
Object* value, |
|
2798 |
Handle<Object> JSObject::SetPropertyWithInterceptor( |
|
2799 |
Handle<JSObject> object, |
|
2800 |
Handle<Name> name, |
|
2801 |
Handle<Object> value, |
|
2709 | 2802 |
PropertyAttributes attributes, |
2710 | 2803 |
StrictModeFlag strict_mode) { |
2711 | 2804 |
// TODO(rossberg): Support symbols in the API. |
2712 | 2805 |
if (name->IsSymbol()) return value; |
2713 |
Isolate* isolate = GetIsolate(); |
|
2714 |
HandleScope scope(isolate); |
|
2715 |
Handle<JSObject> this_handle(this); |
|
2716 |
Handle<String> name_handle(String::cast(name)); |
|
2717 |
Handle<Object> value_handle(value, isolate); |
|
2718 |
Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); |
|
2806 |
Isolate* isolate = object->GetIsolate(); |
|
2807 |
Handle<String> name_string = Handle<String>::cast(name); |
|
2808 |
Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor()); |
|
2719 | 2809 |
if (!interceptor->setter()->IsUndefined()) { |
2720 |
LOG(isolate, ApiNamedPropertyAccess("interceptor-named-set", this, name)); |
|
2721 |
PropertyCallbackArguments args(isolate, interceptor->data(), this, this); |
|
2810 |
LOG(isolate, |
|
2811 |
ApiNamedPropertyAccess("interceptor-named-set", *object, *name)); |
|
2812 |
PropertyCallbackArguments args( |
|
2813 |
isolate, interceptor->data(), *object, *object); |
|
2722 | 2814 |
v8::NamedPropertySetterCallback setter = |
2723 | 2815 |
v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter()); |
2724 |
Handle<Object> value_unhole(value->IsTheHole() ? |
|
2725 |
isolate->heap()->undefined_value() : |
|
2726 |
value, |
|
2727 |
isolate); |
|
2816 |
Handle<Object> value_unhole = value->IsTheHole() |
|
2817 |
? Handle<Object>(isolate->factory()->undefined_value()) : value; |
|
2728 | 2818 |
v8::Handle<v8::Value> result = args.Call(setter, |
2729 |
v8::Utils::ToLocal(name_handle),
|
|
2819 |
v8::Utils::ToLocal(name_string),
|
|
2730 | 2820 |
v8::Utils::ToLocal(value_unhole)); |
2731 |
RETURN_IF_SCHEDULED_EXCEPTION(isolate);
|
|
2732 |
if (!result.IsEmpty()) return *value_handle;
|
|
2821 |
RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
|
2822 |
if (!result.IsEmpty()) return value;
|
|
2733 | 2823 |
} |
2734 |
MaybeObject* raw_result = |
|
2735 |
this_handle->SetPropertyPostInterceptor(*name_handle, |
|
2736 |
*value_handle, |
|
2737 |
attributes, |
|
2738 |
strict_mode); |
|
2739 |
RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
|
2740 |
return raw_result; |
|
2824 |
Handle<Object> result = |
|
2825 |
SetPropertyPostInterceptor(object, name, value, attributes, strict_mode); |
|
2826 |
RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
|
2827 |
return result; |
|
2741 | 2828 |
} |
2742 | 2829 |
|
2743 | 2830 |
|
2744 | 2831 |
Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, |
2745 |
Handle<Name> key,
|
|
2832 |
Handle<Name> name,
|
|
2746 | 2833 |
Handle<Object> value, |
2747 | 2834 |
PropertyAttributes attributes, |
2748 |
StrictModeFlag strict_mode) { |
|
2749 |
CALL_HEAP_FUNCTION(object->GetIsolate(), |
|
2750 |
object->SetProperty(*key, *value, attributes, strict_mode), |
|
2751 |
Object); |
|
2752 |
} |
|
2753 |
|
|
2754 |
|
|
2755 |
MaybeObject* JSReceiver::SetPropertyOrFail( |
|
2756 |
Handle<JSReceiver> object, |
|
2757 |
Handle<Name> key, |
|
2758 |
Handle<Object> value, |
|
2759 |
PropertyAttributes attributes, |
|
2760 |
StrictModeFlag strict_mode, |
|
2761 |
JSReceiver::StoreFromKeyed store_mode) { |
|
2762 |
CALL_HEAP_FUNCTION_PASS_EXCEPTION( |
|
2763 |
object->GetIsolate(), |
|
2764 |
object->SetProperty(*key, *value, attributes, strict_mode, store_mode)); |
|
2765 |
} |
|
2766 |
|
|
2767 |
|
|
2768 |
MaybeObject* JSReceiver::SetProperty(Name* name, |
|
2769 |
Object* value, |
|
2770 |
PropertyAttributes attributes, |
|
2771 |
StrictModeFlag strict_mode, |
|
2772 |
JSReceiver::StoreFromKeyed store_mode) { |
|
2773 |
LookupResult result(GetIsolate()); |
|
2774 |
LocalLookup(name, &result, true); |
|
2835 |
StrictModeFlag strict_mode, |
|
2836 |
StoreFromKeyed store_mode) { |
|
2837 |
LookupResult result(object->GetIsolate()); |
|
2838 |
object->LocalLookup(*name, &result, true); |
|
2775 | 2839 |
if (!result.IsFound()) { |
2776 |
map()->LookupTransition(JSObject::cast(this), name, &result);
|
|
2840 |
object->map()->LookupTransition(JSObject::cast(*object), *name, &result);
|
|
2777 | 2841 |
} |
2778 |
return SetProperty(&result, name, value, attributes, strict_mode, store_mode); |
|
2842 |
return SetProperty(object, &result, name, value, attributes, strict_mode, |
|
2843 |
store_mode); |
|
2779 | 2844 |
} |
2780 | 2845 |
|
2781 | 2846 |
|
2782 |
MaybeObject* JSObject::SetPropertyWithCallback(Object* structure,
|
|
2783 |
Name* name,
|
|
2784 |
Object* value,
|
|
2785 |
JSObject* holder,
|
|
2786 |
StrictModeFlag strict_mode) {
|
|
2787 |
Isolate* isolate = GetIsolate();
|
|
2788 |
HandleScope scope(isolate);
|
|
2847 |
Handle<Object> JSObject::SetPropertyWithCallback(Handle<JSObject> object,
|
|
2848 |
Handle<Object> structure,
|
|
2849 |
Handle<Name> name,
|
|
2850 |
Handle<Object> value,
|
|
2851 |
Handle<JSObject> holder,
|
|
2852 |
StrictModeFlag strict_mode) {
|
|
2853 |
Isolate* isolate = object->GetIsolate();
|
|
2789 | 2854 |
|
2790 | 2855 |
// We should never get here to initialize a const with the hole |
2791 | 2856 |
// value since a const declaration would conflict with the setter. |
2792 | 2857 |
ASSERT(!value->IsTheHole()); |
2793 |
Handle<Object> value_handle(value, isolate); |
|
2794 | 2858 |
|
2795 | 2859 |
// To accommodate both the old and the new api we switch on the |
2796 | 2860 |
// data structure used to store the callbacks. Eventually foreign |
... | ... | |
2798 | 2862 |
if (structure->IsForeign()) { |
2799 | 2863 |
AccessorDescriptor* callback = |
2800 | 2864 |
reinterpret_cast<AccessorDescriptor*>( |
2801 |
Foreign::cast(structure)->foreign_address()); |
|
2802 |
MaybeObject* obj = (callback->setter)( |
|
2803 |
isolate, this, value, callback->data); |
|
2804 |
RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
Also available in: Unified diff