| 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 10 matching lines...) Expand all Loading... |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "accessors.h" | 30 #include "accessors.h" |
| 31 #include "allocation-site-scopes.h" |
| 31 #include "api.h" | 32 #include "api.h" |
| 32 #include "arguments.h" | 33 #include "arguments.h" |
| 33 #include "bootstrapper.h" | 34 #include "bootstrapper.h" |
| 34 #include "codegen.h" | 35 #include "codegen.h" |
| 35 #include "cpu-profiler.h" | 36 #include "cpu-profiler.h" |
| 36 #include "debug.h" | 37 #include "debug.h" |
| 37 #include "deoptimizer.h" | 38 #include "deoptimizer.h" |
| 38 #include "date.h" | 39 #include "date.h" |
| 39 #include "elements.h" | 40 #include "elements.h" |
| 40 #include "execution.h" | 41 #include "execution.h" |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 } else { | 136 } else { |
| 136 result->isolate()->PushStackTraceAndDie( | 137 result->isolate()->PushStackTraceAndDie( |
| 137 0xDEAD0000, this, JSReceiver::cast(this)->map(), 0xDEAD0001); | 138 0xDEAD0000, this, JSReceiver::cast(this)->map(), 0xDEAD0001); |
| 138 } | 139 } |
| 139 } | 140 } |
| 140 ASSERT(holder != NULL); // Cannot handle null or undefined. | 141 ASSERT(holder != NULL); // Cannot handle null or undefined. |
| 141 JSReceiver::cast(holder)->Lookup(name, result); | 142 JSReceiver::cast(holder)->Lookup(name, result); |
| 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 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver, | 160 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver, |
| 146 Name* name, | 161 Name* name, |
| 147 PropertyAttributes* attributes) { | 162 PropertyAttributes* attributes) { |
| 148 LookupResult result(name->GetIsolate()); | 163 LookupResult result(name->GetIsolate()); |
| 149 Lookup(name, &result); | 164 Lookup(name, &result); |
| 150 MaybeObject* value = GetProperty(receiver, &result, name, attributes); | 165 MaybeObject* value = GetProperty(receiver, &result, name, attributes); |
| 151 ASSERT(*attributes <= ABSENT); | 166 ASSERT(*attributes <= ABSENT); |
| 152 return value; | 167 return value; |
| 153 } | 168 } |
| 154 | 169 |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 return GetPrimitiveValue(data->primitive_value_descriptor, | 336 return GetPrimitiveValue(data->primitive_value_descriptor, |
| 322 current, | 337 current, |
| 323 isolate->heap()); | 338 isolate->heap()); |
| 324 } | 339 } |
| 325 } | 340 } |
| 326 UNREACHABLE(); | 341 UNREACHABLE(); |
| 327 return NULL; | 342 return NULL; |
| 328 } | 343 } |
| 329 | 344 |
| 330 | 345 |
| 331 MaybeObject* JSObject::GetPropertyWithCallback(Object* receiver, | 346 Handle<Object> JSObject::GetPropertyWithCallback(Handle<JSObject> object, |
| 332 Object* structure, | 347 Handle<Object> receiver, |
| 333 Name* name) { | 348 Handle<Object> structure, |
| 349 Handle<Name> name) { |
| 334 Isolate* isolate = name->GetIsolate(); | 350 Isolate* isolate = name->GetIsolate(); |
| 335 // To accommodate both the old and the new api we switch on the | 351 // To accommodate both the old and the new api we switch on the |
| 336 // data structure used to store the callbacks. Eventually foreign | 352 // data structure used to store the callbacks. Eventually foreign |
| 337 // callbacks should be phased out. | 353 // callbacks should be phased out. |
| 338 if (structure->IsForeign()) { | 354 if (structure->IsForeign()) { |
| 339 AccessorDescriptor* callback = | 355 AccessorDescriptor* callback = |
| 340 reinterpret_cast<AccessorDescriptor*>( | 356 reinterpret_cast<AccessorDescriptor*>( |
| 341 Foreign::cast(structure)->foreign_address()); | 357 Handle<Foreign>::cast(structure)->foreign_address()); |
| 342 MaybeObject* value = (callback->getter)(isolate, receiver, callback->data); | 358 CALL_HEAP_FUNCTION(isolate, |
| 343 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 359 (callback->getter)(isolate, *receiver, callback->data), |
| 344 return value; | 360 Object); |
| 345 } | 361 } |
| 346 | 362 |
| 347 // api style callbacks. | 363 // api style callbacks. |
| 348 if (structure->IsAccessorInfo()) { | 364 if (structure->IsAccessorInfo()) { |
| 349 if (!AccessorInfo::cast(structure)->IsCompatibleReceiver(receiver)) { | 365 Handle<AccessorInfo> accessor_info = Handle<AccessorInfo>::cast(structure); |
| 350 Handle<Object> name_handle(name, isolate); | 366 if (!accessor_info->IsCompatibleReceiver(*receiver)) { |
| 351 Handle<Object> receiver_handle(receiver, isolate); | 367 Handle<Object> args[2] = { name, receiver }; |
| 352 Handle<Object> args[2] = { name_handle, receiver_handle }; | |
| 353 Handle<Object> error = | 368 Handle<Object> error = |
| 354 isolate->factory()->NewTypeError("incompatible_method_receiver", | 369 isolate->factory()->NewTypeError("incompatible_method_receiver", |
| 355 HandleVector(args, | 370 HandleVector(args, |
| 356 ARRAY_SIZE(args))); | 371 ARRAY_SIZE(args))); |
| 357 return isolate->Throw(*error); | 372 isolate->Throw(*error); |
| 373 return Handle<Object>::null(); |
| 358 } | 374 } |
| 359 // TODO(rossberg): Handling symbols in the API requires changing the API, | 375 // TODO(rossberg): Handling symbols in the API requires changing the API, |
| 360 // so we do not support it for now. | 376 // so we do not support it for now. |
| 361 if (name->IsSymbol()) return isolate->heap()->undefined_value(); | 377 if (name->IsSymbol()) return isolate->factory()->undefined_value(); |
| 362 if (structure->IsDeclaredAccessorInfo()) { | 378 if (structure->IsDeclaredAccessorInfo()) { |
| 363 return GetDeclaredAccessorProperty(receiver, | 379 CALL_HEAP_FUNCTION( |
| 364 DeclaredAccessorInfo::cast(structure), | 380 isolate, |
| 365 isolate); | 381 GetDeclaredAccessorProperty(*receiver, |
| 382 DeclaredAccessorInfo::cast(*structure), |
| 383 isolate), |
| 384 Object); |
| 366 } | 385 } |
| 367 ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(structure); | 386 |
| 368 Object* fun_obj = data->getter(); | 387 Handle<ExecutableAccessorInfo> data = |
| 388 Handle<ExecutableAccessorInfo>::cast(structure); |
| 369 v8::AccessorGetterCallback call_fun = | 389 v8::AccessorGetterCallback call_fun = |
| 370 v8::ToCData<v8::AccessorGetterCallback>(fun_obj); | 390 v8::ToCData<v8::AccessorGetterCallback>(data->getter()); |
| 371 if (call_fun == NULL) return isolate->heap()->undefined_value(); | 391 if (call_fun == NULL) return isolate->factory()->undefined_value(); |
| 392 |
| 372 HandleScope scope(isolate); | 393 HandleScope scope(isolate); |
| 373 JSObject* self = JSObject::cast(receiver); | 394 Handle<JSObject> self = Handle<JSObject>::cast(receiver); |
| 374 Handle<String> key(String::cast(name)); | 395 Handle<String> key = Handle<String>::cast(name); |
| 375 LOG(isolate, ApiNamedPropertyAccess("load", self, name)); | 396 LOG(isolate, ApiNamedPropertyAccess("load", *self, *name)); |
| 376 PropertyCallbackArguments args(isolate, data->data(), self, this); | 397 PropertyCallbackArguments args(isolate, data->data(), *self, *object); |
| 377 v8::Handle<v8::Value> result = | 398 v8::Handle<v8::Value> result = |
| 378 args.Call(call_fun, v8::Utils::ToLocal(key)); | 399 args.Call(call_fun, v8::Utils::ToLocal(key)); |
| 379 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 400 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 380 if (result.IsEmpty()) { | 401 if (result.IsEmpty()) { |
| 381 return isolate->heap()->undefined_value(); | 402 return isolate->factory()->undefined_value(); |
| 382 } | 403 } |
| 383 Object* return_value = *v8::Utils::OpenHandle(*result); | 404 Handle<Object> return_value = v8::Utils::OpenHandle(*result); |
| 384 return_value->VerifyApiCallResultType(); | 405 return_value->VerifyApiCallResultType(); |
| 385 return return_value; | 406 return scope.CloseAndEscape(return_value); |
| 386 } | 407 } |
| 387 | 408 |
| 388 // __defineGetter__ callback | 409 // __defineGetter__ callback |
| 389 if (structure->IsAccessorPair()) { | 410 Handle<Object> getter(Handle<AccessorPair>::cast(structure)->getter(), |
| 390 Object* getter = AccessorPair::cast(structure)->getter(); | 411 isolate); |
| 391 if (getter->IsSpecFunction()) { | 412 if (getter->IsSpecFunction()) { |
| 392 // TODO(rossberg): nicer would be to cast to some JSCallable here... | 413 // TODO(rossberg): nicer would be to cast to some JSCallable here... |
| 393 return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter)); | 414 CALL_HEAP_FUNCTION( |
| 394 } | 415 isolate, |
| 395 // Getter is not a function. | 416 object->GetPropertyWithDefinedGetter(*receiver, |
| 396 return isolate->heap()->undefined_value(); | 417 JSReceiver::cast(*getter)), |
| 418 Object); |
| 397 } | 419 } |
| 398 | 420 // Getter is not a function. |
| 399 UNREACHABLE(); | 421 return isolate->factory()->undefined_value(); |
| 400 return NULL; | |
| 401 } | 422 } |
| 402 | 423 |
| 403 | 424 |
| 404 MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw, | 425 MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw, |
| 405 Name* name_raw) { | 426 Name* name_raw) { |
| 406 Isolate* isolate = GetIsolate(); | 427 Isolate* isolate = GetIsolate(); |
| 407 HandleScope scope(isolate); | 428 HandleScope scope(isolate); |
| 408 Handle<Object> receiver(receiver_raw, isolate); | 429 Handle<Object> receiver(receiver_raw, isolate); |
| 409 Handle<Object> name(name_raw, isolate); | 430 Handle<Object> name(name_raw, isolate); |
| 410 | 431 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 486 bool has_pending_exception; | 507 bool has_pending_exception; |
| 487 Handle<Object> result = Execution::Call( | 508 Handle<Object> result = Execution::Call( |
| 488 isolate, fun, self, 0, NULL, &has_pending_exception, true); | 509 isolate, fun, self, 0, NULL, &has_pending_exception, true); |
| 489 // Check for pending exception and return the result. | 510 // Check for pending exception and return the result. |
| 490 if (has_pending_exception) return Failure::Exception(); | 511 if (has_pending_exception) return Failure::Exception(); |
| 491 return *result; | 512 return *result; |
| 492 } | 513 } |
| 493 | 514 |
| 494 | 515 |
| 495 // Only deal with CALLBACKS and INTERCEPTOR | 516 // Only deal with CALLBACKS and INTERCEPTOR |
| 496 MaybeObject* JSObject::GetPropertyWithFailedAccessCheck( | 517 Handle<Object> JSObject::GetPropertyWithFailedAccessCheck( |
| 497 Object* receiver, | 518 Handle<JSObject> object, |
| 519 Handle<Object> receiver, |
| 498 LookupResult* result, | 520 LookupResult* result, |
| 499 Name* name, | 521 Handle<Name> name, |
| 500 PropertyAttributes* attributes) { | 522 PropertyAttributes* attributes) { |
| 523 Isolate* isolate = name->GetIsolate(); |
| 501 if (result->IsProperty()) { | 524 if (result->IsProperty()) { |
| 502 switch (result->type()) { | 525 switch (result->type()) { |
| 503 case CALLBACKS: { | 526 case CALLBACKS: { |
| 504 // Only allow API accessors. | 527 // Only allow API accessors. |
| 505 Object* obj = result->GetCallbackObject(); | 528 Handle<Object> callback_obj(result->GetCallbackObject(), isolate); |
| 506 if (obj->IsAccessorInfo()) { | 529 if (callback_obj->IsAccessorInfo()) { |
| 507 AccessorInfo* info = AccessorInfo::cast(obj); | 530 if (!AccessorInfo::cast(*callback_obj)->all_can_read()) break; |
| 508 if (info->all_can_read()) { | 531 *attributes = result->GetAttributes(); |
| 509 *attributes = result->GetAttributes(); | 532 // Fall through to GetPropertyWithCallback. |
| 510 return result->holder()->GetPropertyWithCallback( | 533 } else if (callback_obj->IsAccessorPair()) { |
| 511 receiver, result->GetCallbackObject(), name); | 534 if (!AccessorPair::cast(*callback_obj)->all_can_read()) break; |
| 512 } | 535 // Fall through to GetPropertyWithCallback. |
| 513 } else if (obj->IsAccessorPair()) { | 536 } else { |
| 514 AccessorPair* pair = AccessorPair::cast(obj); | 537 break; |
| 515 if (pair->all_can_read()) { | |
| 516 return result->holder()->GetPropertyWithCallback( | |
| 517 receiver, result->GetCallbackObject(), name); | |
| 518 } | |
| 519 } | 538 } |
| 520 break; | 539 Handle<JSObject> holder(result->holder(), isolate); |
| 540 return GetPropertyWithCallback(holder, receiver, callback_obj, name); |
| 521 } | 541 } |
| 522 case NORMAL: | 542 case NORMAL: |
| 523 case FIELD: | 543 case FIELD: |
| 524 case CONSTANT: { | 544 case CONSTANT: { |
| 525 // Search ALL_CAN_READ accessors in prototype chain. | 545 // Search ALL_CAN_READ accessors in prototype chain. |
| 526 LookupResult r(GetIsolate()); | 546 LookupResult r(isolate); |
| 527 result->holder()->LookupRealNamedPropertyInPrototypes(name, &r); | 547 result->holder()->LookupRealNamedPropertyInPrototypes(*name, &r); |
| 528 if (r.IsProperty()) { | 548 if (r.IsProperty()) { |
| 529 return GetPropertyWithFailedAccessCheck(receiver, | 549 return GetPropertyWithFailedAccessCheck( |
| 530 &r, | 550 object, receiver, &r, name, attributes); |
| 531 name, | |
| 532 attributes); | |
| 533 } | 551 } |
| 534 break; | 552 break; |
| 535 } | 553 } |
| 536 case INTERCEPTOR: { | 554 case INTERCEPTOR: { |
| 537 // If the object has an interceptor, try real named properties. | 555 // If the object has an interceptor, try real named properties. |
| 538 // No access check in GetPropertyAttributeWithInterceptor. | 556 // No access check in GetPropertyAttributeWithInterceptor. |
| 539 LookupResult r(GetIsolate()); | 557 LookupResult r(isolate); |
| 540 result->holder()->LookupRealNamedProperty(name, &r); | 558 result->holder()->LookupRealNamedProperty(*name, &r); |
| 541 if (r.IsProperty()) { | 559 if (r.IsProperty()) { |
| 542 return GetPropertyWithFailedAccessCheck(receiver, | 560 return GetPropertyWithFailedAccessCheck( |
| 543 &r, | 561 object, receiver, &r, name, attributes); |
| 544 name, | |
| 545 attributes); | |
| 546 } | 562 } |
| 547 break; | 563 break; |
| 548 } | 564 } |
| 549 default: | 565 default: |
| 550 UNREACHABLE(); | 566 UNREACHABLE(); |
| 551 } | 567 } |
| 552 } | 568 } |
| 553 | 569 |
| 554 // No accessible property found. | 570 // No accessible property found. |
| 555 *attributes = ABSENT; | 571 *attributes = ABSENT; |
| 556 Heap* heap = name->GetHeap(); | 572 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_GET); |
| 557 Isolate* isolate = heap->isolate(); | 573 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 558 isolate->ReportFailedAccessCheck(this, v8::ACCESS_GET); | 574 return isolate->factory()->undefined_value(); |
| 559 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | |
| 560 return heap->undefined_value(); | |
| 561 } | 575 } |
| 562 | 576 |
| 563 | 577 |
| 564 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck( | 578 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck( |
| 565 Object* receiver, | 579 Object* receiver, |
| 566 LookupResult* result, | 580 LookupResult* result, |
| 567 Name* name, | 581 Name* name, |
| 568 bool continue_search) { | 582 bool continue_search) { |
| 569 if (result->IsProperty()) { | 583 if (result->IsProperty()) { |
| 570 switch (result->type()) { | 584 switch (result->type()) { |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 796 LookupResult* result, | 810 LookupResult* result, |
| 797 Handle<Name> key, | 811 Handle<Name> key, |
| 798 PropertyAttributes* attributes) { | 812 PropertyAttributes* attributes) { |
| 799 Isolate* isolate = result->isolate(); | 813 Isolate* isolate = result->isolate(); |
| 800 CALL_HEAP_FUNCTION_PASS_EXCEPTION( | 814 CALL_HEAP_FUNCTION_PASS_EXCEPTION( |
| 801 isolate, | 815 isolate, |
| 802 object->GetProperty(*receiver, result, *key, attributes)); | 816 object->GetProperty(*receiver, result, *key, attributes)); |
| 803 } | 817 } |
| 804 | 818 |
| 805 | 819 |
| 820 // TODO(yangguo): handlify this and get rid of. |
| 806 MaybeObject* Object::GetProperty(Object* receiver, | 821 MaybeObject* Object::GetProperty(Object* receiver, |
| 807 LookupResult* result, | 822 LookupResult* result, |
| 808 Name* name, | 823 Name* name, |
| 809 PropertyAttributes* attributes) { | 824 PropertyAttributes* attributes) { |
| 810 Isolate* isolate = name->GetIsolate(); | 825 Isolate* isolate = name->GetIsolate(); |
| 811 Heap* heap = isolate->heap(); | 826 Heap* heap = isolate->heap(); |
| 812 | 827 |
| 813 #ifdef DEBUG | 828 #ifdef DEBUG |
| 814 // TODO(mstarzinger): Only because of the AssertNoContextChange, drop as soon | 829 // TODO(mstarzinger): Only because of the AssertNoContextChange, drop as soon |
| 815 // as this method has been fully handlified. | 830 // as this method has been fully handlified. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 834 ASSERT(this != this->GetPrototype(isolate)); | 849 ASSERT(this != this->GetPrototype(isolate)); |
| 835 for (Object* current = this; | 850 for (Object* current = this; |
| 836 true; | 851 true; |
| 837 current = current->GetPrototype(isolate)) { | 852 current = current->GetPrototype(isolate)) { |
| 838 if (current->IsAccessCheckNeeded()) { | 853 if (current->IsAccessCheckNeeded()) { |
| 839 // Check if we're allowed to read from the current object. Note | 854 // Check if we're allowed to read from the current object. Note |
| 840 // that even though we may not actually end up loading the named | 855 // that even though we may not actually end up loading the named |
| 841 // property from the current object, we still check that we have | 856 // property from the current object, we still check that we have |
| 842 // access to it. | 857 // access to it. |
| 843 JSObject* checked = JSObject::cast(current); | 858 JSObject* checked = JSObject::cast(current); |
| 844 if (!heap->isolate()->MayNamedAccess(checked, name, v8::ACCESS_GET)) { | 859 if (!isolate->MayNamedAccess(checked, name, v8::ACCESS_GET)) { |
| 845 return checked->GetPropertyWithFailedAccessCheck(receiver, | 860 HandleScope scope(isolate); |
| 846 result, | 861 Handle<Object> value = JSObject::GetPropertyWithFailedAccessCheck( |
| 847 name, | 862 handle(checked, isolate), |
| 848 attributes); | 863 handle(receiver, isolate), |
| 864 result, |
| 865 handle(name, isolate), |
| 866 attributes); |
| 867 RETURN_IF_EMPTY_HANDLE(isolate, value); |
| 868 return *value; |
| 849 } | 869 } |
| 850 } | 870 } |
| 851 // Stop traversing the chain once we reach the last object in the | 871 // Stop traversing the chain once we reach the last object in the |
| 852 // chain; either the holder of the result or null in case of an | 872 // chain; either the holder of the result or null in case of an |
| 853 // absent property. | 873 // absent property. |
| 854 if (current == last) break; | 874 if (current == last) break; |
| 855 } | 875 } |
| 856 } | 876 } |
| 857 | 877 |
| 858 if (!result->IsProperty()) { | 878 if (!result->IsProperty()) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 869 case FIELD: { | 889 case FIELD: { |
| 870 MaybeObject* maybe_result = result->holder()->FastPropertyAt( | 890 MaybeObject* maybe_result = result->holder()->FastPropertyAt( |
| 871 result->representation(), | 891 result->representation(), |
| 872 result->GetFieldIndex().field_index()); | 892 result->GetFieldIndex().field_index()); |
| 873 if (!maybe_result->To(&value)) return maybe_result; | 893 if (!maybe_result->To(&value)) return maybe_result; |
| 874 ASSERT(!value->IsTheHole() || result->IsReadOnly()); | 894 ASSERT(!value->IsTheHole() || result->IsReadOnly()); |
| 875 return value->IsTheHole() ? heap->undefined_value() : value; | 895 return value->IsTheHole() ? heap->undefined_value() : value; |
| 876 } | 896 } |
| 877 case CONSTANT: | 897 case CONSTANT: |
| 878 return result->GetConstant(); | 898 return result->GetConstant(); |
| 879 case CALLBACKS: | 899 case CALLBACKS: { |
| 880 return result->holder()->GetPropertyWithCallback( | 900 HandleScope scope(isolate); |
| 881 receiver, result->GetCallbackObject(), name); | 901 Handle<Object> value = JSObject::GetPropertyWithCallback( |
| 902 handle(result->holder(), isolate), |
| 903 handle(receiver, isolate), |
| 904 handle(result->GetCallbackObject(), isolate), |
| 905 handle(name, isolate)); |
| 906 RETURN_IF_EMPTY_HANDLE(isolate, value); |
| 907 return *value; |
| 908 } |
| 882 case HANDLER: | 909 case HANDLER: |
| 883 return result->proxy()->GetPropertyWithHandler(receiver, name); | 910 return result->proxy()->GetPropertyWithHandler(receiver, name); |
| 884 case INTERCEPTOR: | 911 case INTERCEPTOR: { |
| 885 return result->holder()->GetPropertyWithInterceptor( | 912 HandleScope scope(isolate); |
| 886 receiver, name, attributes); | 913 Handle<Object> value = JSObject::GetPropertyWithInterceptor( |
| 914 handle(result->holder(), isolate), |
| 915 handle(receiver, isolate), |
| 916 handle(name, isolate), |
| 917 attributes); |
| 918 RETURN_IF_EMPTY_HANDLE(isolate, value); |
| 919 return *value; |
| 920 } |
| 887 case TRANSITION: | 921 case TRANSITION: |
| 888 case NONEXISTENT: | 922 case NONEXISTENT: |
| 889 UNREACHABLE(); | 923 UNREACHABLE(); |
| 890 break; | 924 break; |
| 891 } | 925 } |
| 892 UNREACHABLE(); | 926 UNREACHABLE(); |
| 893 return NULL; | 927 return NULL; |
| 894 } | 928 } |
| 895 | 929 |
| 896 | 930 |
| (...skipping 800 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1697 } | 1731 } |
| 1698 break; | 1732 break; |
| 1699 } | 1733 } |
| 1700 return; | 1734 return; |
| 1701 } | 1735 } |
| 1702 | 1736 |
| 1703 switch (type) { | 1737 switch (type) { |
| 1704 case FIXED_ARRAY_TYPE: | 1738 case FIXED_ARRAY_TYPE: |
| 1705 FixedArray::BodyDescriptor::IterateBody(this, object_size, v); | 1739 FixedArray::BodyDescriptor::IterateBody(this, object_size, v); |
| 1706 break; | 1740 break; |
| 1741 case CONSTANT_POOL_ARRAY_TYPE: |
| 1742 reinterpret_cast<ConstantPoolArray*>(this)->ConstantPoolIterateBody(v); |
| 1743 break; |
| 1707 case FIXED_DOUBLE_ARRAY_TYPE: | 1744 case FIXED_DOUBLE_ARRAY_TYPE: |
| 1708 break; | 1745 break; |
| 1709 case JS_OBJECT_TYPE: | 1746 case JS_OBJECT_TYPE: |
| 1710 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: | 1747 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: |
| 1711 case JS_GENERATOR_OBJECT_TYPE: | 1748 case JS_GENERATOR_OBJECT_TYPE: |
| 1712 case JS_MODULE_TYPE: | 1749 case JS_MODULE_TYPE: |
| 1713 case JS_VALUE_TYPE: | 1750 case JS_VALUE_TYPE: |
| 1714 case JS_DATE_TYPE: | 1751 case JS_DATE_TYPE: |
| 1715 case JS_ARRAY_TYPE: | 1752 case JS_ARRAY_TYPE: |
| 1716 case JS_ARRAY_BUFFER_TYPE: | 1753 case JS_ARRAY_BUFFER_TYPE: |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2093 } else { | 2130 } else { |
| 2094 // Normalize the object to prevent very large instance descriptors. | 2131 // Normalize the object to prevent very large instance descriptors. |
| 2095 // This eliminates unwanted N^2 allocation and lookup behavior. | 2132 // This eliminates unwanted N^2 allocation and lookup behavior. |
| 2096 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 2133 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 2097 AddSlowProperty(object, name, value, attributes); | 2134 AddSlowProperty(object, name, value, attributes); |
| 2098 } | 2135 } |
| 2099 } else { | 2136 } else { |
| 2100 AddSlowProperty(object, name, value, attributes); | 2137 AddSlowProperty(object, name, value, attributes); |
| 2101 } | 2138 } |
| 2102 | 2139 |
| 2103 if (FLAG_harmony_observation && object->map()->is_observed()) { | 2140 if (FLAG_harmony_observation && |
| 2141 object->map()->is_observed() && |
| 2142 *name != isolate->heap()->hidden_string()) { |
| 2104 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 2143 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 2105 EnqueueChangeRecord(object, "new", name, old_value); | 2144 EnqueueChangeRecord(object, "new", name, old_value); |
| 2106 } | 2145 } |
| 2107 | 2146 |
| 2108 return value; | 2147 return value; |
| 2109 } | 2148 } |
| 2110 | 2149 |
| 2111 | 2150 |
| 2112 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, | 2151 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, |
| 2113 const char* type_str, | 2152 const char* type_str, |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2244 elms->set_length(len - to_trim); | 2283 elms->set_length(len - to_trim); |
| 2245 | 2284 |
| 2246 // Maintain marking consistency for IncrementalMarking. | 2285 // Maintain marking consistency for IncrementalMarking. |
| 2247 if (Marking::IsBlack(Marking::MarkBitFrom(elms))) { | 2286 if (Marking::IsBlack(Marking::MarkBitFrom(elms))) { |
| 2248 if (trim_mode == FROM_GC) { | 2287 if (trim_mode == FROM_GC) { |
| 2249 MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta); | 2288 MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta); |
| 2250 } else { | 2289 } else { |
| 2251 MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta); | 2290 MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta); |
| 2252 } | 2291 } |
| 2253 } | 2292 } |
| 2293 |
| 2294 // The array may not be moved during GC, |
| 2295 // and size has to be adjusted nevertheless. |
| 2296 HeapProfiler* profiler = heap->isolate()->heap_profiler(); |
| 2297 if (profiler->is_tracking_allocations()) { |
| 2298 profiler->UpdateObjectSizeEvent(elms->address(), elms->Size()); |
| 2299 } |
| 2254 } | 2300 } |
| 2255 | 2301 |
| 2256 | 2302 |
| 2257 bool Map::InstancesNeedRewriting(Map* target, | 2303 bool Map::InstancesNeedRewriting(Map* target, |
| 2258 int target_number_of_fields, | 2304 int target_number_of_fields, |
| 2259 int target_inobject, | 2305 int target_inobject, |
| 2260 int target_unused) { | 2306 int target_unused) { |
| 2261 // If fields were added (or removed), rewrite the instance. | 2307 // If fields were added (or removed), rewrite the instance. |
| 2262 int number_of_fields = NumberOfFields(); | 2308 int number_of_fields = NumberOfFields(); |
| 2263 ASSERT(target_number_of_fields >= number_of_fields); | 2309 ASSERT(target_number_of_fields >= number_of_fields); |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2381 // size and install the backing store into the object. | 2427 // size and install the backing store into the object. |
| 2382 if (external > 0) { | 2428 if (external > 0) { |
| 2383 RightTrimFixedArray<FROM_MUTATOR>(isolate->heap(), *array, inobject); | 2429 RightTrimFixedArray<FROM_MUTATOR>(isolate->heap(), *array, inobject); |
| 2384 object->set_properties(*array); | 2430 object->set_properties(*array); |
| 2385 } | 2431 } |
| 2386 | 2432 |
| 2387 object->set_map(*new_map); | 2433 object->set_map(*new_map); |
| 2388 } | 2434 } |
| 2389 | 2435 |
| 2390 | 2436 |
| 2437 Handle<TransitionArray> Map::AddTransition(Handle<Map> map, |
| 2438 Handle<Name> key, |
| 2439 Handle<Map> target, |
| 2440 SimpleTransitionFlag flag) { |
| 2441 CALL_HEAP_FUNCTION(map->GetIsolate(), |
| 2442 map->AddTransition(*key, *target, flag), |
| 2443 TransitionArray); |
| 2444 } |
| 2445 |
| 2446 |
| 2391 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, | 2447 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, |
| 2392 int modify_index, | 2448 int modify_index, |
| 2393 Representation new_representation, | 2449 Representation new_representation, |
| 2394 StoreMode store_mode) { | 2450 StoreMode store_mode) { |
| 2395 Handle<Map> new_map = Map::GeneralizeRepresentation( | 2451 Handle<Map> new_map = Map::GeneralizeRepresentation( |
| 2396 handle(object->map()), modify_index, new_representation, store_mode); | 2452 handle(object->map()), modify_index, new_representation, store_mode); |
| 2397 if (object->map() == *new_map) return; | 2453 if (object->map() == *new_map) return; |
| 2398 return MigrateToMap(object, new_map); | 2454 return MigrateToMap(object, new_map); |
| 2399 } | 2455 } |
| 2400 | 2456 |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2681 for (; descriptor < descriptors; descriptor++) { | 2737 for (; descriptor < descriptors; descriptor++) { |
| 2682 new_map = Map::CopyInstallDescriptors(new_map, descriptor, new_descriptors); | 2738 new_map = Map::CopyInstallDescriptors(new_map, descriptor, new_descriptors); |
| 2683 new_map->set_migration_target(true); | 2739 new_map->set_migration_target(true); |
| 2684 } | 2740 } |
| 2685 | 2741 |
| 2686 new_map->set_owns_descriptors(true); | 2742 new_map->set_owns_descriptors(true); |
| 2687 return new_map; | 2743 return new_map; |
| 2688 } | 2744 } |
| 2689 | 2745 |
| 2690 | 2746 |
| 2747 // Generalize the representation of all FIELD descriptors. |
| 2748 Handle<Map> Map::GeneralizeAllFieldRepresentations( |
| 2749 Handle<Map> map, |
| 2750 Representation new_representation) { |
| 2751 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
| 2752 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { |
| 2753 PropertyDetails details = descriptors->GetDetails(i); |
| 2754 if (details.type() == FIELD) { |
| 2755 map = GeneralizeRepresentation(map, i, new_representation, FORCE_FIELD); |
| 2756 } |
| 2757 } |
| 2758 return map; |
| 2759 } |
| 2760 |
| 2761 |
| 2691 Map* Map::CurrentMapForDeprecated() { | 2762 Map* Map::CurrentMapForDeprecated() { |
| 2692 DisallowHeapAllocation no_allocation; | 2763 DisallowHeapAllocation no_allocation; |
| 2693 if (!is_deprecated()) return this; | 2764 if (!is_deprecated()) return this; |
| 2694 | 2765 |
| 2695 DescriptorArray* old_descriptors = instance_descriptors(); | 2766 DescriptorArray* old_descriptors = instance_descriptors(); |
| 2696 | 2767 |
| 2697 int descriptors = NumberOfOwnDescriptors(); | 2768 int descriptors = NumberOfOwnDescriptors(); |
| 2698 Map* root_map = FindRootMap(); | 2769 Map* root_map = FindRootMap(); |
| 2699 | 2770 |
| 2700 // Check the state of the root map. | 2771 // Check the state of the root map. |
| (...skipping 1263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3964 Handle<Object> error = isolate->factory()->NewTypeError( | 4035 Handle<Object> error = isolate->factory()->NewTypeError( |
| 3965 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); | 4036 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); |
| 3966 isolate->Throw(*error); | 4037 isolate->Throw(*error); |
| 3967 return Handle<Object>(); | 4038 return Handle<Object>(); |
| 3968 } else { | 4039 } else { |
| 3969 return value; | 4040 return value; |
| 3970 } | 4041 } |
| 3971 } | 4042 } |
| 3972 | 4043 |
| 3973 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 4044 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 3974 if (FLAG_harmony_observation && | 4045 bool is_observed = FLAG_harmony_observation && |
| 3975 object->map()->is_observed() && lookup->IsDataProperty()) { | 4046 object->map()->is_observed() && |
| 4047 *name != isolate->heap()->hidden_string(); |
| 4048 if (is_observed && lookup->IsDataProperty()) { |
| 3976 old_value = Object::GetProperty(object, name); | 4049 old_value = Object::GetProperty(object, name); |
| 3977 } | 4050 } |
| 3978 | 4051 |
| 3979 // This is a real property that is not read-only, or it is a | 4052 // This is a real property that is not read-only, or it is a |
| 3980 // transition or null descriptor and there are no setters in the prototypes. | 4053 // transition or null descriptor and there are no setters in the prototypes. |
| 3981 Handle<Object> result = value; | 4054 Handle<Object> result = value; |
| 3982 switch (lookup->type()) { | 4055 switch (lookup->type()) { |
| 3983 case NORMAL: | 4056 case NORMAL: |
| 3984 SetNormalizedProperty(handle(lookup->holder()), lookup, value); | 4057 SetNormalizedProperty(handle(lookup->holder()), lookup, value); |
| 3985 break; | 4058 break; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4004 result = SetPropertyUsingTransition(handle(lookup->holder()), lookup, | 4077 result = SetPropertyUsingTransition(handle(lookup->holder()), lookup, |
| 4005 name, value, attributes); | 4078 name, value, attributes); |
| 4006 break; | 4079 break; |
| 4007 case HANDLER: | 4080 case HANDLER: |
| 4008 case NONEXISTENT: | 4081 case NONEXISTENT: |
| 4009 UNREACHABLE(); | 4082 UNREACHABLE(); |
| 4010 } | 4083 } |
| 4011 | 4084 |
| 4012 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>()); | 4085 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>()); |
| 4013 | 4086 |
| 4014 if (FLAG_harmony_observation && object->map()->is_observed()) { | 4087 if (is_observed) { |
| 4015 if (lookup->IsTransition()) { | 4088 if (lookup->IsTransition()) { |
| 4016 EnqueueChangeRecord(object, "new", name, old_value); | 4089 EnqueueChangeRecord(object, "new", name, old_value); |
| 4017 } else { | 4090 } else { |
| 4018 LookupResult new_lookup(isolate); | 4091 LookupResult new_lookup(isolate); |
| 4019 object->LocalLookup(*name, &new_lookup, true); | 4092 object->LocalLookup(*name, &new_lookup, true); |
| 4020 if (new_lookup.IsDataProperty()) { | 4093 if (new_lookup.IsDataProperty()) { |
| 4021 Handle<Object> new_value = Object::GetProperty(object, name); | 4094 Handle<Object> new_value = Object::GetProperty(object, name); |
| 4022 if (!new_value->SameValue(*old_value)) { | 4095 if (!new_value->SameValue(*old_value)) { |
| 4023 EnqueueChangeRecord(object, "updated", name, old_value); | 4096 EnqueueChangeRecord(object, "updated", name, old_value); |
| 4024 } | 4097 } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4105 | 4178 |
| 4106 // Check for accessor in prototype chain removed here in clone. | 4179 // Check for accessor in prototype chain removed here in clone. |
| 4107 if (!lookup.IsFound()) { | 4180 if (!lookup.IsFound()) { |
| 4108 // Neither properties nor transitions found. | 4181 // Neither properties nor transitions found. |
| 4109 return AddProperty(object, name, value, attributes, kNonStrictMode, | 4182 return AddProperty(object, name, value, attributes, kNonStrictMode, |
| 4110 MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode); | 4183 MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode); |
| 4111 } | 4184 } |
| 4112 | 4185 |
| 4113 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 4186 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 4114 PropertyAttributes old_attributes = ABSENT; | 4187 PropertyAttributes old_attributes = ABSENT; |
| 4115 bool is_observed = FLAG_harmony_observation && object->map()->is_observed(); | 4188 bool is_observed = FLAG_harmony_observation && |
| 4189 object->map()->is_observed() && |
| 4190 *name != isolate->heap()->hidden_string(); |
| 4116 if (is_observed && lookup.IsProperty()) { | 4191 if (is_observed && lookup.IsProperty()) { |
| 4117 if (lookup.IsDataProperty()) old_value = | 4192 if (lookup.IsDataProperty()) old_value = |
| 4118 Object::GetProperty(object, name); | 4193 Object::GetProperty(object, name); |
| 4119 old_attributes = lookup.GetAttributes(); | 4194 old_attributes = lookup.GetAttributes(); |
| 4120 } | 4195 } |
| 4121 | 4196 |
| 4122 // Check of IsReadOnly removed from here in clone. | 4197 // Check of IsReadOnly removed from here in clone. |
| 4123 switch (lookup.type()) { | 4198 switch (lookup.type()) { |
| 4124 case NORMAL: | 4199 case NORMAL: |
| 4125 ReplaceSlowProperty(object, name, value, attributes); | 4200 ReplaceSlowProperty(object, name, value, attributes); |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4391 } | 4466 } |
| 4392 if (pt->IsNull()) return ABSENT; | 4467 if (pt->IsNull()) return ABSENT; |
| 4393 return JSObject::cast(pt)->GetElementAttributeWithReceiver( | 4468 return JSObject::cast(pt)->GetElementAttributeWithReceiver( |
| 4394 receiver, index, true); | 4469 receiver, index, true); |
| 4395 } | 4470 } |
| 4396 | 4471 |
| 4397 | 4472 |
| 4398 Handle<Map> NormalizedMapCache::Get(Handle<NormalizedMapCache> cache, | 4473 Handle<Map> NormalizedMapCache::Get(Handle<NormalizedMapCache> cache, |
| 4399 Handle<JSObject> obj, | 4474 Handle<JSObject> obj, |
| 4400 PropertyNormalizationMode mode) { | 4475 PropertyNormalizationMode mode) { |
| 4401 Map* fast = obj->map(); | 4476 int index = obj->map()->Hash() % kEntries; |
| 4402 int index = fast->Hash() % kEntries; | 4477 Handle<Object> result = handle(cache->get(index), cache->GetIsolate()); |
| 4403 Object* result = cache->get(index); | |
| 4404 if (result->IsMap() && | 4478 if (result->IsMap() && |
| 4405 Map::cast(result)->EquivalentToForNormalization(fast, mode)) { | 4479 Handle<Map>::cast(result)->EquivalentToForNormalization(obj->map(), |
| 4480 mode)) { |
| 4406 #ifdef VERIFY_HEAP | 4481 #ifdef VERIFY_HEAP |
| 4407 if (FLAG_verify_heap) { | 4482 if (FLAG_verify_heap) { |
| 4408 Map::cast(result)->SharedMapVerify(); | 4483 Handle<Map>::cast(result)->SharedMapVerify(); |
| 4409 } | 4484 } |
| 4410 #endif | 4485 #endif |
| 4411 #ifdef DEBUG | 4486 #ifdef DEBUG |
| 4412 if (FLAG_enable_slow_asserts) { | 4487 if (FLAG_enable_slow_asserts) { |
| 4413 // The cached map should match newly created normalized map bit-by-bit, | 4488 // The cached map should match newly created normalized map bit-by-bit, |
| 4414 // except for the code cache, which can contain some ics which can be | 4489 // except for the code cache, which can contain some ics which can be |
| 4415 // applied to the shared map. | 4490 // applied to the shared map. |
| 4416 Object* fresh; | 4491 Handle<Map> fresh = Map::CopyNormalized(handle(obj->map()), mode, |
| 4417 MaybeObject* maybe_fresh = | 4492 SHARED_NORMALIZED_MAP); |
| 4418 fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP); | 4493 |
| 4419 if (maybe_fresh->ToObject(&fresh)) { | 4494 ASSERT(memcmp(fresh->address(), |
| 4420 ASSERT(memcmp(Map::cast(fresh)->address(), | 4495 Handle<Map>::cast(result)->address(), |
| 4421 Map::cast(result)->address(), | 4496 Map::kCodeCacheOffset) == 0); |
| 4422 Map::kCodeCacheOffset) == 0); | 4497 STATIC_ASSERT(Map::kDependentCodeOffset == |
| 4423 STATIC_ASSERT(Map::kDependentCodeOffset == | 4498 Map::kCodeCacheOffset + kPointerSize); |
| 4424 Map::kCodeCacheOffset + kPointerSize); | 4499 int offset = Map::kDependentCodeOffset + kPointerSize; |
| 4425 int offset = Map::kDependentCodeOffset + kPointerSize; | 4500 ASSERT(memcmp(fresh->address() + offset, |
| 4426 ASSERT(memcmp(Map::cast(fresh)->address() + offset, | 4501 Handle<Map>::cast(result)->address() + offset, |
| 4427 Map::cast(result)->address() + offset, | 4502 Map::kSize - offset) == 0); |
| 4428 Map::kSize - offset) == 0); | |
| 4429 } | |
| 4430 } | 4503 } |
| 4431 #endif | 4504 #endif |
| 4432 return handle(Map::cast(result)); | 4505 return Handle<Map>::cast(result); |
| 4433 } | 4506 } |
| 4434 | 4507 |
| 4435 Isolate* isolate = cache->GetIsolate(); | 4508 Isolate* isolate = cache->GetIsolate(); |
| 4436 Handle<Map> map = Map::CopyNormalized(handle(fast), mode, | 4509 Handle<Map> map = Map::CopyNormalized(handle(obj->map()), mode, |
| 4437 SHARED_NORMALIZED_MAP); | 4510 SHARED_NORMALIZED_MAP); |
| 4438 ASSERT(map->is_dictionary_map()); | 4511 ASSERT(map->is_dictionary_map()); |
| 4439 cache->set(index, *map); | 4512 cache->set(index, *map); |
| 4440 isolate->counters()->normalized_maps()->Increment(); | 4513 isolate->counters()->normalized_maps()->Increment(); |
| 4441 | 4514 |
| 4442 return map; | 4515 return map; |
| 4443 } | 4516 } |
| 4444 | 4517 |
| 4445 | 4518 |
| 4446 void NormalizedMapCache::Clear() { | 4519 void NormalizedMapCache::Clear() { |
| (...skipping 722 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5169 Handle<Object> args[2] = { name, object }; | 5242 Handle<Object> args[2] = { name, object }; |
| 5170 Handle<Object> error = isolate->factory()->NewTypeError( | 5243 Handle<Object> error = isolate->factory()->NewTypeError( |
| 5171 "strict_delete_property", HandleVector(args, ARRAY_SIZE(args))); | 5244 "strict_delete_property", HandleVector(args, ARRAY_SIZE(args))); |
| 5172 isolate->Throw(*error); | 5245 isolate->Throw(*error); |
| 5173 return Handle<Object>(); | 5246 return Handle<Object>(); |
| 5174 } | 5247 } |
| 5175 return isolate->factory()->false_value(); | 5248 return isolate->factory()->false_value(); |
| 5176 } | 5249 } |
| 5177 | 5250 |
| 5178 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 5251 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 5179 bool is_observed = FLAG_harmony_observation && object->map()->is_observed(); | 5252 bool is_observed = FLAG_harmony_observation && |
| 5253 object->map()->is_observed() && |
| 5254 *name != isolate->heap()->hidden_string(); |
| 5180 if (is_observed && lookup.IsDataProperty()) { | 5255 if (is_observed && lookup.IsDataProperty()) { |
| 5181 old_value = Object::GetProperty(object, name); | 5256 old_value = Object::GetProperty(object, name); |
| 5182 } | 5257 } |
| 5183 Handle<Object> result; | 5258 Handle<Object> result; |
| 5184 | 5259 |
| 5185 // Check for interceptor. | 5260 // Check for interceptor. |
| 5186 if (lookup.IsInterceptor()) { | 5261 if (lookup.IsInterceptor()) { |
| 5187 // Skip interceptor if forcing a deletion. | 5262 // Skip interceptor if forcing a deletion. |
| 5188 if (mode == FORCE_DELETION) { | 5263 if (mode == FORCE_DELETION) { |
| 5189 result = DeletePropertyPostInterceptor(object, name, mode); | 5264 result = DeletePropertyPostInterceptor(object, name, mode); |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5531 // Make sure we never go back to the fast case | 5606 // Make sure we never go back to the fast case |
| 5532 dictionary->set_requires_slow_elements(); | 5607 dictionary->set_requires_slow_elements(); |
| 5533 // Freeze all elements in the dictionary | 5608 // Freeze all elements in the dictionary |
| 5534 FreezeDictionary(dictionary); | 5609 FreezeDictionary(dictionary); |
| 5535 } | 5610 } |
| 5536 | 5611 |
| 5537 return object; | 5612 return object; |
| 5538 } | 5613 } |
| 5539 | 5614 |
| 5540 | 5615 |
| 5541 MUST_USE_RESULT MaybeObject* JSObject::SetObserved(Isolate* isolate) { | 5616 void JSObject::SetObserved(Handle<JSObject> object) { |
| 5542 if (map()->is_observed()) | 5617 Isolate* isolate = object->GetIsolate(); |
| 5543 return isolate->heap()->undefined_value(); | |
| 5544 | 5618 |
| 5545 Heap* heap = isolate->heap(); | 5619 if (object->map()->is_observed()) |
| 5620 return; |
| 5546 | 5621 |
| 5547 if (!HasExternalArrayElements()) { | 5622 if (!object->HasExternalArrayElements()) { |
| 5548 // Go to dictionary mode, so that we don't skip map checks. | 5623 // Go to dictionary mode, so that we don't skip map checks. |
| 5549 MaybeObject* maybe = NormalizeElements(); | 5624 NormalizeElements(object); |
| 5550 if (maybe->IsFailure()) return maybe; | 5625 ASSERT(!object->HasFastElements()); |
| 5551 ASSERT(!HasFastElements()); | |
| 5552 } | 5626 } |
| 5553 | 5627 |
| 5554 LookupResult result(isolate); | 5628 LookupResult result(isolate); |
| 5555 map()->LookupTransition(this, heap->observed_symbol(), &result); | 5629 object->map()->LookupTransition(*object, |
| 5630 isolate->heap()->observed_symbol(), |
| 5631 &result); |
| 5556 | 5632 |
| 5557 Map* new_map; | 5633 Handle<Map> new_map; |
| 5558 if (result.IsTransition()) { | 5634 if (result.IsTransition()) { |
| 5559 new_map = result.GetTransitionTarget(); | 5635 new_map = handle(result.GetTransitionTarget()); |
| 5560 ASSERT(new_map->is_observed()); | 5636 ASSERT(new_map->is_observed()); |
| 5561 } else if (map()->CanHaveMoreTransitions()) { | 5637 } else if (object->map()->CanHaveMoreTransitions()) { |
| 5562 MaybeObject* maybe_new_map = map()->CopyForObserved(); | 5638 new_map = Map::CopyForObserved(handle(object->map())); |
| 5563 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
| 5564 } else { | 5639 } else { |
| 5565 MaybeObject* maybe_copy = map()->Copy(); | 5640 new_map = Map::Copy(handle(object->map())); |
| 5566 if (!maybe_copy->To(&new_map)) return maybe_copy; | |
| 5567 new_map->set_is_observed(true); | 5641 new_map->set_is_observed(true); |
| 5568 } | 5642 } |
| 5569 set_map(new_map); | 5643 object->set_map(*new_map); |
| 5570 | |
| 5571 return heap->undefined_value(); | |
| 5572 } | 5644 } |
| 5573 | 5645 |
| 5574 | 5646 |
| 5647 Handle<JSObject> JSObject::Copy(Handle<JSObject> object, |
| 5648 Handle<AllocationSite> site) { |
| 5649 Isolate* isolate = object->GetIsolate(); |
| 5650 CALL_HEAP_FUNCTION(isolate, |
| 5651 isolate->heap()->CopyJSObject(*object, *site), JSObject); |
| 5652 } |
| 5653 |
| 5654 |
| 5575 Handle<JSObject> JSObject::Copy(Handle<JSObject> object) { | 5655 Handle<JSObject> JSObject::Copy(Handle<JSObject> object) { |
| 5576 Isolate* isolate = object->GetIsolate(); | 5656 Isolate* isolate = object->GetIsolate(); |
| 5577 CALL_HEAP_FUNCTION(isolate, | 5657 CALL_HEAP_FUNCTION(isolate, |
| 5578 isolate->heap()->CopyJSObject(*object), JSObject); | 5658 isolate->heap()->CopyJSObject(*object), JSObject); |
| 5579 } | 5659 } |
| 5580 | 5660 |
| 5581 | 5661 |
| 5582 class JSObjectWalkVisitor { | 5662 class JSObjectWalkVisitor { |
| 5583 public: | 5663 public: |
| 5584 explicit JSObjectWalkVisitor() {} | 5664 explicit JSObjectWalkVisitor(AllocationSiteContext* site_context) : |
| 5665 site_context_(site_context) {} |
| 5585 virtual ~JSObjectWalkVisitor() {} | 5666 virtual ~JSObjectWalkVisitor() {} |
| 5586 | 5667 |
| 5587 Handle<JSObject> Visit(Handle<JSObject> object) { | 5668 Handle<JSObject> Visit(Handle<JSObject> object) { |
| 5588 return StructureWalk(object); | 5669 return StructureWalk(object); |
| 5589 } | 5670 } |
| 5590 | 5671 |
| 5591 // Returns true if the visitor is a copying visitor. | |
| 5592 virtual bool is_copying() = 0; | 5672 virtual bool is_copying() = 0; |
| 5593 | 5673 |
| 5594 protected: | 5674 protected: |
| 5595 Handle<JSObject> StructureWalk(Handle<JSObject> object); | 5675 Handle<JSObject> StructureWalk(Handle<JSObject> object); |
| 5596 | 5676 |
| 5597 // The returned handle should point to a new object if the visitor is a | 5677 // The returned handle will be used for the object in all subsequent usages. |
| 5598 // copying visitor, otherwise it should be the same as the input object. | 5678 // This allows VisitObject to make a copy of the object if desired. |
| 5599 virtual Handle<JSObject> VisitObject(Handle<JSObject> object) = 0; | 5679 virtual Handle<JSObject> VisitObject(Handle<JSObject> object) = 0; |
| 5600 | |
| 5601 // The returned handle should point to a new value if the visitor is a | |
| 5602 // copying visitor, otherwise it should be the same as the input value. | |
| 5603 virtual Handle<JSObject> VisitElementOrProperty(Handle<JSObject> object, | 5680 virtual Handle<JSObject> VisitElementOrProperty(Handle<JSObject> object, |
| 5604 Handle<JSObject> value) = 0; | 5681 Handle<JSObject> value) = 0; |
| 5682 |
| 5683 AllocationSiteContext* site_context() { return site_context_; } |
| 5684 |
| 5685 private: |
| 5686 AllocationSiteContext* site_context_; |
| 5605 }; | 5687 }; |
| 5606 | 5688 |
| 5607 | 5689 |
| 5608 class JSObjectCopyVisitor: public JSObjectWalkVisitor { | 5690 class JSObjectCopyVisitor: public JSObjectWalkVisitor { |
| 5609 public: | 5691 public: |
| 5610 explicit JSObjectCopyVisitor() {} | 5692 explicit JSObjectCopyVisitor(AllocationSiteContext* site_context) |
| 5693 : JSObjectWalkVisitor(site_context) {} |
| 5611 | 5694 |
| 5612 virtual bool is_copying() V8_OVERRIDE { return true; } | 5695 virtual bool is_copying() V8_OVERRIDE { return true; } |
| 5613 | 5696 |
| 5614 protected: | 5697 // The returned handle will be used for the object in all |
| 5698 // subsequent usages. This allows VisitObject to make a copy |
| 5699 // of the object if desired. |
| 5615 virtual Handle<JSObject> VisitObject(Handle<JSObject> object) V8_OVERRIDE { | 5700 virtual Handle<JSObject> VisitObject(Handle<JSObject> object) V8_OVERRIDE { |
| 5616 return JSObject::Copy(object); | 5701 // Only create a memento if |
| 5702 // 1) we have a JSArray, and |
| 5703 // 2) the elements kind is palatable |
| 5704 // 3) allow_mementos is true |
| 5705 Handle<JSObject> copy; |
| 5706 if (site_context()->activated() && |
| 5707 AllocationSite::CanTrack(object->map()->instance_type()) && |
| 5708 AllocationSite::GetMode(object->GetElementsKind()) == |
| 5709 TRACK_ALLOCATION_SITE) { |
| 5710 copy = JSObject::Copy(object, site_context()->current()); |
| 5711 } else { |
| 5712 copy = JSObject::Copy(object); |
| 5713 } |
| 5714 |
| 5715 return copy; |
| 5617 } | 5716 } |
| 5618 | 5717 |
| 5619 virtual Handle<JSObject> VisitElementOrProperty( | 5718 virtual Handle<JSObject> VisitElementOrProperty( |
| 5620 Handle<JSObject> object, | 5719 Handle<JSObject> object, |
| 5621 Handle<JSObject> value) V8_OVERRIDE { | 5720 Handle<JSObject> value) V8_OVERRIDE { |
| 5622 return StructureWalk(value); | 5721 Handle<AllocationSite> current_site = site_context()->EnterNewScope(); |
| 5722 Handle<JSObject> copy_of_value = StructureWalk(value); |
| 5723 site_context()->ExitScope(current_site, value); |
| 5724 return copy_of_value; |
| 5623 } | 5725 } |
| 5624 }; | 5726 }; |
| 5625 | 5727 |
| 5728 |
| 5729 class JSObjectCreateAllocationSitesVisitor: public JSObjectWalkVisitor { |
| 5730 public: |
| 5731 explicit JSObjectCreateAllocationSitesVisitor( |
| 5732 AllocationSiteContext* site_context) |
| 5733 : JSObjectWalkVisitor(site_context) {} |
| 5734 |
| 5735 virtual bool is_copying() V8_OVERRIDE { return false; } |
| 5736 |
| 5737 // The returned handle will be used for the object in all |
| 5738 // subsequent usages. This allows VisitObject to make a copy |
| 5739 // of the object if desired. |
| 5740 virtual Handle<JSObject> VisitObject(Handle<JSObject> object) V8_OVERRIDE { |
| 5741 return object; |
| 5742 } |
| 5743 |
| 5744 virtual Handle<JSObject> VisitElementOrProperty( |
| 5745 Handle<JSObject> object, |
| 5746 Handle<JSObject> value) V8_OVERRIDE { |
| 5747 Handle<AllocationSite> current_site = site_context()->EnterNewScope(); |
| 5748 value = StructureWalk(value); |
| 5749 site_context()->ExitScope(current_site, value); |
| 5750 return value; |
| 5751 } |
| 5752 }; |
| 5753 |
| 5626 | 5754 |
| 5627 Handle<JSObject> JSObjectWalkVisitor::StructureWalk(Handle<JSObject> object) { | 5755 Handle<JSObject> JSObjectWalkVisitor::StructureWalk(Handle<JSObject> object) { |
| 5628 bool copying = is_copying(); | 5756 bool copying = is_copying(); |
| 5629 Isolate* isolate = object->GetIsolate(); | 5757 Isolate* isolate = object->GetIsolate(); |
| 5630 StackLimitCheck check(isolate); | 5758 StackLimitCheck check(isolate); |
| 5631 if (check.HasOverflowed()) { | 5759 if (check.HasOverflowed()) { |
| 5632 isolate->StackOverflow(); | 5760 isolate->StackOverflow(); |
| 5633 return Handle<JSObject>::null(); | 5761 return Handle<JSObject>::null(); |
| 5634 } | 5762 } |
| 5635 | 5763 |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5759 case EXTERNAL_DOUBLE_ELEMENTS: | 5887 case EXTERNAL_DOUBLE_ELEMENTS: |
| 5760 case FAST_DOUBLE_ELEMENTS: | 5888 case FAST_DOUBLE_ELEMENTS: |
| 5761 case FAST_HOLEY_DOUBLE_ELEMENTS: | 5889 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 5762 // No contained objects, nothing to do. | 5890 // No contained objects, nothing to do. |
| 5763 break; | 5891 break; |
| 5764 } | 5892 } |
| 5765 return copy; | 5893 return copy; |
| 5766 } | 5894 } |
| 5767 | 5895 |
| 5768 | 5896 |
| 5769 Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object) { | 5897 Handle<JSObject> JSObject::DeepWalk(Handle<JSObject> object, |
| 5770 JSObjectCopyVisitor v; | 5898 AllocationSiteContext* site_context) { |
| 5899 JSObjectCreateAllocationSitesVisitor v(site_context); |
| 5900 Handle<JSObject> result = v.Visit(object); |
| 5901 ASSERT(!v.is_copying() && |
| 5902 (result.is_null() || result.is_identical_to(object))); |
| 5903 return result; |
| 5904 } |
| 5905 |
| 5906 |
| 5907 Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object, |
| 5908 AllocationSiteContext* site_context) { |
| 5909 JSObjectCopyVisitor v(site_context); |
| 5771 Handle<JSObject> copy = v.Visit(object); | 5910 Handle<JSObject> copy = v.Visit(object); |
| 5772 ASSERT(v.is_copying() && !copy.is_identical_to(object)); | 5911 ASSERT(v.is_copying() && !copy.is_identical_to(object)); |
| 5773 return copy; | 5912 return copy; |
| 5774 } | 5913 } |
| 5775 | 5914 |
| 5776 | 5915 |
| 5777 // Tests for the fast common case for property enumeration: | 5916 // Tests for the fast common case for property enumeration: |
| 5778 // - This object and all prototypes has an enum cache (which means that | 5917 // - This object and all prototypes has an enum cache (which means that |
| 5779 // it is no proxy, has no interceptors and needs no access checks). | 5918 // it is no proxy, has no interceptors and needs no access checks). |
| 5780 // - This object has no elements. | 5919 // - This object has no elements. |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6177 | 6316 |
| 6178 // Try to flatten before operating on the string. | 6317 // Try to flatten before operating on the string. |
| 6179 if (name->IsString()) String::cast(*name)->TryFlatten(); | 6318 if (name->IsString()) String::cast(*name)->TryFlatten(); |
| 6180 | 6319 |
| 6181 if (!object->CanSetCallback(*name)) return; | 6320 if (!object->CanSetCallback(*name)) return; |
| 6182 | 6321 |
| 6183 uint32_t index = 0; | 6322 uint32_t index = 0; |
| 6184 bool is_element = name->AsArrayIndex(&index); | 6323 bool is_element = name->AsArrayIndex(&index); |
| 6185 | 6324 |
| 6186 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 6325 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 6187 bool is_observed = FLAG_harmony_observation && object->map()->is_observed(); | 6326 bool is_observed = FLAG_harmony_observation && |
| 6327 object->map()->is_observed() && |
| 6328 *name != isolate->heap()->hidden_string(); |
| 6188 bool preexists = false; | 6329 bool preexists = false; |
| 6189 if (is_observed) { | 6330 if (is_observed) { |
| 6190 if (is_element) { | 6331 if (is_element) { |
| 6191 preexists = HasLocalElement(object, index); | 6332 preexists = HasLocalElement(object, index); |
| 6192 if (preexists && object->GetLocalElementAccessorPair(index) == NULL) { | 6333 if (preexists && object->GetLocalElementAccessorPair(index) == NULL) { |
| 6193 old_value = Object::GetElement(isolate, object, index); | 6334 old_value = Object::GetElement(isolate, object, index); |
| 6194 } | 6335 } |
| 6195 } else { | 6336 } else { |
| 6196 LookupResult lookup(isolate); | 6337 LookupResult lookup(isolate); |
| 6197 object->LocalLookup(*name, &lookup, true); | 6338 object->LocalLookup(*name, &lookup, true); |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6432 !isolate->MayNamedAccess(*object, *name, v8::ACCESS_HAS)) { | 6573 !isolate->MayNamedAccess(*object, *name, v8::ACCESS_HAS)) { |
| 6433 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_HAS); | 6574 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_HAS); |
| 6434 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); | 6575 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 6435 return isolate->factory()->undefined_value(); | 6576 return isolate->factory()->undefined_value(); |
| 6436 } | 6577 } |
| 6437 | 6578 |
| 6438 // Make the lookup and include prototypes. | 6579 // Make the lookup and include prototypes. |
| 6439 uint32_t index = 0; | 6580 uint32_t index = 0; |
| 6440 if (name->AsArrayIndex(&index)) { | 6581 if (name->AsArrayIndex(&index)) { |
| 6441 for (Handle<Object> obj = object; | 6582 for (Handle<Object> obj = object; |
| 6442 *obj != isolate->heap()->null_value(); | 6583 !obj->IsNull(); |
| 6443 obj = handle(JSReceiver::cast(*obj)->GetPrototype(), isolate)) { | 6584 obj = handle(JSReceiver::cast(*obj)->GetPrototype(), isolate)) { |
| 6444 if (obj->IsJSObject() && JSObject::cast(*obj)->HasDictionaryElements()) { | 6585 if (obj->IsJSObject() && JSObject::cast(*obj)->HasDictionaryElements()) { |
| 6445 JSObject* js_object = JSObject::cast(*obj); | 6586 JSObject* js_object = JSObject::cast(*obj); |
| 6446 SeededNumberDictionary* dictionary = js_object->element_dictionary(); | 6587 SeededNumberDictionary* dictionary = js_object->element_dictionary(); |
| 6447 int entry = dictionary->FindEntry(index); | 6588 int entry = dictionary->FindEntry(index); |
| 6448 if (entry != SeededNumberDictionary::kNotFound) { | 6589 if (entry != SeededNumberDictionary::kNotFound) { |
| 6449 Object* element = dictionary->ValueAt(entry); | 6590 Object* element = dictionary->ValueAt(entry); |
| 6450 if (dictionary->DetailsAt(entry).type() == CALLBACKS && | 6591 if (dictionary->DetailsAt(entry).type() == CALLBACKS && |
| 6451 element->IsAccessorPair()) { | 6592 element->IsAccessorPair()) { |
| 6452 return handle(AccessorPair::cast(element)->GetComponent(component), | 6593 return handle(AccessorPair::cast(element)->GetComponent(component), |
| 6453 isolate); | 6594 isolate); |
| 6454 } | 6595 } |
| 6455 } | 6596 } |
| 6456 } | 6597 } |
| 6457 } | 6598 } |
| 6458 } else { | 6599 } else { |
| 6459 for (Handle<Object> obj = object; | 6600 for (Handle<Object> obj = object; |
| 6460 *obj != isolate->heap()->null_value(); | 6601 !obj->IsNull(); |
| 6461 obj = handle(JSReceiver::cast(*obj)->GetPrototype(), isolate)) { | 6602 obj = handle(JSReceiver::cast(*obj)->GetPrototype(), isolate)) { |
| 6462 LookupResult result(isolate); | 6603 LookupResult result(isolate); |
| 6463 JSReceiver::cast(*obj)->LocalLookup(*name, &result); | 6604 JSReceiver::cast(*obj)->LocalLookup(*name, &result); |
| 6464 if (result.IsFound()) { | 6605 if (result.IsFound()) { |
| 6465 if (result.IsReadOnly()) return isolate->factory()->undefined_value(); | 6606 if (result.IsReadOnly()) return isolate->factory()->undefined_value(); |
| 6466 if (result.IsPropertyCallbacks()) { | 6607 if (result.IsPropertyCallbacks()) { |
| 6467 Object* obj = result.GetCallbackObject(); | 6608 Object* obj = result.GetCallbackObject(); |
| 6468 if (obj->IsAccessorPair()) { | 6609 if (obj->IsAccessorPair()) { |
| 6469 return handle(AccessorPair::cast(obj)->GetComponent(component), | 6610 return handle(AccessorPair::cast(obj)->GetComponent(component), |
| 6470 isolate); | 6611 isolate); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 6499 } | 6640 } |
| 6500 } | 6641 } |
| 6501 } | 6642 } |
| 6502 return GetHeap()->undefined_value(); | 6643 return GetHeap()->undefined_value(); |
| 6503 } else { | 6644 } else { |
| 6504 return property_dictionary()->SlowReverseLookup(value); | 6645 return property_dictionary()->SlowReverseLookup(value); |
| 6505 } | 6646 } |
| 6506 } | 6647 } |
| 6507 | 6648 |
| 6508 | 6649 |
| 6650 Handle<Map> Map::RawCopy(Handle<Map> map, |
| 6651 int instance_size) { |
| 6652 CALL_HEAP_FUNCTION(map->GetIsolate(), |
| 6653 map->RawCopy(instance_size), |
| 6654 Map); |
| 6655 } |
| 6656 |
| 6657 |
| 6509 MaybeObject* Map::RawCopy(int instance_size) { | 6658 MaybeObject* Map::RawCopy(int instance_size) { |
| 6510 Map* result; | 6659 Map* result; |
| 6511 MaybeObject* maybe_result = | 6660 MaybeObject* maybe_result = |
| 6512 GetHeap()->AllocateMap(instance_type(), instance_size); | 6661 GetHeap()->AllocateMap(instance_type(), instance_size); |
| 6513 if (!maybe_result->To(&result)) return maybe_result; | 6662 if (!maybe_result->To(&result)) return maybe_result; |
| 6514 | 6663 |
| 6515 result->set_prototype(prototype()); | 6664 result->set_prototype(prototype()); |
| 6516 result->set_constructor(constructor()); | 6665 result->set_constructor(constructor()); |
| 6517 result->set_bit_field(bit_field()); | 6666 result->set_bit_field(bit_field()); |
| 6518 result->set_bit_field2(bit_field2()); | 6667 result->set_bit_field2(bit_field2()); |
| 6519 int new_bit_field3 = bit_field3(); | 6668 int new_bit_field3 = bit_field3(); |
| 6520 new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true); | 6669 new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true); |
| 6521 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0); | 6670 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0); |
| 6522 new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache); | 6671 new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache); |
| 6523 new_bit_field3 = Deprecated::update(new_bit_field3, false); | 6672 new_bit_field3 = Deprecated::update(new_bit_field3, false); |
| 6524 new_bit_field3 = IsUnstable::update(new_bit_field3, false); | 6673 new_bit_field3 = IsUnstable::update(new_bit_field3, false); |
| 6525 result->set_bit_field3(new_bit_field3); | 6674 result->set_bit_field3(new_bit_field3); |
| 6526 return result; | 6675 return result; |
| 6527 } | 6676 } |
| 6528 | 6677 |
| 6529 | 6678 |
| 6530 Handle<Map> Map::CopyNormalized(Handle<Map> map, | 6679 Handle<Map> Map::CopyNormalized(Handle<Map> map, |
| 6531 PropertyNormalizationMode mode, | 6680 PropertyNormalizationMode mode, |
| 6532 NormalizedMapSharingMode sharing) { | 6681 NormalizedMapSharingMode sharing) { |
| 6533 CALL_HEAP_FUNCTION(map->GetIsolate(), | 6682 int new_instance_size = map->instance_size(); |
| 6534 map->CopyNormalized(mode, sharing), | |
| 6535 Map); | |
| 6536 } | |
| 6537 | |
| 6538 | |
| 6539 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, | |
| 6540 NormalizedMapSharingMode sharing) { | |
| 6541 int new_instance_size = instance_size(); | |
| 6542 if (mode == CLEAR_INOBJECT_PROPERTIES) { | 6683 if (mode == CLEAR_INOBJECT_PROPERTIES) { |
| 6543 new_instance_size -= inobject_properties() * kPointerSize; | 6684 new_instance_size -= map->inobject_properties() * kPointerSize; |
| 6544 } | 6685 } |
| 6545 | 6686 |
| 6546 Map* result; | 6687 Handle<Map> result = Map::RawCopy(map, new_instance_size); |
| 6547 MaybeObject* maybe_result = RawCopy(new_instance_size); | |
| 6548 if (!maybe_result->To(&result)) return maybe_result; | |
| 6549 | 6688 |
| 6550 if (mode != CLEAR_INOBJECT_PROPERTIES) { | 6689 if (mode != CLEAR_INOBJECT_PROPERTIES) { |
| 6551 result->set_inobject_properties(inobject_properties()); | 6690 result->set_inobject_properties(map->inobject_properties()); |
| 6552 } | 6691 } |
| 6553 | 6692 |
| 6554 result->set_is_shared(sharing == SHARED_NORMALIZED_MAP); | 6693 result->set_is_shared(sharing == SHARED_NORMALIZED_MAP); |
| 6555 result->set_dictionary_map(true); | 6694 result->set_dictionary_map(true); |
| 6556 result->set_migration_target(false); | 6695 result->set_migration_target(false); |
| 6557 | 6696 |
| 6558 #ifdef VERIFY_HEAP | 6697 #ifdef VERIFY_HEAP |
| 6559 if (FLAG_verify_heap && result->is_shared()) { | 6698 if (FLAG_verify_heap && result->is_shared()) { |
| 6560 result->SharedMapVerify(); | 6699 result->SharedMapVerify(); |
| 6561 } | 6700 } |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6691 set_transitions(transitions); | 6830 set_transitions(transitions); |
| 6692 result->SetBackPointer(this); | 6831 result->SetBackPointer(this); |
| 6693 } else { | 6832 } else { |
| 6694 descriptors->InitializeRepresentations(Representation::Tagged()); | 6833 descriptors->InitializeRepresentations(Representation::Tagged()); |
| 6695 } | 6834 } |
| 6696 | 6835 |
| 6697 return result; | 6836 return result; |
| 6698 } | 6837 } |
| 6699 | 6838 |
| 6700 | 6839 |
| 6701 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map, | |
| 6702 int new_descriptor, | |
| 6703 Handle<DescriptorArray> descriptors) { | |
| 6704 CALL_HEAP_FUNCTION(map->GetIsolate(), | |
| 6705 map->CopyInstallDescriptors(new_descriptor, *descriptors), | |
| 6706 Map); | |
| 6707 } | |
| 6708 | |
| 6709 | |
| 6710 // Since this method is used to rewrite an existing transition tree, it can | 6840 // Since this method is used to rewrite an existing transition tree, it can |
| 6711 // always insert transitions without checking. | 6841 // always insert transitions without checking. |
| 6712 MaybeObject* Map::CopyInstallDescriptors(int new_descriptor, | 6842 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map, |
| 6713 DescriptorArray* descriptors) { | 6843 int new_descriptor, |
| 6844 Handle<DescriptorArray> descriptors) { |
| 6714 ASSERT(descriptors->IsSortedNoDuplicates()); | 6845 ASSERT(descriptors->IsSortedNoDuplicates()); |
| 6715 | 6846 |
| 6716 Map* result; | 6847 Handle<Map> result = Map::CopyDropDescriptors(map); |
| 6717 MaybeObject* maybe_result = CopyDropDescriptors(); | |
| 6718 if (!maybe_result->To(&result)) return maybe_result; | |
| 6719 | 6848 |
| 6720 result->InitializeDescriptors(descriptors); | 6849 result->InitializeDescriptors(*descriptors); |
| 6721 result->SetNumberOfOwnDescriptors(new_descriptor + 1); | 6850 result->SetNumberOfOwnDescriptors(new_descriptor + 1); |
| 6722 | 6851 |
| 6723 int unused_property_fields = this->unused_property_fields(); | 6852 int unused_property_fields = map->unused_property_fields(); |
| 6724 if (descriptors->GetDetails(new_descriptor).type() == FIELD) { | 6853 if (descriptors->GetDetails(new_descriptor).type() == FIELD) { |
| 6725 unused_property_fields = this->unused_property_fields() - 1; | 6854 unused_property_fields = map->unused_property_fields() - 1; |
| 6726 if (unused_property_fields < 0) { | 6855 if (unused_property_fields < 0) { |
| 6727 unused_property_fields += JSObject::kFieldsAdded; | 6856 unused_property_fields += JSObject::kFieldsAdded; |
| 6728 } | 6857 } |
| 6729 } | 6858 } |
| 6730 | 6859 |
| 6731 result->set_unused_property_fields(unused_property_fields); | 6860 result->set_unused_property_fields(unused_property_fields); |
| 6732 result->set_owns_descriptors(false); | 6861 result->set_owns_descriptors(false); |
| 6733 | 6862 |
| 6734 Name* name = descriptors->GetKey(new_descriptor); | 6863 Handle<Name> name = handle(descriptors->GetKey(new_descriptor)); |
| 6735 TransitionArray* transitions; | 6864 Handle<TransitionArray> transitions = Map::AddTransition(map, name, result, |
| 6736 MaybeObject* maybe_transitions = | 6865 SIMPLE_TRANSITION); |
| 6737 AddTransition(name, result, SIMPLE_TRANSITION); | |
| 6738 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | |
| 6739 | 6866 |
| 6740 set_transitions(transitions); | 6867 map->set_transitions(*transitions); |
| 6741 result->SetBackPointer(this); | 6868 result->SetBackPointer(*map); |
| 6742 | 6869 |
| 6743 return result; | 6870 return result; |
| 6744 } | 6871 } |
| 6745 | 6872 |
| 6746 | 6873 |
| 6747 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { | 6874 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { |
| 6748 if (flag == INSERT_TRANSITION) { | 6875 if (flag == INSERT_TRANSITION) { |
| 6749 ASSERT(!HasElementsTransition() || | 6876 ASSERT(!HasElementsTransition() || |
| 6750 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || | 6877 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || |
| 6751 IsExternalArrayElementsKind( | 6878 IsExternalArrayElementsKind( |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6789 if (insert_transition) { | 6916 if (insert_transition) { |
| 6790 MaybeObject* added_elements = set_elements_transition_map(new_map); | 6917 MaybeObject* added_elements = set_elements_transition_map(new_map); |
| 6791 if (added_elements->IsFailure()) return added_elements; | 6918 if (added_elements->IsFailure()) return added_elements; |
| 6792 new_map->SetBackPointer(this); | 6919 new_map->SetBackPointer(this); |
| 6793 } | 6920 } |
| 6794 | 6921 |
| 6795 return new_map; | 6922 return new_map; |
| 6796 } | 6923 } |
| 6797 | 6924 |
| 6798 | 6925 |
| 6799 MaybeObject* Map::CopyForObserved() { | 6926 Handle<Map> Map::CopyForObserved(Handle<Map> map) { |
| 6800 ASSERT(!is_observed()); | 6927 ASSERT(!map->is_observed()); |
| 6928 |
| 6929 Isolate* isolate = map->GetIsolate(); |
| 6801 | 6930 |
| 6802 // In case the map owned its own descriptors, share the descriptors and | 6931 // In case the map owned its own descriptors, share the descriptors and |
| 6803 // transfer ownership to the new map. | 6932 // transfer ownership to the new map. |
| 6804 Map* new_map; | 6933 Handle<Map> new_map; |
| 6805 MaybeObject* maybe_new_map; | 6934 if (map->owns_descriptors()) { |
| 6806 if (owns_descriptors()) { | 6935 new_map = Map::CopyDropDescriptors(map); |
| 6807 maybe_new_map = CopyDropDescriptors(); | |
| 6808 } else { | 6936 } else { |
| 6809 maybe_new_map = Copy(); | 6937 new_map = Map::Copy(map); |
| 6810 } | 6938 } |
| 6811 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
| 6812 | 6939 |
| 6813 TransitionArray* transitions; | 6940 Handle<TransitionArray> transitions = |
| 6814 MaybeObject* maybe_transitions = AddTransition(GetHeap()->observed_symbol(), | 6941 Map::AddTransition(map, isolate->factory()->observed_symbol(), new_map, |
| 6815 new_map, | 6942 FULL_TRANSITION); |
| 6816 FULL_TRANSITION); | 6943 |
| 6817 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | 6944 map->set_transitions(*transitions); |
| 6818 set_transitions(transitions); | |
| 6819 | 6945 |
| 6820 new_map->set_is_observed(true); | 6946 new_map->set_is_observed(true); |
| 6821 | 6947 |
| 6822 if (owns_descriptors()) { | 6948 if (map->owns_descriptors()) { |
| 6823 new_map->InitializeDescriptors(instance_descriptors()); | 6949 new_map->InitializeDescriptors(map->instance_descriptors()); |
| 6824 set_owns_descriptors(false); | 6950 map->set_owns_descriptors(false); |
| 6825 } | 6951 } |
| 6826 | 6952 |
| 6827 new_map->SetBackPointer(this); | 6953 new_map->SetBackPointer(*map); |
| 6828 return new_map; | 6954 return new_map; |
| 6829 } | 6955 } |
| 6830 | 6956 |
| 6831 | 6957 |
| 6832 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() { | 6958 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() { |
| 6833 if (pre_allocated_property_fields() == 0) return CopyDropDescriptors(); | 6959 if (pre_allocated_property_fields() == 0) return CopyDropDescriptors(); |
| 6834 | 6960 |
| 6835 // If the map has pre-allocated properties always start out with a descriptor | 6961 // If the map has pre-allocated properties always start out with a descriptor |
| 6836 // array describing these properties. | 6962 // array describing these properties. |
| 6837 ASSERT(constructor()->IsJSFunction()); | 6963 ASSERT(constructor()->IsJSFunction()); |
| (...skipping 2421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9259 // TODO(verwaest) Should be an assert, otherwise back pointers are not | 9385 // TODO(verwaest) Should be an assert, otherwise back pointers are not |
| 9260 // properly cleared. | 9386 // properly cleared. |
| 9261 if (transition_index == t->number_of_transitions()) return; | 9387 if (transition_index == t->number_of_transitions()) return; |
| 9262 | 9388 |
| 9263 int number_of_own_descriptors = NumberOfOwnDescriptors(); | 9389 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
| 9264 | 9390 |
| 9265 if (descriptors_owner_died) { | 9391 if (descriptors_owner_died) { |
| 9266 if (number_of_own_descriptors > 0) { | 9392 if (number_of_own_descriptors > 0) { |
| 9267 TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors); | 9393 TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors); |
| 9268 ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors); | 9394 ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors); |
| 9395 set_owns_descriptors(true); |
| 9269 } else { | 9396 } else { |
| 9270 ASSERT(descriptors == GetHeap()->empty_descriptor_array()); | 9397 ASSERT(descriptors == GetHeap()->empty_descriptor_array()); |
| 9271 } | 9398 } |
| 9272 } | 9399 } |
| 9273 | 9400 |
| 9274 int trim = t->number_of_transitions() - transition_index; | 9401 int trim = t->number_of_transitions() - transition_index; |
| 9275 if (trim > 0) { | 9402 if (trim > 0) { |
| 9276 RightTrimFixedArray<FROM_GC>(heap, t, t->IsSimpleTransition() | 9403 RightTrimFixedArray<FROM_GC>(heap, t, t->IsSimpleTransition() |
| 9277 ? trim : trim * TransitionArray::kTransitionSize); | 9404 ? trim : trim * TransitionArray::kTransitionSize); |
| 9278 } | 9405 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9315 | 9442 |
| 9316 | 9443 |
| 9317 bool Map::EquivalentToForNormalization(Map* other, | 9444 bool Map::EquivalentToForNormalization(Map* other, |
| 9318 PropertyNormalizationMode mode) { | 9445 PropertyNormalizationMode mode) { |
| 9319 int properties = mode == CLEAR_INOBJECT_PROPERTIES | 9446 int properties = mode == CLEAR_INOBJECT_PROPERTIES |
| 9320 ? 0 : other->inobject_properties(); | 9447 ? 0 : other->inobject_properties(); |
| 9321 return CheckEquivalent(this, other) && inobject_properties() == properties; | 9448 return CheckEquivalent(this, other) && inobject_properties() == properties; |
| 9322 } | 9449 } |
| 9323 | 9450 |
| 9324 | 9451 |
| 9452 void ConstantPoolArray::ConstantPoolIterateBody(ObjectVisitor* v) { |
| 9453 int first_ptr_offset = OffsetOfElementAt(first_ptr_index()); |
| 9454 int last_ptr_offset = |
| 9455 OffsetOfElementAt(first_ptr_index() + count_of_ptr_entries()); |
| 9456 v->VisitPointers( |
| 9457 HeapObject::RawField(this, first_ptr_offset), |
| 9458 HeapObject::RawField(this, last_ptr_offset)); |
| 9459 } |
| 9460 |
| 9461 |
| 9325 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { | 9462 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { |
| 9326 // Iterate over all fields in the body but take care in dealing with | 9463 // Iterate over all fields in the body but take care in dealing with |
| 9327 // the code entry. | 9464 // the code entry. |
| 9328 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); | 9465 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); |
| 9329 v->VisitCodeEntry(this->address() + kCodeEntryOffset); | 9466 v->VisitCodeEntry(this->address() + kCodeEntryOffset); |
| 9330 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); | 9467 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); |
| 9331 } | 9468 } |
| 9332 | 9469 |
| 9333 | 9470 |
| 9334 void JSFunction::MarkForLazyRecompilation() { | 9471 void JSFunction::MarkForLazyRecompilation() { |
| (...skipping 832 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10167 | 10304 |
| 10168 | 10305 |
| 10169 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) { | 10306 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) { |
| 10170 ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); | 10307 ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); |
| 10171 VisitPointer(rinfo->target_object_address()); | 10308 VisitPointer(rinfo->target_object_address()); |
| 10172 } | 10309 } |
| 10173 | 10310 |
| 10174 | 10311 |
| 10175 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) { | 10312 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) { |
| 10176 Address* p = rinfo->target_reference_address(); | 10313 Address* p = rinfo->target_reference_address(); |
| 10177 VisitExternalReferences(p, p + 1); | 10314 VisitExternalReference(p); |
| 10178 } | 10315 } |
| 10179 | 10316 |
| 10180 | 10317 |
| 10181 void Code::InvalidateRelocation() { | 10318 void Code::InvalidateRelocation() { |
| 10182 set_relocation_info(GetHeap()->empty_byte_array()); | 10319 set_relocation_info(GetHeap()->empty_byte_array()); |
| 10183 } | 10320 } |
| 10184 | 10321 |
| 10185 | 10322 |
| 10186 void Code::Relocate(intptr_t delta) { | 10323 void Code::Relocate(intptr_t delta) { |
| 10187 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) { | 10324 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10224 } else if (RelocInfo::IsCodeTarget(mode)) { | 10361 } else if (RelocInfo::IsCodeTarget(mode)) { |
| 10225 // rewrite code handles in inline cache targets to direct | 10362 // rewrite code handles in inline cache targets to direct |
| 10226 // pointers to the first instruction in the code object | 10363 // pointers to the first instruction in the code object |
| 10227 Handle<Object> p = it.rinfo()->target_object_handle(origin); | 10364 Handle<Object> p = it.rinfo()->target_object_handle(origin); |
| 10228 Code* code = Code::cast(*p); | 10365 Code* code = Code::cast(*p); |
| 10229 it.rinfo()->set_target_address(code->instruction_start(), | 10366 it.rinfo()->set_target_address(code->instruction_start(), |
| 10230 SKIP_WRITE_BARRIER); | 10367 SKIP_WRITE_BARRIER); |
| 10231 } else if (RelocInfo::IsRuntimeEntry(mode)) { | 10368 } else if (RelocInfo::IsRuntimeEntry(mode)) { |
| 10232 Address p = it.rinfo()->target_runtime_entry(origin); | 10369 Address p = it.rinfo()->target_runtime_entry(origin); |
| 10233 it.rinfo()->set_target_runtime_entry(p, SKIP_WRITE_BARRIER); | 10370 it.rinfo()->set_target_runtime_entry(p, SKIP_WRITE_BARRIER); |
| 10371 } else if (mode == RelocInfo::CODE_AGE_SEQUENCE) { |
| 10372 Handle<Object> p = it.rinfo()->code_age_stub_handle(origin); |
| 10373 Code* code = Code::cast(*p); |
| 10374 it.rinfo()->set_code_age_stub(code); |
| 10234 } else { | 10375 } else { |
| 10235 it.rinfo()->apply(delta); | 10376 it.rinfo()->apply(delta); |
| 10236 } | 10377 } |
| 10237 } | 10378 } |
| 10238 CPU::FlushICache(instruction_start(), instruction_size()); | 10379 CPU::FlushICache(instruction_start(), instruction_size()); |
| 10239 } | 10380 } |
| 10240 | 10381 |
| 10241 | 10382 |
| 10242 // Locate the source position which is closest to the address in the code. This | 10383 // Locate the source position which is closest to the address in the code. This |
| 10243 // is using the source position information embedded in the relocation info. | 10384 // is using the source position information embedded in the relocation info. |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10461 ASSERT(kind() == FUNCTION); | 10602 ASSERT(kind() == FUNCTION); |
| 10462 BackEdgeTable back_edges(this, &no_gc); | 10603 BackEdgeTable back_edges(this, &no_gc); |
| 10463 for (uint32_t i = 0; i < back_edges.length(); i++) { | 10604 for (uint32_t i = 0; i < back_edges.length(); i++) { |
| 10464 if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i); | 10605 if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i); |
| 10465 } | 10606 } |
| 10466 return BailoutId::None(); | 10607 return BailoutId::None(); |
| 10467 } | 10608 } |
| 10468 | 10609 |
| 10469 | 10610 |
| 10470 void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) { | 10611 void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) { |
| 10471 PatchPlatformCodeAge(isolate, sequence, kNoAge, NO_MARKING_PARITY); | 10612 PatchPlatformCodeAge(isolate, sequence, kNoAgeCodeAge, NO_MARKING_PARITY); |
| 10472 } | 10613 } |
| 10473 | 10614 |
| 10474 | 10615 |
| 10616 void Code::MarkCodeAsExecuted(byte* sequence, Isolate* isolate) { |
| 10617 PatchPlatformCodeAge(isolate, sequence, kExecutedOnceCodeAge, |
| 10618 NO_MARKING_PARITY); |
| 10619 } |
| 10620 |
| 10621 |
| 10475 void Code::MakeOlder(MarkingParity current_parity) { | 10622 void Code::MakeOlder(MarkingParity current_parity) { |
| 10476 byte* sequence = FindCodeAgeSequence(); | 10623 byte* sequence = FindCodeAgeSequence(); |
| 10477 if (sequence != NULL) { | 10624 if (sequence != NULL) { |
| 10478 Age age; | 10625 Age age; |
| 10479 MarkingParity code_parity; | 10626 MarkingParity code_parity; |
| 10480 GetCodeAgeAndParity(sequence, &age, &code_parity); | 10627 GetCodeAgeAndParity(sequence, &age, &code_parity); |
| 10481 if (age != kLastCodeAge && code_parity != current_parity) { | 10628 if (age != kLastCodeAge && code_parity != current_parity) { |
| 10482 PatchPlatformCodeAge(GetIsolate(), | 10629 PatchPlatformCodeAge(GetIsolate(), |
| 10483 sequence, | 10630 sequence, |
| 10484 static_cast<Age>(age + 1), | 10631 static_cast<Age>(age + 1), |
| 10485 current_parity); | 10632 current_parity); |
| 10486 } | 10633 } |
| 10487 } | 10634 } |
| 10488 } | 10635 } |
| 10489 | 10636 |
| 10490 | 10637 |
| 10491 bool Code::IsOld() { | 10638 bool Code::IsOld() { |
| 10492 byte* sequence = FindCodeAgeSequence(); | 10639 Age age = GetAge(); |
| 10493 if (sequence == NULL) return false; | 10640 return age >= kIsOldCodeAge; |
| 10494 Age age; | |
| 10495 MarkingParity parity; | |
| 10496 GetCodeAgeAndParity(sequence, &age, &parity); | |
| 10497 return age >= kSexagenarianCodeAge; | |
| 10498 } | 10641 } |
| 10499 | 10642 |
| 10500 | 10643 |
| 10501 byte* Code::FindCodeAgeSequence() { | 10644 byte* Code::FindCodeAgeSequence() { |
| 10502 return FLAG_age_code && | 10645 return FLAG_age_code && |
| 10503 prologue_offset() != kPrologueOffsetNotSet && | 10646 prologue_offset() != Code::kPrologueOffsetNotSet && |
| 10504 (kind() == OPTIMIZED_FUNCTION || | 10647 (kind() == OPTIMIZED_FUNCTION || |
| 10505 (kind() == FUNCTION && !has_debug_break_slots())) | 10648 (kind() == FUNCTION && !has_debug_break_slots())) |
| 10506 ? instruction_start() + prologue_offset() | 10649 ? instruction_start() + prologue_offset() |
| 10507 : NULL; | 10650 : NULL; |
| 10508 } | 10651 } |
| 10509 | 10652 |
| 10510 | 10653 |
| 10511 int Code::GetAge() { | 10654 Code::Age Code::GetAge() { |
| 10512 byte* sequence = FindCodeAgeSequence(); | 10655 byte* sequence = FindCodeAgeSequence(); |
| 10513 if (sequence == NULL) { | 10656 if (sequence == NULL) { |
| 10514 return Code::kNoAge; | 10657 return Code::kNoAgeCodeAge; |
| 10515 } | 10658 } |
| 10516 Age age; | 10659 Age age; |
| 10517 MarkingParity parity; | 10660 MarkingParity parity; |
| 10518 GetCodeAgeAndParity(sequence, &age, &parity); | 10661 GetCodeAgeAndParity(sequence, &age, &parity); |
| 10519 return age; | 10662 return age; |
| 10520 } | 10663 } |
| 10521 | 10664 |
| 10522 | 10665 |
| 10523 void Code::GetCodeAgeAndParity(Code* code, Age* age, | 10666 void Code::GetCodeAgeAndParity(Code* code, Age* age, |
| 10524 MarkingParity* parity) { | 10667 MarkingParity* parity) { |
| 10525 Isolate* isolate = code->GetIsolate(); | 10668 Isolate* isolate = code->GetIsolate(); |
| 10526 Builtins* builtins = isolate->builtins(); | 10669 Builtins* builtins = isolate->builtins(); |
| 10527 Code* stub = NULL; | 10670 Code* stub = NULL; |
| 10528 #define HANDLE_CODE_AGE(AGE) \ | 10671 #define HANDLE_CODE_AGE(AGE) \ |
| 10529 stub = *builtins->Make##AGE##CodeYoungAgainEvenMarking(); \ | 10672 stub = *builtins->Make##AGE##CodeYoungAgainEvenMarking(); \ |
| 10530 if (code == stub) { \ | 10673 if (code == stub) { \ |
| 10531 *age = k##AGE##CodeAge; \ | 10674 *age = k##AGE##CodeAge; \ |
| 10532 *parity = EVEN_MARKING_PARITY; \ | 10675 *parity = EVEN_MARKING_PARITY; \ |
| 10533 return; \ | 10676 return; \ |
| 10534 } \ | 10677 } \ |
| 10535 stub = *builtins->Make##AGE##CodeYoungAgainOddMarking(); \ | 10678 stub = *builtins->Make##AGE##CodeYoungAgainOddMarking(); \ |
| 10536 if (code == stub) { \ | 10679 if (code == stub) { \ |
| 10537 *age = k##AGE##CodeAge; \ | 10680 *age = k##AGE##CodeAge; \ |
| 10538 *parity = ODD_MARKING_PARITY; \ | 10681 *parity = ODD_MARKING_PARITY; \ |
| 10539 return; \ | 10682 return; \ |
| 10540 } | 10683 } |
| 10541 CODE_AGE_LIST(HANDLE_CODE_AGE) | 10684 CODE_AGE_LIST(HANDLE_CODE_AGE) |
| 10542 #undef HANDLE_CODE_AGE | 10685 #undef HANDLE_CODE_AGE |
| 10686 stub = *builtins->MarkCodeAsExecutedOnce(); |
| 10687 if (code == stub) { |
| 10688 // Treat that's never been executed as old immediatly. |
| 10689 *age = kIsOldCodeAge; |
| 10690 *parity = NO_MARKING_PARITY; |
| 10691 return; |
| 10692 } |
| 10693 stub = *builtins->MarkCodeAsExecutedTwice(); |
| 10694 if (code == stub) { |
| 10695 // Pre-age code that has only been executed once. |
| 10696 *age = kPreAgedCodeAge; |
| 10697 *parity = NO_MARKING_PARITY; |
| 10698 return; |
| 10699 } |
| 10543 UNREACHABLE(); | 10700 UNREACHABLE(); |
| 10544 } | 10701 } |
| 10545 | 10702 |
| 10546 | 10703 |
| 10547 Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) { | 10704 Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) { |
| 10548 Builtins* builtins = isolate->builtins(); | 10705 Builtins* builtins = isolate->builtins(); |
| 10549 switch (age) { | 10706 switch (age) { |
| 10550 #define HANDLE_CODE_AGE(AGE) \ | 10707 #define HANDLE_CODE_AGE(AGE) \ |
| 10551 case k##AGE##CodeAge: { \ | 10708 case k##AGE##CodeAge: { \ |
| 10552 Code* stub = parity == EVEN_MARKING_PARITY \ | 10709 Code* stub = parity == EVEN_MARKING_PARITY \ |
| 10553 ? *builtins->Make##AGE##CodeYoungAgainEvenMarking() \ | 10710 ? *builtins->Make##AGE##CodeYoungAgainEvenMarking() \ |
| 10554 : *builtins->Make##AGE##CodeYoungAgainOddMarking(); \ | 10711 : *builtins->Make##AGE##CodeYoungAgainOddMarking(); \ |
| 10555 return stub; \ | 10712 return stub; \ |
| 10556 } | 10713 } |
| 10557 CODE_AGE_LIST(HANDLE_CODE_AGE) | 10714 CODE_AGE_LIST(HANDLE_CODE_AGE) |
| 10558 #undef HANDLE_CODE_AGE | 10715 #undef HANDLE_CODE_AGE |
| 10716 case kNotExecutedCodeAge: { |
| 10717 ASSERT(parity == NO_MARKING_PARITY); |
| 10718 return *builtins->MarkCodeAsExecutedOnce(); |
| 10719 } |
| 10720 case kExecutedOnceCodeAge: { |
| 10721 ASSERT(parity == NO_MARKING_PARITY); |
| 10722 return *builtins->MarkCodeAsExecutedTwice(); |
| 10723 } |
| 10559 default: | 10724 default: |
| 10560 UNREACHABLE(); | 10725 UNREACHABLE(); |
| 10561 break; | 10726 break; |
| 10562 } | 10727 } |
| 10563 return NULL; | 10728 return NULL; |
| 10564 } | 10729 } |
| 10565 | 10730 |
| 10566 | 10731 |
| 10567 void Code::PrintDeoptLocation(int bailout_id) { | 10732 void Code::PrintDeoptLocation(int bailout_id) { |
| 10568 const char* last_comment = NULL; | 10733 const char* last_comment = NULL; |
| (...skipping 1944 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12513 } | 12678 } |
| 12514 | 12679 |
| 12515 | 12680 |
| 12516 void JSObject::TransitionElementsKind(Handle<JSObject> object, | 12681 void JSObject::TransitionElementsKind(Handle<JSObject> object, |
| 12517 ElementsKind to_kind) { | 12682 ElementsKind to_kind) { |
| 12518 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), | 12683 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), |
| 12519 object->TransitionElementsKind(to_kind)); | 12684 object->TransitionElementsKind(to_kind)); |
| 12520 } | 12685 } |
| 12521 | 12686 |
| 12522 | 12687 |
| 12688 bool AllocationSite::IsNestedSite() { |
| 12689 ASSERT(FLAG_trace_track_allocation_sites); |
| 12690 Object* current = GetHeap()->allocation_sites_list(); |
| 12691 while (current != NULL && current->IsAllocationSite()) { |
| 12692 AllocationSite* current_site = AllocationSite::cast(current); |
| 12693 if (current_site->nested_site() == this) { |
| 12694 return true; |
| 12695 } |
| 12696 current = current_site->weak_next(); |
| 12697 } |
| 12698 return false; |
| 12699 } |
| 12700 |
| 12701 |
| 12523 MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) { | 12702 MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) { |
| 12524 if (!FLAG_track_allocation_sites || !IsJSArray()) { | 12703 if (!FLAG_track_allocation_sites || !IsJSArray()) { |
| 12525 return this; | 12704 return this; |
| 12526 } | 12705 } |
| 12527 | 12706 |
| 12528 AllocationMemento* memento = AllocationMemento::FindForJSObject(this); | 12707 AllocationMemento* memento = AllocationMemento::FindForJSObject(this); |
| 12529 if (memento == NULL || !memento->IsValid()) { | 12708 if (memento == NULL || !memento->IsValid()) { |
| 12530 return this; | 12709 return this; |
| 12531 } | 12710 } |
| 12532 | 12711 |
| 12533 // Walk through to the Allocation Site | 12712 // Walk through to the Allocation Site |
| 12534 AllocationSite* site = memento->GetAllocationSite(); | 12713 AllocationSite* site = memento->GetAllocationSite(); |
| 12535 if (site->IsLiteralSite()) { | 12714 if (site->SitePointsToLiteral() && |
| 12715 site->transition_info()->IsJSArray()) { |
| 12536 JSArray* transition_info = JSArray::cast(site->transition_info()); | 12716 JSArray* transition_info = JSArray::cast(site->transition_info()); |
| 12537 ElementsKind kind = transition_info->GetElementsKind(); | 12717 ElementsKind kind = transition_info->GetElementsKind(); |
| 12538 // if kind is holey ensure that to_kind is as well. | 12718 // if kind is holey ensure that to_kind is as well. |
| 12539 if (IsHoleyElementsKind(kind)) { | 12719 if (IsHoleyElementsKind(kind)) { |
| 12540 to_kind = GetHoleyElementsKind(to_kind); | 12720 to_kind = GetHoleyElementsKind(to_kind); |
| 12541 } | 12721 } |
| 12542 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { | 12722 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { |
| 12543 // If the array is huge, it's not likely to be defined in a local | 12723 // If the array is huge, it's not likely to be defined in a local |
| 12544 // function, so we shouldn't make new instances of it very often. | 12724 // function, so we shouldn't make new instances of it very often. |
| 12545 uint32_t length = 0; | 12725 uint32_t length = 0; |
| 12546 CHECK(transition_info->length()->ToArrayIndex(&length)); | 12726 CHECK(transition_info->length()->ToArrayIndex(&length)); |
| 12547 if (length <= AllocationSite::kMaximumArrayBytesToPretransition) { | 12727 if (length <= AllocationSite::kMaximumArrayBytesToPretransition) { |
| 12548 if (FLAG_trace_track_allocation_sites) { | 12728 if (FLAG_trace_track_allocation_sites) { |
| 12729 bool is_nested = site->IsNestedSite(); |
| 12549 PrintF( | 12730 PrintF( |
| 12550 "AllocationSite: JSArray %p boilerplate updated %s->%s\n", | 12731 "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n", |
| 12551 reinterpret_cast<void*>(this), | 12732 reinterpret_cast<void*>(this), |
| 12733 is_nested ? "(nested)" : "", |
| 12552 ElementsKindToString(kind), | 12734 ElementsKindToString(kind), |
| 12553 ElementsKindToString(to_kind)); | 12735 ElementsKindToString(to_kind)); |
| 12554 } | 12736 } |
| 12555 return transition_info->TransitionElementsKind(to_kind); | 12737 return transition_info->TransitionElementsKind(to_kind); |
| 12556 } | 12738 } |
| 12557 } | 12739 } |
| 12558 } else { | 12740 } else { |
| 12559 ElementsKind kind = site->GetElementsKind(); | 12741 ElementsKind kind = site->GetElementsKind(); |
| 12560 // if kind is holey ensure that to_kind is as well. | 12742 // if kind is holey ensure that to_kind is as well. |
| 12561 if (IsHoleyElementsKind(kind)) { | 12743 if (IsHoleyElementsKind(kind)) { |
| (...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12944 InterceptorInfo* JSObject::GetIndexedInterceptor() { | 13126 InterceptorInfo* JSObject::GetIndexedInterceptor() { |
| 12945 ASSERT(map()->has_indexed_interceptor()); | 13127 ASSERT(map()->has_indexed_interceptor()); |
| 12946 JSFunction* constructor = JSFunction::cast(map()->constructor()); | 13128 JSFunction* constructor = JSFunction::cast(map()->constructor()); |
| 12947 ASSERT(constructor->shared()->IsApiFunction()); | 13129 ASSERT(constructor->shared()->IsApiFunction()); |
| 12948 Object* result = | 13130 Object* result = |
| 12949 constructor->shared()->get_api_func_data()->indexed_property_handler(); | 13131 constructor->shared()->get_api_func_data()->indexed_property_handler(); |
| 12950 return InterceptorInfo::cast(result); | 13132 return InterceptorInfo::cast(result); |
| 12951 } | 13133 } |
| 12952 | 13134 |
| 12953 | 13135 |
| 12954 MaybeObject* JSObject::GetPropertyPostInterceptor( | 13136 Handle<Object> JSObject::GetPropertyPostInterceptor( |
| 12955 Object* receiver, | 13137 Handle<JSObject> object, |
| 12956 Name* name, | 13138 Handle<Object> receiver, |
| 13139 Handle<Name> name, |
| 12957 PropertyAttributes* attributes) { | 13140 PropertyAttributes* attributes) { |
| 12958 // Check local property in holder, ignore interceptor. | 13141 // Check local property in holder, ignore interceptor. |
| 12959 LookupResult result(GetIsolate()); | 13142 Isolate* isolate = object->GetIsolate(); |
| 12960 LocalLookupRealNamedProperty(name, &result); | 13143 LookupResult lookup(isolate); |
| 12961 if (result.IsFound()) { | 13144 object->LocalLookupRealNamedProperty(*name, &lookup); |
| 12962 return GetProperty(receiver, &result, name, attributes); | 13145 Handle<Object> result; |
| 13146 if (lookup.IsFound()) { |
| 13147 result = GetProperty(object, receiver, &lookup, name, attributes); |
| 13148 } else { |
| 13149 // Continue searching via the prototype chain. |
| 13150 Handle<Object> prototype(object->GetPrototype(), isolate); |
| 13151 *attributes = ABSENT; |
| 13152 if (prototype->IsNull()) return isolate->factory()->undefined_value(); |
| 13153 result = GetPropertyWithReceiver(prototype, receiver, name, attributes); |
| 12963 } | 13154 } |
| 12964 // Continue searching via the prototype chain. | 13155 return result; |
| 12965 Object* pt = GetPrototype(); | |
| 12966 *attributes = ABSENT; | |
| 12967 if (pt->IsNull()) return GetHeap()->undefined_value(); | |
| 12968 return pt->GetPropertyWithReceiver(receiver, name, attributes); | |
| 12969 } | 13156 } |
| 12970 | 13157 |
| 12971 | 13158 |
| 12972 MaybeObject* JSObject::GetLocalPropertyPostInterceptor( | 13159 MaybeObject* JSObject::GetLocalPropertyPostInterceptor( |
| 12973 Object* receiver, | 13160 Object* receiver, |
| 12974 Name* name, | 13161 Name* name, |
| 12975 PropertyAttributes* attributes) { | 13162 PropertyAttributes* attributes) { |
| 12976 // Check local property in holder, ignore interceptor. | 13163 // Check local property in holder, ignore interceptor. |
| 12977 LookupResult result(GetIsolate()); | 13164 LookupResult result(GetIsolate()); |
| 12978 LocalLookupRealNamedProperty(name, &result); | 13165 LocalLookupRealNamedProperty(name, &result); |
| 12979 if (result.IsFound()) { | 13166 if (result.IsFound()) { |
| 12980 return GetProperty(receiver, &result, name, attributes); | 13167 return GetProperty(receiver, &result, name, attributes); |
| 12981 } | 13168 } |
| 12982 return GetHeap()->undefined_value(); | 13169 return GetHeap()->undefined_value(); |
| 12983 } | 13170 } |
| 12984 | 13171 |
| 12985 | 13172 |
| 12986 MaybeObject* JSObject::GetPropertyWithInterceptor( | 13173 Handle<Object> JSObject::GetPropertyWithInterceptor( |
| 12987 Object* receiver, | 13174 Handle<JSObject> object, |
| 12988 Name* name, | 13175 Handle<Object> receiver, |
| 13176 Handle<Name> name, |
| 12989 PropertyAttributes* attributes) { | 13177 PropertyAttributes* attributes) { |
| 13178 Isolate* isolate = object->GetIsolate(); |
| 13179 |
| 12990 // TODO(rossberg): Support symbols in the API. | 13180 // TODO(rossberg): Support symbols in the API. |
| 12991 if (name->IsSymbol()) return GetHeap()->undefined_value(); | 13181 if (name->IsSymbol()) return isolate->factory()->undefined_value(); |
| 12992 | 13182 |
| 12993 Isolate* isolate = GetIsolate(); | 13183 Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor(), isolate); |
| 12994 InterceptorInfo* interceptor = GetNamedInterceptor(); | 13184 Handle<String> name_string = Handle<String>::cast(name); |
| 12995 HandleScope scope(isolate); | |
| 12996 Handle<Object> receiver_handle(receiver, isolate); | |
| 12997 Handle<JSObject> holder_handle(this); | |
| 12998 Handle<String> name_handle(String::cast(name)); | |
| 12999 | 13185 |
| 13000 if (!interceptor->getter()->IsUndefined()) { | 13186 if (!interceptor->getter()->IsUndefined()) { |
| 13001 v8::NamedPropertyGetterCallback getter = | 13187 v8::NamedPropertyGetterCallback getter = |
| 13002 v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter()); | 13188 v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter()); |
| 13003 LOG(isolate, | 13189 LOG(isolate, |
| 13004 ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name)); | 13190 ApiNamedPropertyAccess("interceptor-named-get", *object, *name)); |
| 13005 PropertyCallbackArguments | 13191 PropertyCallbackArguments |
| 13006 args(isolate, interceptor->data(), receiver, this); | 13192 args(isolate, interceptor->data(), *receiver, *object); |
| 13007 v8::Handle<v8::Value> result = | 13193 v8::Handle<v8::Value> result = |
| 13008 args.Call(getter, v8::Utils::ToLocal(name_handle)); | 13194 args.Call(getter, v8::Utils::ToLocal(name_string)); |
| 13009 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 13195 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 13010 if (!result.IsEmpty()) { | 13196 if (!result.IsEmpty()) { |
| 13011 *attributes = NONE; | 13197 *attributes = NONE; |
| 13012 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | 13198 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); |
| 13013 result_internal->VerifyApiCallResultType(); | 13199 result_internal->VerifyApiCallResultType(); |
| 13014 return *result_internal; | 13200 // Rebox handle to escape this scope. |
| 13201 return handle(*result_internal, isolate); |
| 13015 } | 13202 } |
| 13016 } | 13203 } |
| 13017 | 13204 |
| 13018 MaybeObject* result = holder_handle->GetPropertyPostInterceptor( | 13205 return GetPropertyPostInterceptor(object, receiver, name, attributes); |
| 13019 *receiver_handle, | |
| 13020 *name_handle, | |
| 13021 attributes); | |
| 13022 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | |
| 13023 return result; | |
| 13024 } | 13206 } |
| 13025 | 13207 |
| 13026 | 13208 |
| 13027 bool JSObject::HasRealNamedProperty(Isolate* isolate, Name* key) { | 13209 bool JSObject::HasRealNamedProperty(Handle<JSObject> object, |
| 13210 Handle<Name> key) { |
| 13211 Isolate* isolate = object->GetIsolate(); |
| 13212 SealHandleScope shs(isolate); |
| 13028 // Check access rights if needed. | 13213 // Check access rights if needed. |
| 13029 if (IsAccessCheckNeeded()) { | 13214 if (object->IsAccessCheckNeeded()) { |
| 13030 if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) { | 13215 if (!isolate->MayNamedAccess(*object, *key, v8::ACCESS_HAS)) { |
| 13031 isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 13216 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_HAS); |
| 13032 return false; | 13217 return false; |
| 13033 } | 13218 } |
| 13034 } | 13219 } |
| 13035 | 13220 |
| 13036 LookupResult result(isolate); | 13221 LookupResult result(isolate); |
| 13037 LocalLookupRealNamedProperty(key, &result); | 13222 object->LocalLookupRealNamedProperty(*key, &result); |
| 13038 return result.IsFound() && !result.IsInterceptor(); | 13223 return result.IsFound() && !result.IsInterceptor(); |
| 13039 } | 13224 } |
| 13040 | 13225 |
| 13041 | 13226 |
| 13042 bool JSObject::HasRealElementProperty(Isolate* isolate, uint32_t index) { | 13227 bool JSObject::HasRealElementProperty(Handle<JSObject> object, uint32_t index) { |
| 13228 Isolate* isolate = object->GetIsolate(); |
| 13229 SealHandleScope shs(isolate); |
| 13043 // Check access rights if needed. | 13230 // Check access rights if needed. |
| 13044 if (IsAccessCheckNeeded()) { | 13231 if (object->IsAccessCheckNeeded()) { |
| 13045 if (!isolate->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 13232 if (!isolate->MayIndexedAccess(*object, index, v8::ACCESS_HAS)) { |
| 13046 isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 13233 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_HAS); |
| 13047 return false; | 13234 return false; |
| 13048 } | 13235 } |
| 13049 } | 13236 } |
| 13050 | 13237 |
| 13051 if (IsJSGlobalProxy()) { | 13238 if (object->IsJSGlobalProxy()) { |
| 13052 Object* proto = GetPrototype(); | 13239 HandleScope scope(isolate); |
| 13240 Handle<Object> proto(object->GetPrototype(), isolate); |
| 13053 if (proto->IsNull()) return false; | 13241 if (proto->IsNull()) return false; |
| 13054 ASSERT(proto->IsJSGlobalObject()); | 13242 ASSERT(proto->IsJSGlobalObject()); |
| 13055 return JSObject::cast(proto)->HasRealElementProperty(isolate, index); | 13243 return HasRealElementProperty(Handle<JSObject>::cast(proto), index); |
| 13056 } | 13244 } |
| 13057 | 13245 |
| 13058 return GetElementAttributeWithoutInterceptor(this, index, false) != ABSENT; | 13246 return object->GetElementAttributeWithoutInterceptor( |
| 13247 *object, index, false) != ABSENT; |
| 13059 } | 13248 } |
| 13060 | 13249 |
| 13061 | 13250 |
| 13062 bool JSObject::HasRealNamedCallbackProperty(Isolate* isolate, Name* key) { | 13251 bool JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object, |
| 13252 Handle<Name> key) { |
| 13253 Isolate* isolate = object->GetIsolate(); |
| 13254 SealHandleScope shs(isolate); |
| 13063 // Check access rights if needed. | 13255 // Check access rights if needed. |
| 13064 if (IsAccessCheckNeeded()) { | 13256 if (object->IsAccessCheckNeeded()) { |
| 13065 if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) { | 13257 if (!isolate->MayNamedAccess(*object, *key, v8::ACCESS_HAS)) { |
| 13066 isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 13258 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_HAS); |
| 13067 return false; | 13259 return false; |
| 13068 } | 13260 } |
| 13069 } | 13261 } |
| 13070 | 13262 |
| 13071 LookupResult result(isolate); | 13263 LookupResult result(isolate); |
| 13072 LocalLookupRealNamedProperty(key, &result); | 13264 object->LocalLookupRealNamedProperty(*key, &result); |
| 13073 return result.IsPropertyCallbacks(); | 13265 return result.IsPropertyCallbacks(); |
| 13074 } | 13266 } |
| 13075 | 13267 |
| 13076 | 13268 |
| 13077 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { | 13269 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { |
| 13078 if (HasFastProperties()) { | 13270 if (HasFastProperties()) { |
| 13079 Map* map = this->map(); | 13271 Map* map = this->map(); |
| 13080 if (filter == NONE) return map->NumberOfOwnDescriptors(); | 13272 if (filter == NONE) return map->NumberOfOwnDescriptors(); |
| 13081 if (filter & DONT_ENUM) { | 13273 if (filter & DONT_ENUM) { |
| 13082 int result = map->EnumLength(); | 13274 int result = map->EnumLength(); |
| (...skipping 3057 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16140 return static_cast<Type*>(type_raw()); | 16332 return static_cast<Type*>(type_raw()); |
| 16141 } | 16333 } |
| 16142 | 16334 |
| 16143 | 16335 |
| 16144 void PropertyCell::set_type(Type* type, WriteBarrierMode ignored) { | 16336 void PropertyCell::set_type(Type* type, WriteBarrierMode ignored) { |
| 16145 ASSERT(IsPropertyCell()); | 16337 ASSERT(IsPropertyCell()); |
| 16146 set_type_raw(type, ignored); | 16338 set_type_raw(type, ignored); |
| 16147 } | 16339 } |
| 16148 | 16340 |
| 16149 | 16341 |
| 16150 Type* PropertyCell::UpdateType(Handle<PropertyCell> cell, | 16342 Handle<Type> PropertyCell::UpdatedType(Handle<PropertyCell> cell, |
| 16151 Handle<Object> value) { | 16343 Handle<Object> value) { |
| 16152 Isolate* isolate = cell->GetIsolate(); | 16344 Isolate* isolate = cell->GetIsolate(); |
| 16153 Handle<Type> old_type(cell->type(), isolate); | 16345 Handle<Type> old_type(cell->type(), isolate); |
| 16154 // TODO(2803): Do not track ConsString as constant because they cannot be | 16346 // TODO(2803): Do not track ConsString as constant because they cannot be |
| 16155 // embedded into code. | 16347 // embedded into code. |
| 16156 Handle<Type> new_type(value->IsConsString() || value->IsTheHole() | 16348 Handle<Type> new_type(value->IsConsString() || value->IsTheHole() |
| 16157 ? Type::Any() | 16349 ? Type::Any() |
| 16158 : Type::Constant(value, isolate), isolate); | 16350 : Type::Constant(value, isolate), isolate); |
| 16159 | 16351 |
| 16160 if (new_type->Is(old_type)) { | 16352 if (new_type->Is(old_type)) { |
| 16161 return *old_type; | 16353 return old_type; |
| 16162 } | 16354 } |
| 16163 | 16355 |
| 16164 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 16356 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 16165 isolate, DependentCode::kPropertyCellChangedGroup); | 16357 isolate, DependentCode::kPropertyCellChangedGroup); |
| 16166 | 16358 |
| 16167 if (old_type->Is(Type::None()) || old_type->Is(Type::Undefined())) { | 16359 if (old_type->Is(Type::None()) || old_type->Is(Type::Undefined())) { |
| 16168 return *new_type; | 16360 return new_type; |
| 16169 } | 16361 } |
| 16170 | 16362 |
| 16171 return Type::Any(); | 16363 return handle(Type::Any(), isolate); |
| 16172 } | 16364 } |
| 16173 | 16365 |
| 16174 | 16366 |
| 16175 void PropertyCell::SetValueInferType(Handle<PropertyCell> cell, | 16367 void PropertyCell::SetValueInferType(Handle<PropertyCell> cell, |
| 16176 Handle<Object> value, | 16368 Handle<Object> value) { |
| 16177 WriteBarrierMode mode) { | 16369 cell->set_value(*value); |
| 16178 CALL_HEAP_FUNCTION_VOID(cell->GetIsolate(), | 16370 if (!Type::Any()->Is(cell->type())) { |
| 16179 cell->SetValueInferType(*value, mode)); | 16371 Handle<Type> new_type = UpdatedType(cell, value); |
| 16372 cell->set_type(*new_type); |
| 16373 } |
| 16180 } | 16374 } |
| 16181 | 16375 |
| 16182 | 16376 |
| 16183 MaybeObject* PropertyCell::SetValueInferType(Object* value, | |
| 16184 WriteBarrierMode ignored) { | |
| 16185 set_value(value, ignored); | |
| 16186 if (!Type::Any()->Is(type())) { | |
| 16187 IdempotentPointerToHandleCodeTrampoline trampoline(GetIsolate()); | |
| 16188 MaybeObject* maybe_type = trampoline.CallWithReturnValue( | |
| 16189 &PropertyCell::UpdateType, | |
| 16190 Handle<PropertyCell>(this), | |
| 16191 Handle<Object>(value, GetIsolate())); | |
| 16192 Type* new_type = NULL; | |
| 16193 if (!maybe_type->To(&new_type)) return maybe_type; | |
| 16194 set_type(new_type); | |
| 16195 } | |
| 16196 return value; | |
| 16197 } | |
| 16198 | |
| 16199 | |
| 16200 void PropertyCell::AddDependentCompilationInfo(CompilationInfo* info) { | 16377 void PropertyCell::AddDependentCompilationInfo(CompilationInfo* info) { |
| 16201 Handle<DependentCode> dep(dependent_code()); | 16378 Handle<DependentCode> dep(dependent_code()); |
| 16202 Handle<DependentCode> codes = | 16379 Handle<DependentCode> codes = |
| 16203 DependentCode::Insert(dep, DependentCode::kPropertyCellChangedGroup, | 16380 DependentCode::Insert(dep, DependentCode::kPropertyCellChangedGroup, |
| 16204 info->object_wrapper()); | 16381 info->object_wrapper()); |
| 16205 if (*codes != dependent_code()) set_dependent_code(*codes); | 16382 if (*codes != dependent_code()) set_dependent_code(*codes); |
| 16206 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( | 16383 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( |
| 16207 Handle<HeapObject>(this), info->zone()); | 16384 Handle<HeapObject>(this), info->zone()); |
| 16208 } | 16385 } |
| 16209 | 16386 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 16221 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16398 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 16222 static const char* error_messages_[] = { | 16399 static const char* error_messages_[] = { |
| 16223 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16400 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 16224 }; | 16401 }; |
| 16225 #undef ERROR_MESSAGES_TEXTS | 16402 #undef ERROR_MESSAGES_TEXTS |
| 16226 return error_messages_[reason]; | 16403 return error_messages_[reason]; |
| 16227 } | 16404 } |
| 16228 | 16405 |
| 16229 | 16406 |
| 16230 } } // namespace v8::internal | 16407 } } // namespace v8::internal |
| OLD | NEW |