| 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<FixedArray> JSObject::EnsureWritableFastElements( |
| 332 Object* structure, | 347 Handle<JSObject> object) { |
| 333 Name* name) { | 348 CALL_HEAP_FUNCTION(object->GetIsolate(), |
| 349 object->EnsureWritableFastElements(), |
| 350 FixedArray); |
| 351 } |
| 352 |
| 353 |
| 354 Handle<Object> JSObject::GetPropertyWithCallback(Handle<JSObject> object, |
| 355 Handle<Object> receiver, |
| 356 Handle<Object> structure, |
| 357 Handle<Name> name) { |
| 334 Isolate* isolate = name->GetIsolate(); | 358 Isolate* isolate = name->GetIsolate(); |
| 335 // To accommodate both the old and the new api we switch on the | 359 // To accommodate both the old and the new api we switch on the |
| 336 // data structure used to store the callbacks. Eventually foreign | 360 // data structure used to store the callbacks. Eventually foreign |
| 337 // callbacks should be phased out. | 361 // callbacks should be phased out. |
| 338 if (structure->IsForeign()) { | 362 if (structure->IsForeign()) { |
| 339 AccessorDescriptor* callback = | 363 AccessorDescriptor* callback = |
| 340 reinterpret_cast<AccessorDescriptor*>( | 364 reinterpret_cast<AccessorDescriptor*>( |
| 341 Foreign::cast(structure)->foreign_address()); | 365 Handle<Foreign>::cast(structure)->foreign_address()); |
| 342 MaybeObject* value = (callback->getter)(isolate, receiver, callback->data); | 366 CALL_HEAP_FUNCTION(isolate, |
| 343 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 367 (callback->getter)(isolate, *receiver, callback->data), |
| 344 return value; | 368 Object); |
| 345 } | 369 } |
| 346 | 370 |
| 347 // api style callbacks. | 371 // api style callbacks. |
| 348 if (structure->IsAccessorInfo()) { | 372 if (structure->IsAccessorInfo()) { |
| 349 if (!AccessorInfo::cast(structure)->IsCompatibleReceiver(receiver)) { | 373 Handle<AccessorInfo> accessor_info = Handle<AccessorInfo>::cast(structure); |
| 350 Handle<Object> name_handle(name, isolate); | 374 if (!accessor_info->IsCompatibleReceiver(*receiver)) { |
| 351 Handle<Object> receiver_handle(receiver, isolate); | 375 Handle<Object> args[2] = { name, receiver }; |
| 352 Handle<Object> args[2] = { name_handle, receiver_handle }; | |
| 353 Handle<Object> error = | 376 Handle<Object> error = |
| 354 isolate->factory()->NewTypeError("incompatible_method_receiver", | 377 isolate->factory()->NewTypeError("incompatible_method_receiver", |
| 355 HandleVector(args, | 378 HandleVector(args, |
| 356 ARRAY_SIZE(args))); | 379 ARRAY_SIZE(args))); |
| 357 return isolate->Throw(*error); | 380 isolate->Throw(*error); |
| 381 return Handle<Object>::null(); |
| 358 } | 382 } |
| 359 // TODO(rossberg): Handling symbols in the API requires changing the API, | 383 // TODO(rossberg): Handling symbols in the API requires changing the API, |
| 360 // so we do not support it for now. | 384 // so we do not support it for now. |
| 361 if (name->IsSymbol()) return isolate->heap()->undefined_value(); | 385 if (name->IsSymbol()) return isolate->factory()->undefined_value(); |
| 362 if (structure->IsDeclaredAccessorInfo()) { | 386 if (structure->IsDeclaredAccessorInfo()) { |
| 363 return GetDeclaredAccessorProperty(receiver, | 387 CALL_HEAP_FUNCTION( |
| 364 DeclaredAccessorInfo::cast(structure), | 388 isolate, |
| 365 isolate); | 389 GetDeclaredAccessorProperty(*receiver, |
| 390 DeclaredAccessorInfo::cast(*structure), |
| 391 isolate), |
| 392 Object); |
| 366 } | 393 } |
| 367 ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(structure); | 394 |
| 368 Object* fun_obj = data->getter(); | 395 Handle<ExecutableAccessorInfo> data = |
| 396 Handle<ExecutableAccessorInfo>::cast(structure); |
| 369 v8::AccessorGetterCallback call_fun = | 397 v8::AccessorGetterCallback call_fun = |
| 370 v8::ToCData<v8::AccessorGetterCallback>(fun_obj); | 398 v8::ToCData<v8::AccessorGetterCallback>(data->getter()); |
| 371 if (call_fun == NULL) return isolate->heap()->undefined_value(); | 399 if (call_fun == NULL) return isolate->factory()->undefined_value(); |
| 400 |
| 372 HandleScope scope(isolate); | 401 HandleScope scope(isolate); |
| 373 JSObject* self = JSObject::cast(receiver); | 402 Handle<JSObject> self = Handle<JSObject>::cast(receiver); |
| 374 Handle<String> key(String::cast(name)); | 403 Handle<String> key = Handle<String>::cast(name); |
| 375 LOG(isolate, ApiNamedPropertyAccess("load", self, name)); | 404 LOG(isolate, ApiNamedPropertyAccess("load", *self, *name)); |
| 376 PropertyCallbackArguments args(isolate, data->data(), self, this); | 405 PropertyCallbackArguments args(isolate, data->data(), *self, *object); |
| 377 v8::Handle<v8::Value> result = | 406 v8::Handle<v8::Value> result = |
| 378 args.Call(call_fun, v8::Utils::ToLocal(key)); | 407 args.Call(call_fun, v8::Utils::ToLocal(key)); |
| 379 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 408 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 380 if (result.IsEmpty()) { | 409 if (result.IsEmpty()) { |
| 381 return isolate->heap()->undefined_value(); | 410 return isolate->factory()->undefined_value(); |
| 382 } | 411 } |
| 383 Object* return_value = *v8::Utils::OpenHandle(*result); | 412 Handle<Object> return_value = v8::Utils::OpenHandle(*result); |
| 384 return_value->VerifyApiCallResultType(); | 413 return_value->VerifyApiCallResultType(); |
| 385 return return_value; | 414 return scope.CloseAndEscape(return_value); |
| 386 } | 415 } |
| 387 | 416 |
| 388 // __defineGetter__ callback | 417 // __defineGetter__ callback |
| 389 if (structure->IsAccessorPair()) { | 418 Handle<Object> getter(Handle<AccessorPair>::cast(structure)->getter(), |
| 390 Object* getter = AccessorPair::cast(structure)->getter(); | 419 isolate); |
| 391 if (getter->IsSpecFunction()) { | 420 if (getter->IsSpecFunction()) { |
| 392 // TODO(rossberg): nicer would be to cast to some JSCallable here... | 421 // TODO(rossberg): nicer would be to cast to some JSCallable here... |
| 393 return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter)); | 422 CALL_HEAP_FUNCTION( |
| 394 } | 423 isolate, |
| 395 // Getter is not a function. | 424 object->GetPropertyWithDefinedGetter(*receiver, |
| 396 return isolate->heap()->undefined_value(); | 425 JSReceiver::cast(*getter)), |
| 426 Object); |
| 397 } | 427 } |
| 398 | 428 // Getter is not a function. |
| 399 UNREACHABLE(); | 429 return isolate->factory()->undefined_value(); |
| 400 return NULL; | |
| 401 } | 430 } |
| 402 | 431 |
| 403 | 432 |
| 404 MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw, | 433 MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw, |
| 405 Name* name_raw) { | 434 Name* name_raw) { |
| 406 Isolate* isolate = GetIsolate(); | 435 Isolate* isolate = GetIsolate(); |
| 407 HandleScope scope(isolate); | 436 HandleScope scope(isolate); |
| 408 Handle<Object> receiver(receiver_raw, isolate); | 437 Handle<Object> receiver(receiver_raw, isolate); |
| 409 Handle<Object> name(name_raw, isolate); | 438 Handle<Object> name(name_raw, isolate); |
| 410 | 439 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 486 bool has_pending_exception; | 515 bool has_pending_exception; |
| 487 Handle<Object> result = Execution::Call( | 516 Handle<Object> result = Execution::Call( |
| 488 isolate, fun, self, 0, NULL, &has_pending_exception, true); | 517 isolate, fun, self, 0, NULL, &has_pending_exception, true); |
| 489 // Check for pending exception and return the result. | 518 // Check for pending exception and return the result. |
| 490 if (has_pending_exception) return Failure::Exception(); | 519 if (has_pending_exception) return Failure::Exception(); |
| 491 return *result; | 520 return *result; |
| 492 } | 521 } |
| 493 | 522 |
| 494 | 523 |
| 495 // Only deal with CALLBACKS and INTERCEPTOR | 524 // Only deal with CALLBACKS and INTERCEPTOR |
| 496 MaybeObject* JSObject::GetPropertyWithFailedAccessCheck( | 525 Handle<Object> JSObject::GetPropertyWithFailedAccessCheck( |
| 497 Object* receiver, | 526 Handle<JSObject> object, |
| 527 Handle<Object> receiver, |
| 498 LookupResult* result, | 528 LookupResult* result, |
| 499 Name* name, | 529 Handle<Name> name, |
| 500 PropertyAttributes* attributes) { | 530 PropertyAttributes* attributes) { |
| 531 Isolate* isolate = name->GetIsolate(); |
| 501 if (result->IsProperty()) { | 532 if (result->IsProperty()) { |
| 502 switch (result->type()) { | 533 switch (result->type()) { |
| 503 case CALLBACKS: { | 534 case CALLBACKS: { |
| 504 // Only allow API accessors. | 535 // Only allow API accessors. |
| 505 Object* obj = result->GetCallbackObject(); | 536 Handle<Object> callback_obj(result->GetCallbackObject(), isolate); |
| 506 if (obj->IsAccessorInfo()) { | 537 if (callback_obj->IsAccessorInfo()) { |
| 507 AccessorInfo* info = AccessorInfo::cast(obj); | 538 if (!AccessorInfo::cast(*callback_obj)->all_can_read()) break; |
| 508 if (info->all_can_read()) { | 539 *attributes = result->GetAttributes(); |
| 509 *attributes = result->GetAttributes(); | 540 // Fall through to GetPropertyWithCallback. |
| 510 return result->holder()->GetPropertyWithCallback( | 541 } else if (callback_obj->IsAccessorPair()) { |
| 511 receiver, result->GetCallbackObject(), name); | 542 if (!AccessorPair::cast(*callback_obj)->all_can_read()) break; |
| 512 } | 543 // Fall through to GetPropertyWithCallback. |
| 513 } else if (obj->IsAccessorPair()) { | 544 } else { |
| 514 AccessorPair* pair = AccessorPair::cast(obj); | 545 break; |
| 515 if (pair->all_can_read()) { | |
| 516 return result->holder()->GetPropertyWithCallback( | |
| 517 receiver, result->GetCallbackObject(), name); | |
| 518 } | |
| 519 } | 546 } |
| 520 break; | 547 Handle<JSObject> holder(result->holder(), isolate); |
| 548 return GetPropertyWithCallback(holder, receiver, callback_obj, name); |
| 521 } | 549 } |
| 522 case NORMAL: | 550 case NORMAL: |
| 523 case FIELD: | 551 case FIELD: |
| 524 case CONSTANT: { | 552 case CONSTANT: { |
| 525 // Search ALL_CAN_READ accessors in prototype chain. | 553 // Search ALL_CAN_READ accessors in prototype chain. |
| 526 LookupResult r(GetIsolate()); | 554 LookupResult r(isolate); |
| 527 result->holder()->LookupRealNamedPropertyInPrototypes(name, &r); | 555 result->holder()->LookupRealNamedPropertyInPrototypes(*name, &r); |
| 528 if (r.IsProperty()) { | 556 if (r.IsProperty()) { |
| 529 return GetPropertyWithFailedAccessCheck(receiver, | 557 return GetPropertyWithFailedAccessCheck( |
| 530 &r, | 558 object, receiver, &r, name, attributes); |
| 531 name, | |
| 532 attributes); | |
| 533 } | 559 } |
| 534 break; | 560 break; |
| 535 } | 561 } |
| 536 case INTERCEPTOR: { | 562 case INTERCEPTOR: { |
| 537 // If the object has an interceptor, try real named properties. | 563 // If the object has an interceptor, try real named properties. |
| 538 // No access check in GetPropertyAttributeWithInterceptor. | 564 // No access check in GetPropertyAttributeWithInterceptor. |
| 539 LookupResult r(GetIsolate()); | 565 LookupResult r(isolate); |
| 540 result->holder()->LookupRealNamedProperty(name, &r); | 566 result->holder()->LookupRealNamedProperty(*name, &r); |
| 541 if (r.IsProperty()) { | 567 if (r.IsProperty()) { |
| 542 return GetPropertyWithFailedAccessCheck(receiver, | 568 return GetPropertyWithFailedAccessCheck( |
| 543 &r, | 569 object, receiver, &r, name, attributes); |
| 544 name, | |
| 545 attributes); | |
| 546 } | 570 } |
| 547 break; | 571 break; |
| 548 } | 572 } |
| 549 default: | 573 default: |
| 550 UNREACHABLE(); | 574 UNREACHABLE(); |
| 551 } | 575 } |
| 552 } | 576 } |
| 553 | 577 |
| 554 // No accessible property found. | 578 // No accessible property found. |
| 555 *attributes = ABSENT; | 579 *attributes = ABSENT; |
| 556 Heap* heap = name->GetHeap(); | 580 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_GET); |
| 557 Isolate* isolate = heap->isolate(); | 581 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 558 isolate->ReportFailedAccessCheck(this, v8::ACCESS_GET); | 582 return isolate->factory()->undefined_value(); |
| 559 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | |
| 560 return heap->undefined_value(); | |
| 561 } | 583 } |
| 562 | 584 |
| 563 | 585 |
| 564 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck( | 586 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck( |
| 565 Object* receiver, | 587 Object* receiver, |
| 566 LookupResult* result, | 588 LookupResult* result, |
| 567 Name* name, | 589 Name* name, |
| 568 bool continue_search) { | 590 bool continue_search) { |
| 569 if (result->IsProperty()) { | 591 if (result->IsProperty()) { |
| 570 switch (result->type()) { | 592 switch (result->type()) { |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 796 LookupResult* result, | 818 LookupResult* result, |
| 797 Handle<Name> key, | 819 Handle<Name> key, |
| 798 PropertyAttributes* attributes) { | 820 PropertyAttributes* attributes) { |
| 799 Isolate* isolate = result->isolate(); | 821 Isolate* isolate = result->isolate(); |
| 800 CALL_HEAP_FUNCTION_PASS_EXCEPTION( | 822 CALL_HEAP_FUNCTION_PASS_EXCEPTION( |
| 801 isolate, | 823 isolate, |
| 802 object->GetProperty(*receiver, result, *key, attributes)); | 824 object->GetProperty(*receiver, result, *key, attributes)); |
| 803 } | 825 } |
| 804 | 826 |
| 805 | 827 |
| 828 // TODO(yangguo): handlify this and get rid of. |
| 806 MaybeObject* Object::GetProperty(Object* receiver, | 829 MaybeObject* Object::GetProperty(Object* receiver, |
| 807 LookupResult* result, | 830 LookupResult* result, |
| 808 Name* name, | 831 Name* name, |
| 809 PropertyAttributes* attributes) { | 832 PropertyAttributes* attributes) { |
| 810 Isolate* isolate = name->GetIsolate(); | 833 Isolate* isolate = name->GetIsolate(); |
| 811 Heap* heap = isolate->heap(); | 834 Heap* heap = isolate->heap(); |
| 812 | 835 |
| 813 #ifdef DEBUG | 836 #ifdef DEBUG |
| 814 // TODO(mstarzinger): Only because of the AssertNoContextChange, drop as soon | 837 // TODO(mstarzinger): Only because of the AssertNoContextChange, drop as soon |
| 815 // as this method has been fully handlified. | 838 // as this method has been fully handlified. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 834 ASSERT(this != this->GetPrototype(isolate)); | 857 ASSERT(this != this->GetPrototype(isolate)); |
| 835 for (Object* current = this; | 858 for (Object* current = this; |
| 836 true; | 859 true; |
| 837 current = current->GetPrototype(isolate)) { | 860 current = current->GetPrototype(isolate)) { |
| 838 if (current->IsAccessCheckNeeded()) { | 861 if (current->IsAccessCheckNeeded()) { |
| 839 // Check if we're allowed to read from the current object. Note | 862 // 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 | 863 // that even though we may not actually end up loading the named |
| 841 // property from the current object, we still check that we have | 864 // property from the current object, we still check that we have |
| 842 // access to it. | 865 // access to it. |
| 843 JSObject* checked = JSObject::cast(current); | 866 JSObject* checked = JSObject::cast(current); |
| 844 if (!heap->isolate()->MayNamedAccess(checked, name, v8::ACCESS_GET)) { | 867 if (!isolate->MayNamedAccess(checked, name, v8::ACCESS_GET)) { |
| 845 return checked->GetPropertyWithFailedAccessCheck(receiver, | 868 HandleScope scope(isolate); |
| 846 result, | 869 Handle<Object> value = JSObject::GetPropertyWithFailedAccessCheck( |
| 847 name, | 870 handle(checked, isolate), |
| 848 attributes); | 871 handle(receiver, isolate), |
| 872 result, |
| 873 handle(name, isolate), |
| 874 attributes); |
| 875 RETURN_IF_EMPTY_HANDLE(isolate, value); |
| 876 return *value; |
| 849 } | 877 } |
| 850 } | 878 } |
| 851 // Stop traversing the chain once we reach the last object in the | 879 // 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 | 880 // chain; either the holder of the result or null in case of an |
| 853 // absent property. | 881 // absent property. |
| 854 if (current == last) break; | 882 if (current == last) break; |
| 855 } | 883 } |
| 856 } | 884 } |
| 857 | 885 |
| 858 if (!result->IsProperty()) { | 886 if (!result->IsProperty()) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 869 case FIELD: { | 897 case FIELD: { |
| 870 MaybeObject* maybe_result = result->holder()->FastPropertyAt( | 898 MaybeObject* maybe_result = result->holder()->FastPropertyAt( |
| 871 result->representation(), | 899 result->representation(), |
| 872 result->GetFieldIndex().field_index()); | 900 result->GetFieldIndex().field_index()); |
| 873 if (!maybe_result->To(&value)) return maybe_result; | 901 if (!maybe_result->To(&value)) return maybe_result; |
| 874 ASSERT(!value->IsTheHole() || result->IsReadOnly()); | 902 ASSERT(!value->IsTheHole() || result->IsReadOnly()); |
| 875 return value->IsTheHole() ? heap->undefined_value() : value; | 903 return value->IsTheHole() ? heap->undefined_value() : value; |
| 876 } | 904 } |
| 877 case CONSTANT: | 905 case CONSTANT: |
| 878 return result->GetConstant(); | 906 return result->GetConstant(); |
| 879 case CALLBACKS: | 907 case CALLBACKS: { |
| 880 return result->holder()->GetPropertyWithCallback( | 908 HandleScope scope(isolate); |
| 881 receiver, result->GetCallbackObject(), name); | 909 Handle<Object> value = JSObject::GetPropertyWithCallback( |
| 910 handle(result->holder(), isolate), |
| 911 handle(receiver, isolate), |
| 912 handle(result->GetCallbackObject(), isolate), |
| 913 handle(name, isolate)); |
| 914 RETURN_IF_EMPTY_HANDLE(isolate, value); |
| 915 return *value; |
| 916 } |
| 882 case HANDLER: | 917 case HANDLER: |
| 883 return result->proxy()->GetPropertyWithHandler(receiver, name); | 918 return result->proxy()->GetPropertyWithHandler(receiver, name); |
| 884 case INTERCEPTOR: | 919 case INTERCEPTOR: { |
| 885 return result->holder()->GetPropertyWithInterceptor( | 920 HandleScope scope(isolate); |
| 886 receiver, name, attributes); | 921 Handle<Object> value = JSObject::GetPropertyWithInterceptor( |
| 922 handle(result->holder(), isolate), |
| 923 handle(receiver, isolate), |
| 924 handle(name, isolate), |
| 925 attributes); |
| 926 RETURN_IF_EMPTY_HANDLE(isolate, value); |
| 927 return *value; |
| 928 } |
| 887 case TRANSITION: | 929 case TRANSITION: |
| 888 case NONEXISTENT: | 930 case NONEXISTENT: |
| 889 UNREACHABLE(); | 931 UNREACHABLE(); |
| 890 break; | 932 break; |
| 891 } | 933 } |
| 892 UNREACHABLE(); | 934 UNREACHABLE(); |
| 893 return NULL; | 935 return NULL; |
| 894 } | 936 } |
| 895 | 937 |
| 896 | 938 |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 default: | 1197 default: |
| 1156 return this; | 1198 return this; |
| 1157 } | 1199 } |
| 1158 } | 1200 } |
| 1159 | 1201 |
| 1160 | 1202 |
| 1161 bool String::MakeExternal(v8::String::ExternalStringResource* resource) { | 1203 bool String::MakeExternal(v8::String::ExternalStringResource* resource) { |
| 1162 // Externalizing twice leaks the external resource, so it's | 1204 // Externalizing twice leaks the external resource, so it's |
| 1163 // prohibited by the API. | 1205 // prohibited by the API. |
| 1164 ASSERT(!this->IsExternalString()); | 1206 ASSERT(!this->IsExternalString()); |
| 1165 #ifdef DEBUG | 1207 #ifdef ENABLE_SLOW_ASSERTS |
| 1166 if (FLAG_enable_slow_asserts) { | 1208 if (FLAG_enable_slow_asserts) { |
| 1167 // Assert that the resource and the string are equivalent. | 1209 // Assert that the resource and the string are equivalent. |
| 1168 ASSERT(static_cast<size_t>(this->length()) == resource->length()); | 1210 ASSERT(static_cast<size_t>(this->length()) == resource->length()); |
| 1169 ScopedVector<uc16> smart_chars(this->length()); | 1211 ScopedVector<uc16> smart_chars(this->length()); |
| 1170 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); | 1212 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); |
| 1171 ASSERT(memcmp(smart_chars.start(), | 1213 ASSERT(memcmp(smart_chars.start(), |
| 1172 resource->data(), | 1214 resource->data(), |
| 1173 resource->length() * sizeof(smart_chars[0])) == 0); | 1215 resource->length() * sizeof(smart_chars[0])) == 0); |
| 1174 } | 1216 } |
| 1175 #endif // DEBUG | 1217 #endif // DEBUG |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1212 heap->CreateFillerObjectAt(this->address() + new_size, size - new_size); | 1254 heap->CreateFillerObjectAt(this->address() + new_size, size - new_size); |
| 1213 if (Marking::IsBlack(Marking::MarkBitFrom(this))) { | 1255 if (Marking::IsBlack(Marking::MarkBitFrom(this))) { |
| 1214 MemoryChunk::IncrementLiveBytesFromMutator(this->address(), | 1256 MemoryChunk::IncrementLiveBytesFromMutator(this->address(), |
| 1215 new_size - size); | 1257 new_size - size); |
| 1216 } | 1258 } |
| 1217 return true; | 1259 return true; |
| 1218 } | 1260 } |
| 1219 | 1261 |
| 1220 | 1262 |
| 1221 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) { | 1263 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) { |
| 1222 #ifdef DEBUG | 1264 #ifdef ENABLE_SLOW_ASSERTS |
| 1223 if (FLAG_enable_slow_asserts) { | 1265 if (FLAG_enable_slow_asserts) { |
| 1224 // Assert that the resource and the string are equivalent. | 1266 // Assert that the resource and the string are equivalent. |
| 1225 ASSERT(static_cast<size_t>(this->length()) == resource->length()); | 1267 ASSERT(static_cast<size_t>(this->length()) == resource->length()); |
| 1226 if (this->IsTwoByteRepresentation()) { | 1268 if (this->IsTwoByteRepresentation()) { |
| 1227 ScopedVector<uint16_t> smart_chars(this->length()); | 1269 ScopedVector<uint16_t> smart_chars(this->length()); |
| 1228 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); | 1270 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); |
| 1229 ASSERT(String::IsOneByte(smart_chars.start(), this->length())); | 1271 ASSERT(String::IsOneByte(smart_chars.start(), this->length())); |
| 1230 } | 1272 } |
| 1231 ScopedVector<char> smart_chars(this->length()); | 1273 ScopedVector<char> smart_chars(this->length()); |
| 1232 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); | 1274 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); |
| (...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1697 } | 1739 } |
| 1698 break; | 1740 break; |
| 1699 } | 1741 } |
| 1700 return; | 1742 return; |
| 1701 } | 1743 } |
| 1702 | 1744 |
| 1703 switch (type) { | 1745 switch (type) { |
| 1704 case FIXED_ARRAY_TYPE: | 1746 case FIXED_ARRAY_TYPE: |
| 1705 FixedArray::BodyDescriptor::IterateBody(this, object_size, v); | 1747 FixedArray::BodyDescriptor::IterateBody(this, object_size, v); |
| 1706 break; | 1748 break; |
| 1749 case CONSTANT_POOL_ARRAY_TYPE: |
| 1750 reinterpret_cast<ConstantPoolArray*>(this)->ConstantPoolIterateBody(v); |
| 1751 break; |
| 1707 case FIXED_DOUBLE_ARRAY_TYPE: | 1752 case FIXED_DOUBLE_ARRAY_TYPE: |
| 1708 break; | 1753 break; |
| 1709 case JS_OBJECT_TYPE: | 1754 case JS_OBJECT_TYPE: |
| 1710 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: | 1755 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: |
| 1711 case JS_GENERATOR_OBJECT_TYPE: | 1756 case JS_GENERATOR_OBJECT_TYPE: |
| 1712 case JS_MODULE_TYPE: | 1757 case JS_MODULE_TYPE: |
| 1713 case JS_VALUE_TYPE: | 1758 case JS_VALUE_TYPE: |
| 1714 case JS_DATE_TYPE: | 1759 case JS_DATE_TYPE: |
| 1715 case JS_ARRAY_TYPE: | 1760 case JS_ARRAY_TYPE: |
| 1716 case JS_ARRAY_BUFFER_TYPE: | 1761 case JS_ARRAY_BUFFER_TYPE: |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2093 } else { | 2138 } else { |
| 2094 // Normalize the object to prevent very large instance descriptors. | 2139 // Normalize the object to prevent very large instance descriptors. |
| 2095 // This eliminates unwanted N^2 allocation and lookup behavior. | 2140 // This eliminates unwanted N^2 allocation and lookup behavior. |
| 2096 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 2141 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 2097 AddSlowProperty(object, name, value, attributes); | 2142 AddSlowProperty(object, name, value, attributes); |
| 2098 } | 2143 } |
| 2099 } else { | 2144 } else { |
| 2100 AddSlowProperty(object, name, value, attributes); | 2145 AddSlowProperty(object, name, value, attributes); |
| 2101 } | 2146 } |
| 2102 | 2147 |
| 2103 if (FLAG_harmony_observation && object->map()->is_observed()) { | 2148 if (FLAG_harmony_observation && |
| 2149 object->map()->is_observed() && |
| 2150 *name != isolate->heap()->hidden_string()) { |
| 2104 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 2151 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 2105 EnqueueChangeRecord(object, "new", name, old_value); | 2152 EnqueueChangeRecord(object, "new", name, old_value); |
| 2106 } | 2153 } |
| 2107 | 2154 |
| 2108 return value; | 2155 return value; |
| 2109 } | 2156 } |
| 2110 | 2157 |
| 2111 | 2158 |
| 2112 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, | 2159 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, |
| 2113 const char* type_str, | 2160 const char* type_str, |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2244 elms->set_length(len - to_trim); | 2291 elms->set_length(len - to_trim); |
| 2245 | 2292 |
| 2246 // Maintain marking consistency for IncrementalMarking. | 2293 // Maintain marking consistency for IncrementalMarking. |
| 2247 if (Marking::IsBlack(Marking::MarkBitFrom(elms))) { | 2294 if (Marking::IsBlack(Marking::MarkBitFrom(elms))) { |
| 2248 if (trim_mode == FROM_GC) { | 2295 if (trim_mode == FROM_GC) { |
| 2249 MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta); | 2296 MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta); |
| 2250 } else { | 2297 } else { |
| 2251 MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta); | 2298 MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta); |
| 2252 } | 2299 } |
| 2253 } | 2300 } |
| 2301 |
| 2302 // The array may not be moved during GC, |
| 2303 // and size has to be adjusted nevertheless. |
| 2304 HeapProfiler* profiler = heap->isolate()->heap_profiler(); |
| 2305 if (profiler->is_tracking_allocations()) { |
| 2306 profiler->UpdateObjectSizeEvent(elms->address(), elms->Size()); |
| 2307 } |
| 2254 } | 2308 } |
| 2255 | 2309 |
| 2256 | 2310 |
| 2257 bool Map::InstancesNeedRewriting(Map* target, | 2311 bool Map::InstancesNeedRewriting(Map* target, |
| 2258 int target_number_of_fields, | 2312 int target_number_of_fields, |
| 2259 int target_inobject, | 2313 int target_inobject, |
| 2260 int target_unused) { | 2314 int target_unused) { |
| 2261 // If fields were added (or removed), rewrite the instance. | 2315 // If fields were added (or removed), rewrite the instance. |
| 2262 int number_of_fields = NumberOfFields(); | 2316 int number_of_fields = NumberOfFields(); |
| 2263 ASSERT(target_number_of_fields >= number_of_fields); | 2317 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. | 2435 // size and install the backing store into the object. |
| 2382 if (external > 0) { | 2436 if (external > 0) { |
| 2383 RightTrimFixedArray<FROM_MUTATOR>(isolate->heap(), *array, inobject); | 2437 RightTrimFixedArray<FROM_MUTATOR>(isolate->heap(), *array, inobject); |
| 2384 object->set_properties(*array); | 2438 object->set_properties(*array); |
| 2385 } | 2439 } |
| 2386 | 2440 |
| 2387 object->set_map(*new_map); | 2441 object->set_map(*new_map); |
| 2388 } | 2442 } |
| 2389 | 2443 |
| 2390 | 2444 |
| 2445 Handle<TransitionArray> Map::AddTransition(Handle<Map> map, |
| 2446 Handle<Name> key, |
| 2447 Handle<Map> target, |
| 2448 SimpleTransitionFlag flag) { |
| 2449 CALL_HEAP_FUNCTION(map->GetIsolate(), |
| 2450 map->AddTransition(*key, *target, flag), |
| 2451 TransitionArray); |
| 2452 } |
| 2453 |
| 2454 |
| 2391 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, | 2455 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, |
| 2392 int modify_index, | 2456 int modify_index, |
| 2393 Representation new_representation, | 2457 Representation new_representation, |
| 2394 StoreMode store_mode) { | 2458 StoreMode store_mode) { |
| 2395 Handle<Map> new_map = Map::GeneralizeRepresentation( | 2459 Handle<Map> new_map = Map::GeneralizeRepresentation( |
| 2396 handle(object->map()), modify_index, new_representation, store_mode); | 2460 handle(object->map()), modify_index, new_representation, store_mode); |
| 2397 if (object->map() == *new_map) return; | 2461 if (object->map() == *new_map) return; |
| 2398 return MigrateToMap(object, new_map); | 2462 return MigrateToMap(object, new_map); |
| 2399 } | 2463 } |
| 2400 | 2464 |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2681 for (; descriptor < descriptors; descriptor++) { | 2745 for (; descriptor < descriptors; descriptor++) { |
| 2682 new_map = Map::CopyInstallDescriptors(new_map, descriptor, new_descriptors); | 2746 new_map = Map::CopyInstallDescriptors(new_map, descriptor, new_descriptors); |
| 2683 new_map->set_migration_target(true); | 2747 new_map->set_migration_target(true); |
| 2684 } | 2748 } |
| 2685 | 2749 |
| 2686 new_map->set_owns_descriptors(true); | 2750 new_map->set_owns_descriptors(true); |
| 2687 return new_map; | 2751 return new_map; |
| 2688 } | 2752 } |
| 2689 | 2753 |
| 2690 | 2754 |
| 2755 // Generalize the representation of all FIELD descriptors. |
| 2756 Handle<Map> Map::GeneralizeAllFieldRepresentations( |
| 2757 Handle<Map> map, |
| 2758 Representation new_representation) { |
| 2759 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
| 2760 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { |
| 2761 PropertyDetails details = descriptors->GetDetails(i); |
| 2762 if (details.type() == FIELD) { |
| 2763 map = GeneralizeRepresentation(map, i, new_representation, FORCE_FIELD); |
| 2764 } |
| 2765 } |
| 2766 return map; |
| 2767 } |
| 2768 |
| 2769 |
| 2691 Map* Map::CurrentMapForDeprecated() { | 2770 Map* Map::CurrentMapForDeprecated() { |
| 2692 DisallowHeapAllocation no_allocation; | 2771 DisallowHeapAllocation no_allocation; |
| 2693 if (!is_deprecated()) return this; | 2772 if (!is_deprecated()) return this; |
| 2694 | 2773 |
| 2695 DescriptorArray* old_descriptors = instance_descriptors(); | 2774 DescriptorArray* old_descriptors = instance_descriptors(); |
| 2696 | 2775 |
| 2697 int descriptors = NumberOfOwnDescriptors(); | 2776 int descriptors = NumberOfOwnDescriptors(); |
| 2698 Map* root_map = FindRootMap(); | 2777 Map* root_map = FindRootMap(); |
| 2699 | 2778 |
| 2700 // Check the state of the root map. | 2779 // 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( | 4043 Handle<Object> error = isolate->factory()->NewTypeError( |
| 3965 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); | 4044 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); |
| 3966 isolate->Throw(*error); | 4045 isolate->Throw(*error); |
| 3967 return Handle<Object>(); | 4046 return Handle<Object>(); |
| 3968 } else { | 4047 } else { |
| 3969 return value; | 4048 return value; |
| 3970 } | 4049 } |
| 3971 } | 4050 } |
| 3972 | 4051 |
| 3973 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 4052 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 3974 if (FLAG_harmony_observation && | 4053 bool is_observed = FLAG_harmony_observation && |
| 3975 object->map()->is_observed() && lookup->IsDataProperty()) { | 4054 object->map()->is_observed() && |
| 4055 *name != isolate->heap()->hidden_string(); |
| 4056 if (is_observed && lookup->IsDataProperty()) { |
| 3976 old_value = Object::GetProperty(object, name); | 4057 old_value = Object::GetProperty(object, name); |
| 3977 } | 4058 } |
| 3978 | 4059 |
| 3979 // This is a real property that is not read-only, or it is a | 4060 // 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. | 4061 // transition or null descriptor and there are no setters in the prototypes. |
| 3981 Handle<Object> result = value; | 4062 Handle<Object> result = value; |
| 3982 switch (lookup->type()) { | 4063 switch (lookup->type()) { |
| 3983 case NORMAL: | 4064 case NORMAL: |
| 3984 SetNormalizedProperty(handle(lookup->holder()), lookup, value); | 4065 SetNormalizedProperty(handle(lookup->holder()), lookup, value); |
| 3985 break; | 4066 break; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4004 result = SetPropertyUsingTransition(handle(lookup->holder()), lookup, | 4085 result = SetPropertyUsingTransition(handle(lookup->holder()), lookup, |
| 4005 name, value, attributes); | 4086 name, value, attributes); |
| 4006 break; | 4087 break; |
| 4007 case HANDLER: | 4088 case HANDLER: |
| 4008 case NONEXISTENT: | 4089 case NONEXISTENT: |
| 4009 UNREACHABLE(); | 4090 UNREACHABLE(); |
| 4010 } | 4091 } |
| 4011 | 4092 |
| 4012 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>()); | 4093 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>()); |
| 4013 | 4094 |
| 4014 if (FLAG_harmony_observation && object->map()->is_observed()) { | 4095 if (is_observed) { |
| 4015 if (lookup->IsTransition()) { | 4096 if (lookup->IsTransition()) { |
| 4016 EnqueueChangeRecord(object, "new", name, old_value); | 4097 EnqueueChangeRecord(object, "new", name, old_value); |
| 4017 } else { | 4098 } else { |
| 4018 LookupResult new_lookup(isolate); | 4099 LookupResult new_lookup(isolate); |
| 4019 object->LocalLookup(*name, &new_lookup, true); | 4100 object->LocalLookup(*name, &new_lookup, true); |
| 4020 if (new_lookup.IsDataProperty()) { | 4101 if (new_lookup.IsDataProperty()) { |
| 4021 Handle<Object> new_value = Object::GetProperty(object, name); | 4102 Handle<Object> new_value = Object::GetProperty(object, name); |
| 4022 if (!new_value->SameValue(*old_value)) { | 4103 if (!new_value->SameValue(*old_value)) { |
| 4023 EnqueueChangeRecord(object, "updated", name, old_value); | 4104 EnqueueChangeRecord(object, "updated", name, old_value); |
| 4024 } | 4105 } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4105 | 4186 |
| 4106 // Check for accessor in prototype chain removed here in clone. | 4187 // Check for accessor in prototype chain removed here in clone. |
| 4107 if (!lookup.IsFound()) { | 4188 if (!lookup.IsFound()) { |
| 4108 // Neither properties nor transitions found. | 4189 // Neither properties nor transitions found. |
| 4109 return AddProperty(object, name, value, attributes, kNonStrictMode, | 4190 return AddProperty(object, name, value, attributes, kNonStrictMode, |
| 4110 MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode); | 4191 MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode); |
| 4111 } | 4192 } |
| 4112 | 4193 |
| 4113 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 4194 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 4114 PropertyAttributes old_attributes = ABSENT; | 4195 PropertyAttributes old_attributes = ABSENT; |
| 4115 bool is_observed = FLAG_harmony_observation && object->map()->is_observed(); | 4196 bool is_observed = FLAG_harmony_observation && |
| 4197 object->map()->is_observed() && |
| 4198 *name != isolate->heap()->hidden_string(); |
| 4116 if (is_observed && lookup.IsProperty()) { | 4199 if (is_observed && lookup.IsProperty()) { |
| 4117 if (lookup.IsDataProperty()) old_value = | 4200 if (lookup.IsDataProperty()) old_value = |
| 4118 Object::GetProperty(object, name); | 4201 Object::GetProperty(object, name); |
| 4119 old_attributes = lookup.GetAttributes(); | 4202 old_attributes = lookup.GetAttributes(); |
| 4120 } | 4203 } |
| 4121 | 4204 |
| 4122 // Check of IsReadOnly removed from here in clone. | 4205 // Check of IsReadOnly removed from here in clone. |
| 4123 switch (lookup.type()) { | 4206 switch (lookup.type()) { |
| 4124 case NORMAL: | 4207 case NORMAL: |
| 4125 ReplaceSlowProperty(object, name, value, attributes); | 4208 ReplaceSlowProperty(object, name, value, attributes); |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4391 } | 4474 } |
| 4392 if (pt->IsNull()) return ABSENT; | 4475 if (pt->IsNull()) return ABSENT; |
| 4393 return JSObject::cast(pt)->GetElementAttributeWithReceiver( | 4476 return JSObject::cast(pt)->GetElementAttributeWithReceiver( |
| 4394 receiver, index, true); | 4477 receiver, index, true); |
| 4395 } | 4478 } |
| 4396 | 4479 |
| 4397 | 4480 |
| 4398 Handle<Map> NormalizedMapCache::Get(Handle<NormalizedMapCache> cache, | 4481 Handle<Map> NormalizedMapCache::Get(Handle<NormalizedMapCache> cache, |
| 4399 Handle<JSObject> obj, | 4482 Handle<JSObject> obj, |
| 4400 PropertyNormalizationMode mode) { | 4483 PropertyNormalizationMode mode) { |
| 4401 Map* fast = obj->map(); | 4484 int index = obj->map()->Hash() % kEntries; |
| 4402 int index = fast->Hash() % kEntries; | 4485 Handle<Object> result = handle(cache->get(index), cache->GetIsolate()); |
| 4403 Object* result = cache->get(index); | |
| 4404 if (result->IsMap() && | 4486 if (result->IsMap() && |
| 4405 Map::cast(result)->EquivalentToForNormalization(fast, mode)) { | 4487 Handle<Map>::cast(result)->EquivalentToForNormalization(obj->map(), |
| 4488 mode)) { |
| 4406 #ifdef VERIFY_HEAP | 4489 #ifdef VERIFY_HEAP |
| 4407 if (FLAG_verify_heap) { | 4490 if (FLAG_verify_heap) { |
| 4408 Map::cast(result)->SharedMapVerify(); | 4491 Handle<Map>::cast(result)->SharedMapVerify(); |
| 4409 } | 4492 } |
| 4410 #endif | 4493 #endif |
| 4411 #ifdef DEBUG | 4494 #ifdef ENABLE_SLOW_ASSERTS |
| 4412 if (FLAG_enable_slow_asserts) { | 4495 if (FLAG_enable_slow_asserts) { |
| 4413 // The cached map should match newly created normalized map bit-by-bit, | 4496 // 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 | 4497 // except for the code cache, which can contain some ics which can be |
| 4415 // applied to the shared map. | 4498 // applied to the shared map. |
| 4416 Object* fresh; | 4499 Handle<Map> fresh = Map::CopyNormalized(handle(obj->map()), mode, |
| 4417 MaybeObject* maybe_fresh = | 4500 SHARED_NORMALIZED_MAP); |
| 4418 fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP); | 4501 |
| 4419 if (maybe_fresh->ToObject(&fresh)) { | 4502 ASSERT(memcmp(fresh->address(), |
| 4420 ASSERT(memcmp(Map::cast(fresh)->address(), | 4503 Handle<Map>::cast(result)->address(), |
| 4421 Map::cast(result)->address(), | 4504 Map::kCodeCacheOffset) == 0); |
| 4422 Map::kCodeCacheOffset) == 0); | 4505 STATIC_ASSERT(Map::kDependentCodeOffset == |
| 4423 STATIC_ASSERT(Map::kDependentCodeOffset == | 4506 Map::kCodeCacheOffset + kPointerSize); |
| 4424 Map::kCodeCacheOffset + kPointerSize); | 4507 int offset = Map::kDependentCodeOffset + kPointerSize; |
| 4425 int offset = Map::kDependentCodeOffset + kPointerSize; | 4508 ASSERT(memcmp(fresh->address() + offset, |
| 4426 ASSERT(memcmp(Map::cast(fresh)->address() + offset, | 4509 Handle<Map>::cast(result)->address() + offset, |
| 4427 Map::cast(result)->address() + offset, | 4510 Map::kSize - offset) == 0); |
| 4428 Map::kSize - offset) == 0); | |
| 4429 } | |
| 4430 } | 4511 } |
| 4431 #endif | 4512 #endif |
| 4432 return handle(Map::cast(result)); | 4513 return Handle<Map>::cast(result); |
| 4433 } | 4514 } |
| 4434 | 4515 |
| 4435 Isolate* isolate = cache->GetIsolate(); | 4516 Isolate* isolate = cache->GetIsolate(); |
| 4436 Handle<Map> map = Map::CopyNormalized(handle(fast), mode, | 4517 Handle<Map> map = Map::CopyNormalized(handle(obj->map()), mode, |
| 4437 SHARED_NORMALIZED_MAP); | 4518 SHARED_NORMALIZED_MAP); |
| 4438 ASSERT(map->is_dictionary_map()); | 4519 ASSERT(map->is_dictionary_map()); |
| 4439 cache->set(index, *map); | 4520 cache->set(index, *map); |
| 4440 isolate->counters()->normalized_maps()->Increment(); | 4521 isolate->counters()->normalized_maps()->Increment(); |
| 4441 | 4522 |
| 4442 return map; | 4523 return map; |
| 4443 } | 4524 } |
| 4444 | 4525 |
| 4445 | 4526 |
| 4446 void NormalizedMapCache::Clear() { | 4527 void NormalizedMapCache::Clear() { |
| (...skipping 722 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5169 Handle<Object> args[2] = { name, object }; | 5250 Handle<Object> args[2] = { name, object }; |
| 5170 Handle<Object> error = isolate->factory()->NewTypeError( | 5251 Handle<Object> error = isolate->factory()->NewTypeError( |
| 5171 "strict_delete_property", HandleVector(args, ARRAY_SIZE(args))); | 5252 "strict_delete_property", HandleVector(args, ARRAY_SIZE(args))); |
| 5172 isolate->Throw(*error); | 5253 isolate->Throw(*error); |
| 5173 return Handle<Object>(); | 5254 return Handle<Object>(); |
| 5174 } | 5255 } |
| 5175 return isolate->factory()->false_value(); | 5256 return isolate->factory()->false_value(); |
| 5176 } | 5257 } |
| 5177 | 5258 |
| 5178 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 5259 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 5179 bool is_observed = FLAG_harmony_observation && object->map()->is_observed(); | 5260 bool is_observed = FLAG_harmony_observation && |
| 5261 object->map()->is_observed() && |
| 5262 *name != isolate->heap()->hidden_string(); |
| 5180 if (is_observed && lookup.IsDataProperty()) { | 5263 if (is_observed && lookup.IsDataProperty()) { |
| 5181 old_value = Object::GetProperty(object, name); | 5264 old_value = Object::GetProperty(object, name); |
| 5182 } | 5265 } |
| 5183 Handle<Object> result; | 5266 Handle<Object> result; |
| 5184 | 5267 |
| 5185 // Check for interceptor. | 5268 // Check for interceptor. |
| 5186 if (lookup.IsInterceptor()) { | 5269 if (lookup.IsInterceptor()) { |
| 5187 // Skip interceptor if forcing a deletion. | 5270 // Skip interceptor if forcing a deletion. |
| 5188 if (mode == FORCE_DELETION) { | 5271 if (mode == FORCE_DELETION) { |
| 5189 result = DeletePropertyPostInterceptor(object, name, mode); | 5272 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 | 5614 // Make sure we never go back to the fast case |
| 5532 dictionary->set_requires_slow_elements(); | 5615 dictionary->set_requires_slow_elements(); |
| 5533 // Freeze all elements in the dictionary | 5616 // Freeze all elements in the dictionary |
| 5534 FreezeDictionary(dictionary); | 5617 FreezeDictionary(dictionary); |
| 5535 } | 5618 } |
| 5536 | 5619 |
| 5537 return object; | 5620 return object; |
| 5538 } | 5621 } |
| 5539 | 5622 |
| 5540 | 5623 |
| 5541 MUST_USE_RESULT MaybeObject* JSObject::SetObserved(Isolate* isolate) { | 5624 void JSObject::SetObserved(Handle<JSObject> object) { |
| 5542 if (map()->is_observed()) | 5625 Isolate* isolate = object->GetIsolate(); |
| 5543 return isolate->heap()->undefined_value(); | |
| 5544 | 5626 |
| 5545 Heap* heap = isolate->heap(); | 5627 if (object->map()->is_observed()) |
| 5628 return; |
| 5546 | 5629 |
| 5547 if (!HasExternalArrayElements()) { | 5630 if (!object->HasExternalArrayElements()) { |
| 5548 // Go to dictionary mode, so that we don't skip map checks. | 5631 // Go to dictionary mode, so that we don't skip map checks. |
| 5549 MaybeObject* maybe = NormalizeElements(); | 5632 NormalizeElements(object); |
| 5550 if (maybe->IsFailure()) return maybe; | 5633 ASSERT(!object->HasFastElements()); |
| 5551 ASSERT(!HasFastElements()); | |
| 5552 } | 5634 } |
| 5553 | 5635 |
| 5554 LookupResult result(isolate); | 5636 LookupResult result(isolate); |
| 5555 map()->LookupTransition(this, heap->observed_symbol(), &result); | 5637 object->map()->LookupTransition(*object, |
| 5638 isolate->heap()->observed_symbol(), |
| 5639 &result); |
| 5556 | 5640 |
| 5557 Map* new_map; | 5641 Handle<Map> new_map; |
| 5558 if (result.IsTransition()) { | 5642 if (result.IsTransition()) { |
| 5559 new_map = result.GetTransitionTarget(); | 5643 new_map = handle(result.GetTransitionTarget()); |
| 5560 ASSERT(new_map->is_observed()); | 5644 ASSERT(new_map->is_observed()); |
| 5561 } else if (map()->CanHaveMoreTransitions()) { | 5645 } else if (object->map()->CanHaveMoreTransitions()) { |
| 5562 MaybeObject* maybe_new_map = map()->CopyForObserved(); | 5646 new_map = Map::CopyForObserved(handle(object->map())); |
| 5563 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
| 5564 } else { | 5647 } else { |
| 5565 MaybeObject* maybe_copy = map()->Copy(); | 5648 new_map = Map::Copy(handle(object->map())); |
| 5566 if (!maybe_copy->To(&new_map)) return maybe_copy; | |
| 5567 new_map->set_is_observed(true); | 5649 new_map->set_is_observed(true); |
| 5568 } | 5650 } |
| 5569 set_map(new_map); | 5651 object->set_map(*new_map); |
| 5570 | |
| 5571 return heap->undefined_value(); | |
| 5572 } | 5652 } |
| 5573 | 5653 |
| 5574 | 5654 |
| 5655 Handle<JSObject> JSObject::Copy(Handle<JSObject> object, |
| 5656 Handle<AllocationSite> site) { |
| 5657 Isolate* isolate = object->GetIsolate(); |
| 5658 CALL_HEAP_FUNCTION(isolate, |
| 5659 isolate->heap()->CopyJSObject(*object, *site), JSObject); |
| 5660 } |
| 5661 |
| 5662 |
| 5575 Handle<JSObject> JSObject::Copy(Handle<JSObject> object) { | 5663 Handle<JSObject> JSObject::Copy(Handle<JSObject> object) { |
| 5576 Isolate* isolate = object->GetIsolate(); | 5664 Isolate* isolate = object->GetIsolate(); |
| 5577 CALL_HEAP_FUNCTION(isolate, | 5665 CALL_HEAP_FUNCTION(isolate, |
| 5578 isolate->heap()->CopyJSObject(*object), JSObject); | 5666 isolate->heap()->CopyJSObject(*object), JSObject); |
| 5579 } | 5667 } |
| 5580 | 5668 |
| 5581 | 5669 |
| 5582 class JSObjectWalkVisitor { | 5670 class JSObjectWalkVisitor { |
| 5583 public: | 5671 public: |
| 5584 explicit JSObjectWalkVisitor() {} | 5672 explicit JSObjectWalkVisitor(AllocationSiteContext* site_context) : |
| 5673 site_context_(site_context) {} |
| 5585 virtual ~JSObjectWalkVisitor() {} | 5674 virtual ~JSObjectWalkVisitor() {} |
| 5586 | 5675 |
| 5587 Handle<JSObject> Visit(Handle<JSObject> object) { | 5676 Handle<JSObject> Visit(Handle<JSObject> object) { |
| 5588 return StructureWalk(object); | 5677 return StructureWalk(object); |
| 5589 } | 5678 } |
| 5590 | 5679 |
| 5591 // Returns true if the visitor is a copying visitor. | |
| 5592 virtual bool is_copying() = 0; | 5680 virtual bool is_copying() = 0; |
| 5593 | 5681 |
| 5594 protected: | 5682 protected: |
| 5595 Handle<JSObject> StructureWalk(Handle<JSObject> object); | 5683 Handle<JSObject> StructureWalk(Handle<JSObject> object); |
| 5596 | 5684 |
| 5597 // The returned handle should point to a new object if the visitor is a | 5685 // 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. | 5686 // This allows VisitObject to make a copy of the object if desired. |
| 5599 virtual Handle<JSObject> VisitObject(Handle<JSObject> object) = 0; | 5687 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, | 5688 virtual Handle<JSObject> VisitElementOrProperty(Handle<JSObject> object, |
| 5604 Handle<JSObject> value) = 0; | 5689 Handle<JSObject> value) = 0; |
| 5690 |
| 5691 AllocationSiteContext* site_context() { return site_context_; } |
| 5692 |
| 5693 private: |
| 5694 AllocationSiteContext* site_context_; |
| 5605 }; | 5695 }; |
| 5606 | 5696 |
| 5607 | 5697 |
| 5608 class JSObjectCopyVisitor: public JSObjectWalkVisitor { | 5698 class JSObjectCopyVisitor: public JSObjectWalkVisitor { |
| 5609 public: | 5699 public: |
| 5610 explicit JSObjectCopyVisitor() {} | 5700 explicit JSObjectCopyVisitor(AllocationSiteContext* site_context) |
| 5701 : JSObjectWalkVisitor(site_context) {} |
| 5611 | 5702 |
| 5612 virtual bool is_copying() V8_OVERRIDE { return true; } | 5703 virtual bool is_copying() V8_OVERRIDE { return true; } |
| 5613 | 5704 |
| 5614 protected: | 5705 // The returned handle will be used for the object in all |
| 5706 // subsequent usages. This allows VisitObject to make a copy |
| 5707 // of the object if desired. |
| 5615 virtual Handle<JSObject> VisitObject(Handle<JSObject> object) V8_OVERRIDE { | 5708 virtual Handle<JSObject> VisitObject(Handle<JSObject> object) V8_OVERRIDE { |
| 5616 return JSObject::Copy(object); | 5709 // Only create a memento if |
| 5710 // 1) we have a JSArray, and |
| 5711 // 2) the elements kind is palatable |
| 5712 // 3) allow_mementos is true |
| 5713 Handle<JSObject> copy; |
| 5714 if (site_context()->activated() && |
| 5715 AllocationSite::CanTrack(object->map()->instance_type()) && |
| 5716 AllocationSite::GetMode(object->GetElementsKind()) == |
| 5717 TRACK_ALLOCATION_SITE) { |
| 5718 copy = JSObject::Copy(object, site_context()->current()); |
| 5719 } else { |
| 5720 copy = JSObject::Copy(object); |
| 5721 } |
| 5722 |
| 5723 return copy; |
| 5617 } | 5724 } |
| 5618 | 5725 |
| 5619 virtual Handle<JSObject> VisitElementOrProperty( | 5726 virtual Handle<JSObject> VisitElementOrProperty( |
| 5620 Handle<JSObject> object, | 5727 Handle<JSObject> object, |
| 5621 Handle<JSObject> value) V8_OVERRIDE { | 5728 Handle<JSObject> value) V8_OVERRIDE { |
| 5622 return StructureWalk(value); | 5729 Handle<AllocationSite> current_site = site_context()->EnterNewScope(); |
| 5730 Handle<JSObject> copy_of_value = StructureWalk(value); |
| 5731 site_context()->ExitScope(current_site, value); |
| 5732 return copy_of_value; |
| 5623 } | 5733 } |
| 5624 }; | 5734 }; |
| 5625 | 5735 |
| 5736 |
| 5737 class JSObjectCreateAllocationSitesVisitor: public JSObjectWalkVisitor { |
| 5738 public: |
| 5739 explicit JSObjectCreateAllocationSitesVisitor( |
| 5740 AllocationSiteContext* site_context) |
| 5741 : JSObjectWalkVisitor(site_context) {} |
| 5742 |
| 5743 virtual bool is_copying() V8_OVERRIDE { return false; } |
| 5744 |
| 5745 // The returned handle will be used for the object in all |
| 5746 // subsequent usages. This allows VisitObject to make a copy |
| 5747 // of the object if desired. |
| 5748 virtual Handle<JSObject> VisitObject(Handle<JSObject> object) V8_OVERRIDE { |
| 5749 return object; |
| 5750 } |
| 5751 |
| 5752 virtual Handle<JSObject> VisitElementOrProperty( |
| 5753 Handle<JSObject> object, |
| 5754 Handle<JSObject> value) V8_OVERRIDE { |
| 5755 Handle<AllocationSite> current_site = site_context()->EnterNewScope(); |
| 5756 value = StructureWalk(value); |
| 5757 site_context()->ExitScope(current_site, value); |
| 5758 return value; |
| 5759 } |
| 5760 }; |
| 5761 |
| 5626 | 5762 |
| 5627 Handle<JSObject> JSObjectWalkVisitor::StructureWalk(Handle<JSObject> object) { | 5763 Handle<JSObject> JSObjectWalkVisitor::StructureWalk(Handle<JSObject> object) { |
| 5628 bool copying = is_copying(); | 5764 bool copying = is_copying(); |
| 5629 Isolate* isolate = object->GetIsolate(); | 5765 Isolate* isolate = object->GetIsolate(); |
| 5630 StackLimitCheck check(isolate); | 5766 StackLimitCheck check(isolate); |
| 5631 if (check.HasOverflowed()) { | 5767 if (check.HasOverflowed()) { |
| 5632 isolate->StackOverflow(); | 5768 isolate->StackOverflow(); |
| 5633 return Handle<JSObject>::null(); | 5769 return Handle<JSObject>::null(); |
| 5634 } | 5770 } |
| 5635 | 5771 |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5759 case EXTERNAL_DOUBLE_ELEMENTS: | 5895 case EXTERNAL_DOUBLE_ELEMENTS: |
| 5760 case FAST_DOUBLE_ELEMENTS: | 5896 case FAST_DOUBLE_ELEMENTS: |
| 5761 case FAST_HOLEY_DOUBLE_ELEMENTS: | 5897 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 5762 // No contained objects, nothing to do. | 5898 // No contained objects, nothing to do. |
| 5763 break; | 5899 break; |
| 5764 } | 5900 } |
| 5765 return copy; | 5901 return copy; |
| 5766 } | 5902 } |
| 5767 | 5903 |
| 5768 | 5904 |
| 5769 Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object) { | 5905 Handle<JSObject> JSObject::DeepWalk(Handle<JSObject> object, |
| 5770 JSObjectCopyVisitor v; | 5906 AllocationSiteContext* site_context) { |
| 5907 JSObjectCreateAllocationSitesVisitor v(site_context); |
| 5908 Handle<JSObject> result = v.Visit(object); |
| 5909 ASSERT(!v.is_copying() && |
| 5910 (result.is_null() || result.is_identical_to(object))); |
| 5911 return result; |
| 5912 } |
| 5913 |
| 5914 |
| 5915 Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object, |
| 5916 AllocationSiteContext* site_context) { |
| 5917 JSObjectCopyVisitor v(site_context); |
| 5771 Handle<JSObject> copy = v.Visit(object); | 5918 Handle<JSObject> copy = v.Visit(object); |
| 5772 ASSERT(v.is_copying() && !copy.is_identical_to(object)); | 5919 ASSERT(v.is_copying() && !copy.is_identical_to(object)); |
| 5773 return copy; | 5920 return copy; |
| 5774 } | 5921 } |
| 5775 | 5922 |
| 5776 | 5923 |
| 5777 // Tests for the fast common case for property enumeration: | 5924 // Tests for the fast common case for property enumeration: |
| 5778 // - This object and all prototypes has an enum cache (which means that | 5925 // - 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). | 5926 // it is no proxy, has no interceptors and needs no access checks). |
| 5780 // - This object has no elements. | 5927 // - This object has no elements. |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6177 | 6324 |
| 6178 // Try to flatten before operating on the string. | 6325 // Try to flatten before operating on the string. |
| 6179 if (name->IsString()) String::cast(*name)->TryFlatten(); | 6326 if (name->IsString()) String::cast(*name)->TryFlatten(); |
| 6180 | 6327 |
| 6181 if (!object->CanSetCallback(*name)) return; | 6328 if (!object->CanSetCallback(*name)) return; |
| 6182 | 6329 |
| 6183 uint32_t index = 0; | 6330 uint32_t index = 0; |
| 6184 bool is_element = name->AsArrayIndex(&index); | 6331 bool is_element = name->AsArrayIndex(&index); |
| 6185 | 6332 |
| 6186 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 6333 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 6187 bool is_observed = FLAG_harmony_observation && object->map()->is_observed(); | 6334 bool is_observed = FLAG_harmony_observation && |
| 6335 object->map()->is_observed() && |
| 6336 *name != isolate->heap()->hidden_string(); |
| 6188 bool preexists = false; | 6337 bool preexists = false; |
| 6189 if (is_observed) { | 6338 if (is_observed) { |
| 6190 if (is_element) { | 6339 if (is_element) { |
| 6191 preexists = HasLocalElement(object, index); | 6340 preexists = HasLocalElement(object, index); |
| 6192 if (preexists && object->GetLocalElementAccessorPair(index) == NULL) { | 6341 if (preexists && object->GetLocalElementAccessorPair(index) == NULL) { |
| 6193 old_value = Object::GetElement(isolate, object, index); | 6342 old_value = Object::GetElement(isolate, object, index); |
| 6194 } | 6343 } |
| 6195 } else { | 6344 } else { |
| 6196 LookupResult lookup(isolate); | 6345 LookupResult lookup(isolate); |
| 6197 object->LocalLookup(*name, &lookup, true); | 6346 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)) { | 6581 !isolate->MayNamedAccess(*object, *name, v8::ACCESS_HAS)) { |
| 6433 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_HAS); | 6582 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_HAS); |
| 6434 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); | 6583 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 6435 return isolate->factory()->undefined_value(); | 6584 return isolate->factory()->undefined_value(); |
| 6436 } | 6585 } |
| 6437 | 6586 |
| 6438 // Make the lookup and include prototypes. | 6587 // Make the lookup and include prototypes. |
| 6439 uint32_t index = 0; | 6588 uint32_t index = 0; |
| 6440 if (name->AsArrayIndex(&index)) { | 6589 if (name->AsArrayIndex(&index)) { |
| 6441 for (Handle<Object> obj = object; | 6590 for (Handle<Object> obj = object; |
| 6442 *obj != isolate->heap()->null_value(); | 6591 !obj->IsNull(); |
| 6443 obj = handle(JSReceiver::cast(*obj)->GetPrototype(), isolate)) { | 6592 obj = handle(JSReceiver::cast(*obj)->GetPrototype(), isolate)) { |
| 6444 if (obj->IsJSObject() && JSObject::cast(*obj)->HasDictionaryElements()) { | 6593 if (obj->IsJSObject() && JSObject::cast(*obj)->HasDictionaryElements()) { |
| 6445 JSObject* js_object = JSObject::cast(*obj); | 6594 JSObject* js_object = JSObject::cast(*obj); |
| 6446 SeededNumberDictionary* dictionary = js_object->element_dictionary(); | 6595 SeededNumberDictionary* dictionary = js_object->element_dictionary(); |
| 6447 int entry = dictionary->FindEntry(index); | 6596 int entry = dictionary->FindEntry(index); |
| 6448 if (entry != SeededNumberDictionary::kNotFound) { | 6597 if (entry != SeededNumberDictionary::kNotFound) { |
| 6449 Object* element = dictionary->ValueAt(entry); | 6598 Object* element = dictionary->ValueAt(entry); |
| 6450 if (dictionary->DetailsAt(entry).type() == CALLBACKS && | 6599 if (dictionary->DetailsAt(entry).type() == CALLBACKS && |
| 6451 element->IsAccessorPair()) { | 6600 element->IsAccessorPair()) { |
| 6452 return handle(AccessorPair::cast(element)->GetComponent(component), | 6601 return handle(AccessorPair::cast(element)->GetComponent(component), |
| 6453 isolate); | 6602 isolate); |
| 6454 } | 6603 } |
| 6455 } | 6604 } |
| 6456 } | 6605 } |
| 6457 } | 6606 } |
| 6458 } else { | 6607 } else { |
| 6459 for (Handle<Object> obj = object; | 6608 for (Handle<Object> obj = object; |
| 6460 *obj != isolate->heap()->null_value(); | 6609 !obj->IsNull(); |
| 6461 obj = handle(JSReceiver::cast(*obj)->GetPrototype(), isolate)) { | 6610 obj = handle(JSReceiver::cast(*obj)->GetPrototype(), isolate)) { |
| 6462 LookupResult result(isolate); | 6611 LookupResult result(isolate); |
| 6463 JSReceiver::cast(*obj)->LocalLookup(*name, &result); | 6612 JSReceiver::cast(*obj)->LocalLookup(*name, &result); |
| 6464 if (result.IsFound()) { | 6613 if (result.IsFound()) { |
| 6465 if (result.IsReadOnly()) return isolate->factory()->undefined_value(); | 6614 if (result.IsReadOnly()) return isolate->factory()->undefined_value(); |
| 6466 if (result.IsPropertyCallbacks()) { | 6615 if (result.IsPropertyCallbacks()) { |
| 6467 Object* obj = result.GetCallbackObject(); | 6616 Object* obj = result.GetCallbackObject(); |
| 6468 if (obj->IsAccessorPair()) { | 6617 if (obj->IsAccessorPair()) { |
| 6469 return handle(AccessorPair::cast(obj)->GetComponent(component), | 6618 return handle(AccessorPair::cast(obj)->GetComponent(component), |
| 6470 isolate); | 6619 isolate); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 6499 } | 6648 } |
| 6500 } | 6649 } |
| 6501 } | 6650 } |
| 6502 return GetHeap()->undefined_value(); | 6651 return GetHeap()->undefined_value(); |
| 6503 } else { | 6652 } else { |
| 6504 return property_dictionary()->SlowReverseLookup(value); | 6653 return property_dictionary()->SlowReverseLookup(value); |
| 6505 } | 6654 } |
| 6506 } | 6655 } |
| 6507 | 6656 |
| 6508 | 6657 |
| 6658 Handle<Map> Map::RawCopy(Handle<Map> map, |
| 6659 int instance_size) { |
| 6660 CALL_HEAP_FUNCTION(map->GetIsolate(), |
| 6661 map->RawCopy(instance_size), |
| 6662 Map); |
| 6663 } |
| 6664 |
| 6665 |
| 6509 MaybeObject* Map::RawCopy(int instance_size) { | 6666 MaybeObject* Map::RawCopy(int instance_size) { |
| 6510 Map* result; | 6667 Map* result; |
| 6511 MaybeObject* maybe_result = | 6668 MaybeObject* maybe_result = |
| 6512 GetHeap()->AllocateMap(instance_type(), instance_size); | 6669 GetHeap()->AllocateMap(instance_type(), instance_size); |
| 6513 if (!maybe_result->To(&result)) return maybe_result; | 6670 if (!maybe_result->To(&result)) return maybe_result; |
| 6514 | 6671 |
| 6515 result->set_prototype(prototype()); | 6672 result->set_prototype(prototype()); |
| 6516 result->set_constructor(constructor()); | 6673 result->set_constructor(constructor()); |
| 6517 result->set_bit_field(bit_field()); | 6674 result->set_bit_field(bit_field()); |
| 6518 result->set_bit_field2(bit_field2()); | 6675 result->set_bit_field2(bit_field2()); |
| 6519 int new_bit_field3 = bit_field3(); | 6676 int new_bit_field3 = bit_field3(); |
| 6520 new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true); | 6677 new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true); |
| 6521 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0); | 6678 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0); |
| 6522 new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache); | 6679 new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache); |
| 6523 new_bit_field3 = Deprecated::update(new_bit_field3, false); | 6680 new_bit_field3 = Deprecated::update(new_bit_field3, false); |
| 6524 new_bit_field3 = IsUnstable::update(new_bit_field3, false); | 6681 new_bit_field3 = IsUnstable::update(new_bit_field3, false); |
| 6525 result->set_bit_field3(new_bit_field3); | 6682 result->set_bit_field3(new_bit_field3); |
| 6526 return result; | 6683 return result; |
| 6527 } | 6684 } |
| 6528 | 6685 |
| 6529 | 6686 |
| 6530 Handle<Map> Map::CopyNormalized(Handle<Map> map, | 6687 Handle<Map> Map::CopyNormalized(Handle<Map> map, |
| 6531 PropertyNormalizationMode mode, | 6688 PropertyNormalizationMode mode, |
| 6532 NormalizedMapSharingMode sharing) { | 6689 NormalizedMapSharingMode sharing) { |
| 6533 CALL_HEAP_FUNCTION(map->GetIsolate(), | 6690 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) { | 6691 if (mode == CLEAR_INOBJECT_PROPERTIES) { |
| 6543 new_instance_size -= inobject_properties() * kPointerSize; | 6692 new_instance_size -= map->inobject_properties() * kPointerSize; |
| 6544 } | 6693 } |
| 6545 | 6694 |
| 6546 Map* result; | 6695 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 | 6696 |
| 6550 if (mode != CLEAR_INOBJECT_PROPERTIES) { | 6697 if (mode != CLEAR_INOBJECT_PROPERTIES) { |
| 6551 result->set_inobject_properties(inobject_properties()); | 6698 result->set_inobject_properties(map->inobject_properties()); |
| 6552 } | 6699 } |
| 6553 | 6700 |
| 6554 result->set_is_shared(sharing == SHARED_NORMALIZED_MAP); | 6701 result->set_is_shared(sharing == SHARED_NORMALIZED_MAP); |
| 6555 result->set_dictionary_map(true); | 6702 result->set_dictionary_map(true); |
| 6556 result->set_migration_target(false); | 6703 result->set_migration_target(false); |
| 6557 | 6704 |
| 6558 #ifdef VERIFY_HEAP | 6705 #ifdef VERIFY_HEAP |
| 6559 if (FLAG_verify_heap && result->is_shared()) { | 6706 if (FLAG_verify_heap && result->is_shared()) { |
| 6560 result->SharedMapVerify(); | 6707 result->SharedMapVerify(); |
| 6561 } | 6708 } |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6691 set_transitions(transitions); | 6838 set_transitions(transitions); |
| 6692 result->SetBackPointer(this); | 6839 result->SetBackPointer(this); |
| 6693 } else { | 6840 } else { |
| 6694 descriptors->InitializeRepresentations(Representation::Tagged()); | 6841 descriptors->InitializeRepresentations(Representation::Tagged()); |
| 6695 } | 6842 } |
| 6696 | 6843 |
| 6697 return result; | 6844 return result; |
| 6698 } | 6845 } |
| 6699 | 6846 |
| 6700 | 6847 |
| 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 | 6848 // Since this method is used to rewrite an existing transition tree, it can |
| 6711 // always insert transitions without checking. | 6849 // always insert transitions without checking. |
| 6712 MaybeObject* Map::CopyInstallDescriptors(int new_descriptor, | 6850 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map, |
| 6713 DescriptorArray* descriptors) { | 6851 int new_descriptor, |
| 6852 Handle<DescriptorArray> descriptors) { |
| 6714 ASSERT(descriptors->IsSortedNoDuplicates()); | 6853 ASSERT(descriptors->IsSortedNoDuplicates()); |
| 6715 | 6854 |
| 6716 Map* result; | 6855 Handle<Map> result = Map::CopyDropDescriptors(map); |
| 6717 MaybeObject* maybe_result = CopyDropDescriptors(); | |
| 6718 if (!maybe_result->To(&result)) return maybe_result; | |
| 6719 | 6856 |
| 6720 result->InitializeDescriptors(descriptors); | 6857 result->InitializeDescriptors(*descriptors); |
| 6721 result->SetNumberOfOwnDescriptors(new_descriptor + 1); | 6858 result->SetNumberOfOwnDescriptors(new_descriptor + 1); |
| 6722 | 6859 |
| 6723 int unused_property_fields = this->unused_property_fields(); | 6860 int unused_property_fields = map->unused_property_fields(); |
| 6724 if (descriptors->GetDetails(new_descriptor).type() == FIELD) { | 6861 if (descriptors->GetDetails(new_descriptor).type() == FIELD) { |
| 6725 unused_property_fields = this->unused_property_fields() - 1; | 6862 unused_property_fields = map->unused_property_fields() - 1; |
| 6726 if (unused_property_fields < 0) { | 6863 if (unused_property_fields < 0) { |
| 6727 unused_property_fields += JSObject::kFieldsAdded; | 6864 unused_property_fields += JSObject::kFieldsAdded; |
| 6728 } | 6865 } |
| 6729 } | 6866 } |
| 6730 | 6867 |
| 6731 result->set_unused_property_fields(unused_property_fields); | 6868 result->set_unused_property_fields(unused_property_fields); |
| 6732 result->set_owns_descriptors(false); | 6869 result->set_owns_descriptors(false); |
| 6733 | 6870 |
| 6734 Name* name = descriptors->GetKey(new_descriptor); | 6871 Handle<Name> name = handle(descriptors->GetKey(new_descriptor)); |
| 6735 TransitionArray* transitions; | 6872 Handle<TransitionArray> transitions = Map::AddTransition(map, name, result, |
| 6736 MaybeObject* maybe_transitions = | 6873 SIMPLE_TRANSITION); |
| 6737 AddTransition(name, result, SIMPLE_TRANSITION); | |
| 6738 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | |
| 6739 | 6874 |
| 6740 set_transitions(transitions); | 6875 map->set_transitions(*transitions); |
| 6741 result->SetBackPointer(this); | 6876 result->SetBackPointer(*map); |
| 6742 | 6877 |
| 6743 return result; | 6878 return result; |
| 6744 } | 6879 } |
| 6745 | 6880 |
| 6746 | 6881 |
| 6747 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { | 6882 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { |
| 6748 if (flag == INSERT_TRANSITION) { | 6883 if (flag == INSERT_TRANSITION) { |
| 6749 ASSERT(!HasElementsTransition() || | 6884 ASSERT(!HasElementsTransition() || |
| 6750 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || | 6885 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || |
| 6751 IsExternalArrayElementsKind( | 6886 IsExternalArrayElementsKind( |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6789 if (insert_transition) { | 6924 if (insert_transition) { |
| 6790 MaybeObject* added_elements = set_elements_transition_map(new_map); | 6925 MaybeObject* added_elements = set_elements_transition_map(new_map); |
| 6791 if (added_elements->IsFailure()) return added_elements; | 6926 if (added_elements->IsFailure()) return added_elements; |
| 6792 new_map->SetBackPointer(this); | 6927 new_map->SetBackPointer(this); |
| 6793 } | 6928 } |
| 6794 | 6929 |
| 6795 return new_map; | 6930 return new_map; |
| 6796 } | 6931 } |
| 6797 | 6932 |
| 6798 | 6933 |
| 6799 MaybeObject* Map::CopyForObserved() { | 6934 Handle<Map> Map::CopyForObserved(Handle<Map> map) { |
| 6800 ASSERT(!is_observed()); | 6935 ASSERT(!map->is_observed()); |
| 6936 |
| 6937 Isolate* isolate = map->GetIsolate(); |
| 6801 | 6938 |
| 6802 // In case the map owned its own descriptors, share the descriptors and | 6939 // In case the map owned its own descriptors, share the descriptors and |
| 6803 // transfer ownership to the new map. | 6940 // transfer ownership to the new map. |
| 6804 Map* new_map; | 6941 Handle<Map> new_map; |
| 6805 MaybeObject* maybe_new_map; | 6942 if (map->owns_descriptors()) { |
| 6806 if (owns_descriptors()) { | 6943 new_map = Map::CopyDropDescriptors(map); |
| 6807 maybe_new_map = CopyDropDescriptors(); | |
| 6808 } else { | 6944 } else { |
| 6809 maybe_new_map = Copy(); | 6945 new_map = Map::Copy(map); |
| 6810 } | 6946 } |
| 6811 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
| 6812 | 6947 |
| 6813 TransitionArray* transitions; | 6948 Handle<TransitionArray> transitions = |
| 6814 MaybeObject* maybe_transitions = AddTransition(GetHeap()->observed_symbol(), | 6949 Map::AddTransition(map, isolate->factory()->observed_symbol(), new_map, |
| 6815 new_map, | 6950 FULL_TRANSITION); |
| 6816 FULL_TRANSITION); | 6951 |
| 6817 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | 6952 map->set_transitions(*transitions); |
| 6818 set_transitions(transitions); | |
| 6819 | 6953 |
| 6820 new_map->set_is_observed(true); | 6954 new_map->set_is_observed(true); |
| 6821 | 6955 |
| 6822 if (owns_descriptors()) { | 6956 if (map->owns_descriptors()) { |
| 6823 new_map->InitializeDescriptors(instance_descriptors()); | 6957 new_map->InitializeDescriptors(map->instance_descriptors()); |
| 6824 set_owns_descriptors(false); | 6958 map->set_owns_descriptors(false); |
| 6825 } | 6959 } |
| 6826 | 6960 |
| 6827 new_map->SetBackPointer(this); | 6961 new_map->SetBackPointer(*map); |
| 6828 return new_map; | 6962 return new_map; |
| 6829 } | 6963 } |
| 6830 | 6964 |
| 6831 | 6965 |
| 6832 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() { | 6966 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() { |
| 6833 if (pre_allocated_property_fields() == 0) return CopyDropDescriptors(); | 6967 if (pre_allocated_property_fields() == 0) return CopyDropDescriptors(); |
| 6834 | 6968 |
| 6835 // If the map has pre-allocated properties always start out with a descriptor | 6969 // If the map has pre-allocated properties always start out with a descriptor |
| 6836 // array describing these properties. | 6970 // array describing these properties. |
| 6837 ASSERT(constructor()->IsJSFunction()); | 6971 ASSERT(constructor()->IsJSFunction()); |
| (...skipping 857 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7695 return cache; | 7829 return cache; |
| 7696 } | 7830 } |
| 7697 | 7831 |
| 7698 | 7832 |
| 7699 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) { | 7833 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) { |
| 7700 ElementsAccessor* accessor = array->GetElementsAccessor(); | 7834 ElementsAccessor* accessor = array->GetElementsAccessor(); |
| 7701 MaybeObject* maybe_result = | 7835 MaybeObject* maybe_result = |
| 7702 accessor->AddElementsToFixedArray(array, array, this); | 7836 accessor->AddElementsToFixedArray(array, array, this); |
| 7703 FixedArray* result; | 7837 FixedArray* result; |
| 7704 if (!maybe_result->To<FixedArray>(&result)) return maybe_result; | 7838 if (!maybe_result->To<FixedArray>(&result)) return maybe_result; |
| 7705 #ifdef DEBUG | 7839 #ifdef ENABLE_SLOW_ASSERTS |
| 7706 if (FLAG_enable_slow_asserts) { | 7840 if (FLAG_enable_slow_asserts) { |
| 7707 for (int i = 0; i < result->length(); i++) { | 7841 for (int i = 0; i < result->length(); i++) { |
| 7708 Object* current = result->get(i); | 7842 Object* current = result->get(i); |
| 7709 ASSERT(current->IsNumber() || current->IsName()); | 7843 ASSERT(current->IsNumber() || current->IsName()); |
| 7710 } | 7844 } |
| 7711 } | 7845 } |
| 7712 #endif | 7846 #endif |
| 7713 return result; | 7847 return result; |
| 7714 } | 7848 } |
| 7715 | 7849 |
| 7716 | 7850 |
| 7717 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) { | 7851 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) { |
| 7718 ElementsAccessor* accessor = ElementsAccessor::ForArray(other); | 7852 ElementsAccessor* accessor = ElementsAccessor::ForArray(other); |
| 7719 MaybeObject* maybe_result = | 7853 MaybeObject* maybe_result = |
| 7720 accessor->AddElementsToFixedArray(NULL, NULL, this, other); | 7854 accessor->AddElementsToFixedArray(NULL, NULL, this, other); |
| 7721 FixedArray* result; | 7855 FixedArray* result; |
| 7722 if (!maybe_result->To(&result)) return maybe_result; | 7856 if (!maybe_result->To(&result)) return maybe_result; |
| 7723 #ifdef DEBUG | 7857 #ifdef ENABLE_SLOW_ASSERTS |
| 7724 if (FLAG_enable_slow_asserts) { | 7858 if (FLAG_enable_slow_asserts) { |
| 7725 for (int i = 0; i < result->length(); i++) { | 7859 for (int i = 0; i < result->length(); i++) { |
| 7726 Object* current = result->get(i); | 7860 Object* current = result->get(i); |
| 7727 ASSERT(current->IsNumber() || current->IsName()); | 7861 ASSERT(current->IsNumber() || current->IsName()); |
| 7728 } | 7862 } |
| 7729 } | 7863 } |
| 7730 #endif | 7864 #endif |
| 7731 return result; | 7865 return result; |
| 7732 } | 7866 } |
| 7733 | 7867 |
| (...skipping 1034 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8768 | 8902 |
| 8769 bool String::SlowEquals(String* other) { | 8903 bool String::SlowEquals(String* other) { |
| 8770 // Fast check: negative check with lengths. | 8904 // Fast check: negative check with lengths. |
| 8771 int len = length(); | 8905 int len = length(); |
| 8772 if (len != other->length()) return false; | 8906 if (len != other->length()) return false; |
| 8773 if (len == 0) return true; | 8907 if (len == 0) return true; |
| 8774 | 8908 |
| 8775 // Fast check: if hash code is computed for both strings | 8909 // Fast check: if hash code is computed for both strings |
| 8776 // a fast negative check can be performed. | 8910 // a fast negative check can be performed. |
| 8777 if (HasHashCode() && other->HasHashCode()) { | 8911 if (HasHashCode() && other->HasHashCode()) { |
| 8778 #ifdef DEBUG | 8912 #ifdef ENABLE_SLOW_ASSERTS |
| 8779 if (FLAG_enable_slow_asserts) { | 8913 if (FLAG_enable_slow_asserts) { |
| 8780 if (Hash() != other->Hash()) { | 8914 if (Hash() != other->Hash()) { |
| 8781 bool found_difference = false; | 8915 bool found_difference = false; |
| 8782 for (int i = 0; i < len; i++) { | 8916 for (int i = 0; i < len; i++) { |
| 8783 if (Get(i) != other->Get(i)) { | 8917 if (Get(i) != other->Get(i)) { |
| 8784 found_difference = true; | 8918 found_difference = true; |
| 8785 break; | 8919 break; |
| 8786 } | 8920 } |
| 8787 } | 8921 } |
| 8788 ASSERT(found_difference); | 8922 ASSERT(found_difference); |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9023 | 9157 |
| 9024 Address start_of_string = string->address(); | 9158 Address start_of_string = string->address(); |
| 9025 ASSERT_OBJECT_ALIGNED(start_of_string); | 9159 ASSERT_OBJECT_ALIGNED(start_of_string); |
| 9026 ASSERT_OBJECT_ALIGNED(start_of_string + new_size); | 9160 ASSERT_OBJECT_ALIGNED(start_of_string + new_size); |
| 9027 | 9161 |
| 9028 Heap* heap = string->GetHeap(); | 9162 Heap* heap = string->GetHeap(); |
| 9029 NewSpace* newspace = heap->new_space(); | 9163 NewSpace* newspace = heap->new_space(); |
| 9030 if (newspace->Contains(start_of_string) && | 9164 if (newspace->Contains(start_of_string) && |
| 9031 newspace->top() == start_of_string + old_size) { | 9165 newspace->top() == start_of_string + old_size) { |
| 9032 // Last allocated object in new space. Simply lower allocation top. | 9166 // Last allocated object in new space. Simply lower allocation top. |
| 9033 *(newspace->allocation_top_address()) = start_of_string + new_size; | 9167 newspace->set_top(start_of_string + new_size); |
| 9034 } else { | 9168 } else { |
| 9035 // Sizes are pointer size aligned, so that we can use filler objects | 9169 // Sizes are pointer size aligned, so that we can use filler objects |
| 9036 // that are a multiple of pointer size. | 9170 // that are a multiple of pointer size. |
| 9037 heap->CreateFillerObjectAt(start_of_string + new_size, delta); | 9171 heap->CreateFillerObjectAt(start_of_string + new_size, delta); |
| 9038 } | 9172 } |
| 9039 if (Marking::IsBlack(Marking::MarkBitFrom(start_of_string))) { | 9173 if (Marking::IsBlack(Marking::MarkBitFrom(start_of_string))) { |
| 9040 MemoryChunk::IncrementLiveBytesFromMutator(start_of_string, -delta); | 9174 MemoryChunk::IncrementLiveBytesFromMutator(start_of_string, -delta); |
| 9041 } | 9175 } |
| 9042 | 9176 |
| 9043 | 9177 |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9259 // TODO(verwaest) Should be an assert, otherwise back pointers are not | 9393 // TODO(verwaest) Should be an assert, otherwise back pointers are not |
| 9260 // properly cleared. | 9394 // properly cleared. |
| 9261 if (transition_index == t->number_of_transitions()) return; | 9395 if (transition_index == t->number_of_transitions()) return; |
| 9262 | 9396 |
| 9263 int number_of_own_descriptors = NumberOfOwnDescriptors(); | 9397 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
| 9264 | 9398 |
| 9265 if (descriptors_owner_died) { | 9399 if (descriptors_owner_died) { |
| 9266 if (number_of_own_descriptors > 0) { | 9400 if (number_of_own_descriptors > 0) { |
| 9267 TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors); | 9401 TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors); |
| 9268 ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors); | 9402 ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors); |
| 9403 set_owns_descriptors(true); |
| 9269 } else { | 9404 } else { |
| 9270 ASSERT(descriptors == GetHeap()->empty_descriptor_array()); | 9405 ASSERT(descriptors == GetHeap()->empty_descriptor_array()); |
| 9271 } | 9406 } |
| 9272 } | 9407 } |
| 9273 | 9408 |
| 9274 int trim = t->number_of_transitions() - transition_index; | 9409 int trim = t->number_of_transitions() - transition_index; |
| 9275 if (trim > 0) { | 9410 if (trim > 0) { |
| 9276 RightTrimFixedArray<FROM_GC>(heap, t, t->IsSimpleTransition() | 9411 RightTrimFixedArray<FROM_GC>(heap, t, t->IsSimpleTransition() |
| 9277 ? trim : trim * TransitionArray::kTransitionSize); | 9412 ? trim : trim * TransitionArray::kTransitionSize); |
| 9278 } | 9413 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9315 | 9450 |
| 9316 | 9451 |
| 9317 bool Map::EquivalentToForNormalization(Map* other, | 9452 bool Map::EquivalentToForNormalization(Map* other, |
| 9318 PropertyNormalizationMode mode) { | 9453 PropertyNormalizationMode mode) { |
| 9319 int properties = mode == CLEAR_INOBJECT_PROPERTIES | 9454 int properties = mode == CLEAR_INOBJECT_PROPERTIES |
| 9320 ? 0 : other->inobject_properties(); | 9455 ? 0 : other->inobject_properties(); |
| 9321 return CheckEquivalent(this, other) && inobject_properties() == properties; | 9456 return CheckEquivalent(this, other) && inobject_properties() == properties; |
| 9322 } | 9457 } |
| 9323 | 9458 |
| 9324 | 9459 |
| 9460 void ConstantPoolArray::ConstantPoolIterateBody(ObjectVisitor* v) { |
| 9461 int first_ptr_offset = OffsetOfElementAt(first_ptr_index()); |
| 9462 int last_ptr_offset = |
| 9463 OffsetOfElementAt(first_ptr_index() + count_of_ptr_entries()); |
| 9464 v->VisitPointers( |
| 9465 HeapObject::RawField(this, first_ptr_offset), |
| 9466 HeapObject::RawField(this, last_ptr_offset)); |
| 9467 } |
| 9468 |
| 9469 |
| 9325 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { | 9470 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { |
| 9326 // Iterate over all fields in the body but take care in dealing with | 9471 // Iterate over all fields in the body but take care in dealing with |
| 9327 // the code entry. | 9472 // the code entry. |
| 9328 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); | 9473 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); |
| 9329 v->VisitCodeEntry(this->address() + kCodeEntryOffset); | 9474 v->VisitCodeEntry(this->address() + kCodeEntryOffset); |
| 9330 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); | 9475 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); |
| 9331 } | 9476 } |
| 9332 | 9477 |
| 9333 | 9478 |
| 9334 void JSFunction::MarkForLazyRecompilation() { | 9479 void JSFunction::MarkForLazyRecompilation() { |
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9760 // "-" all but the top-level function | 9905 // "-" all but the top-level function |
| 9761 // "-name" all but the function "name" | 9906 // "-name" all but the function "name" |
| 9762 // "" only the top-level function | 9907 // "" only the top-level function |
| 9763 // "name" only the function "name" | 9908 // "name" only the function "name" |
| 9764 // "name*" only functions starting with "name" | 9909 // "name*" only functions starting with "name" |
| 9765 bool JSFunction::PassesFilter(const char* raw_filter) { | 9910 bool JSFunction::PassesFilter(const char* raw_filter) { |
| 9766 if (*raw_filter == '*') return true; | 9911 if (*raw_filter == '*') return true; |
| 9767 String* name = shared()->DebugName(); | 9912 String* name = shared()->DebugName(); |
| 9768 Vector<const char> filter = CStrVector(raw_filter); | 9913 Vector<const char> filter = CStrVector(raw_filter); |
| 9769 if (filter.length() == 0) return name->length() == 0; | 9914 if (filter.length() == 0) return name->length() == 0; |
| 9770 if (filter[0] != '-' && name->IsUtf8EqualTo(filter)) return true; | 9915 if (filter[0] == '-') { |
| 9771 if (filter[0] == '-' && | 9916 if (filter.length() == 1) { |
| 9772 !name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) { | 9917 return (name->length() != 0); |
| 9918 } else if (!name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) { |
| 9919 return true; |
| 9920 } |
| 9921 } else if (name->IsUtf8EqualTo(filter)) { |
| 9773 return true; | 9922 return true; |
| 9774 } | 9923 } |
| 9775 if (filter[filter.length() - 1] == '*' && | 9924 if (filter[filter.length() - 1] == '*' && |
| 9776 name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) { | 9925 name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) { |
| 9777 return true; | 9926 return true; |
| 9778 } | 9927 } |
| 9779 return false; | 9928 return false; |
| 9780 } | 9929 } |
| 9781 | 9930 |
| 9782 | 9931 |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10167 | 10316 |
| 10168 | 10317 |
| 10169 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) { | 10318 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) { |
| 10170 ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); | 10319 ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); |
| 10171 VisitPointer(rinfo->target_object_address()); | 10320 VisitPointer(rinfo->target_object_address()); |
| 10172 } | 10321 } |
| 10173 | 10322 |
| 10174 | 10323 |
| 10175 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) { | 10324 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) { |
| 10176 Address* p = rinfo->target_reference_address(); | 10325 Address* p = rinfo->target_reference_address(); |
| 10177 VisitExternalReferences(p, p + 1); | 10326 VisitExternalReference(p); |
| 10178 } | 10327 } |
| 10179 | 10328 |
| 10180 | 10329 |
| 10181 void Code::InvalidateRelocation() { | 10330 void Code::InvalidateRelocation() { |
| 10182 set_relocation_info(GetHeap()->empty_byte_array()); | 10331 set_relocation_info(GetHeap()->empty_byte_array()); |
| 10183 } | 10332 } |
| 10184 | 10333 |
| 10185 | 10334 |
| 10186 void Code::Relocate(intptr_t delta) { | 10335 void Code::Relocate(intptr_t delta) { |
| 10187 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) { | 10336 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)) { | 10373 } else if (RelocInfo::IsCodeTarget(mode)) { |
| 10225 // rewrite code handles in inline cache targets to direct | 10374 // rewrite code handles in inline cache targets to direct |
| 10226 // pointers to the first instruction in the code object | 10375 // pointers to the first instruction in the code object |
| 10227 Handle<Object> p = it.rinfo()->target_object_handle(origin); | 10376 Handle<Object> p = it.rinfo()->target_object_handle(origin); |
| 10228 Code* code = Code::cast(*p); | 10377 Code* code = Code::cast(*p); |
| 10229 it.rinfo()->set_target_address(code->instruction_start(), | 10378 it.rinfo()->set_target_address(code->instruction_start(), |
| 10230 SKIP_WRITE_BARRIER); | 10379 SKIP_WRITE_BARRIER); |
| 10231 } else if (RelocInfo::IsRuntimeEntry(mode)) { | 10380 } else if (RelocInfo::IsRuntimeEntry(mode)) { |
| 10232 Address p = it.rinfo()->target_runtime_entry(origin); | 10381 Address p = it.rinfo()->target_runtime_entry(origin); |
| 10233 it.rinfo()->set_target_runtime_entry(p, SKIP_WRITE_BARRIER); | 10382 it.rinfo()->set_target_runtime_entry(p, SKIP_WRITE_BARRIER); |
| 10383 } else if (mode == RelocInfo::CODE_AGE_SEQUENCE) { |
| 10384 Handle<Object> p = it.rinfo()->code_age_stub_handle(origin); |
| 10385 Code* code = Code::cast(*p); |
| 10386 it.rinfo()->set_code_age_stub(code); |
| 10234 } else { | 10387 } else { |
| 10235 it.rinfo()->apply(delta); | 10388 it.rinfo()->apply(delta); |
| 10236 } | 10389 } |
| 10237 } | 10390 } |
| 10238 CPU::FlushICache(instruction_start(), instruction_size()); | 10391 CPU::FlushICache(instruction_start(), instruction_size()); |
| 10239 } | 10392 } |
| 10240 | 10393 |
| 10241 | 10394 |
| 10242 // Locate the source position which is closest to the address in the code. This | 10395 // 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. | 10396 // 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); | 10614 ASSERT(kind() == FUNCTION); |
| 10462 BackEdgeTable back_edges(this, &no_gc); | 10615 BackEdgeTable back_edges(this, &no_gc); |
| 10463 for (uint32_t i = 0; i < back_edges.length(); i++) { | 10616 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); | 10617 if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i); |
| 10465 } | 10618 } |
| 10466 return BailoutId::None(); | 10619 return BailoutId::None(); |
| 10467 } | 10620 } |
| 10468 | 10621 |
| 10469 | 10622 |
| 10470 void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) { | 10623 void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) { |
| 10471 PatchPlatformCodeAge(isolate, sequence, kNoAge, NO_MARKING_PARITY); | 10624 PatchPlatformCodeAge(isolate, sequence, kNoAgeCodeAge, NO_MARKING_PARITY); |
| 10472 } | 10625 } |
| 10473 | 10626 |
| 10474 | 10627 |
| 10628 void Code::MarkCodeAsExecuted(byte* sequence, Isolate* isolate) { |
| 10629 PatchPlatformCodeAge(isolate, sequence, kExecutedOnceCodeAge, |
| 10630 NO_MARKING_PARITY); |
| 10631 } |
| 10632 |
| 10633 |
| 10475 void Code::MakeOlder(MarkingParity current_parity) { | 10634 void Code::MakeOlder(MarkingParity current_parity) { |
| 10476 byte* sequence = FindCodeAgeSequence(); | 10635 byte* sequence = FindCodeAgeSequence(); |
| 10477 if (sequence != NULL) { | 10636 if (sequence != NULL) { |
| 10478 Age age; | 10637 Age age; |
| 10479 MarkingParity code_parity; | 10638 MarkingParity code_parity; |
| 10480 GetCodeAgeAndParity(sequence, &age, &code_parity); | 10639 GetCodeAgeAndParity(sequence, &age, &code_parity); |
| 10481 if (age != kLastCodeAge && code_parity != current_parity) { | 10640 if (age != kLastCodeAge && code_parity != current_parity) { |
| 10482 PatchPlatformCodeAge(GetIsolate(), | 10641 PatchPlatformCodeAge(GetIsolate(), |
| 10483 sequence, | 10642 sequence, |
| 10484 static_cast<Age>(age + 1), | 10643 static_cast<Age>(age + 1), |
| 10485 current_parity); | 10644 current_parity); |
| 10486 } | 10645 } |
| 10487 } | 10646 } |
| 10488 } | 10647 } |
| 10489 | 10648 |
| 10490 | 10649 |
| 10491 bool Code::IsOld() { | 10650 bool Code::IsOld() { |
| 10492 byte* sequence = FindCodeAgeSequence(); | 10651 Age age = GetAge(); |
| 10493 if (sequence == NULL) return false; | 10652 return age >= kIsOldCodeAge; |
| 10494 Age age; | |
| 10495 MarkingParity parity; | |
| 10496 GetCodeAgeAndParity(sequence, &age, &parity); | |
| 10497 return age >= kSexagenarianCodeAge; | |
| 10498 } | 10653 } |
| 10499 | 10654 |
| 10500 | 10655 |
| 10501 byte* Code::FindCodeAgeSequence() { | 10656 byte* Code::FindCodeAgeSequence() { |
| 10502 return FLAG_age_code && | 10657 return FLAG_age_code && |
| 10503 prologue_offset() != kPrologueOffsetNotSet && | 10658 prologue_offset() != Code::kPrologueOffsetNotSet && |
| 10504 (kind() == OPTIMIZED_FUNCTION || | 10659 (kind() == OPTIMIZED_FUNCTION || |
| 10505 (kind() == FUNCTION && !has_debug_break_slots())) | 10660 (kind() == FUNCTION && !has_debug_break_slots())) |
| 10506 ? instruction_start() + prologue_offset() | 10661 ? instruction_start() + prologue_offset() |
| 10507 : NULL; | 10662 : NULL; |
| 10508 } | 10663 } |
| 10509 | 10664 |
| 10510 | 10665 |
| 10511 int Code::GetAge() { | 10666 Code::Age Code::GetAge() { |
| 10512 byte* sequence = FindCodeAgeSequence(); | 10667 byte* sequence = FindCodeAgeSequence(); |
| 10513 if (sequence == NULL) { | 10668 if (sequence == NULL) { |
| 10514 return Code::kNoAge; | 10669 return Code::kNoAgeCodeAge; |
| 10515 } | 10670 } |
| 10516 Age age; | 10671 Age age; |
| 10517 MarkingParity parity; | 10672 MarkingParity parity; |
| 10518 GetCodeAgeAndParity(sequence, &age, &parity); | 10673 GetCodeAgeAndParity(sequence, &age, &parity); |
| 10519 return age; | 10674 return age; |
| 10520 } | 10675 } |
| 10521 | 10676 |
| 10522 | 10677 |
| 10523 void Code::GetCodeAgeAndParity(Code* code, Age* age, | 10678 void Code::GetCodeAgeAndParity(Code* code, Age* age, |
| 10524 MarkingParity* parity) { | 10679 MarkingParity* parity) { |
| 10525 Isolate* isolate = code->GetIsolate(); | 10680 Isolate* isolate = code->GetIsolate(); |
| 10526 Builtins* builtins = isolate->builtins(); | 10681 Builtins* builtins = isolate->builtins(); |
| 10527 Code* stub = NULL; | 10682 Code* stub = NULL; |
| 10528 #define HANDLE_CODE_AGE(AGE) \ | 10683 #define HANDLE_CODE_AGE(AGE) \ |
| 10529 stub = *builtins->Make##AGE##CodeYoungAgainEvenMarking(); \ | 10684 stub = *builtins->Make##AGE##CodeYoungAgainEvenMarking(); \ |
| 10530 if (code == stub) { \ | 10685 if (code == stub) { \ |
| 10531 *age = k##AGE##CodeAge; \ | 10686 *age = k##AGE##CodeAge; \ |
| 10532 *parity = EVEN_MARKING_PARITY; \ | 10687 *parity = EVEN_MARKING_PARITY; \ |
| 10533 return; \ | 10688 return; \ |
| 10534 } \ | 10689 } \ |
| 10535 stub = *builtins->Make##AGE##CodeYoungAgainOddMarking(); \ | 10690 stub = *builtins->Make##AGE##CodeYoungAgainOddMarking(); \ |
| 10536 if (code == stub) { \ | 10691 if (code == stub) { \ |
| 10537 *age = k##AGE##CodeAge; \ | 10692 *age = k##AGE##CodeAge; \ |
| 10538 *parity = ODD_MARKING_PARITY; \ | 10693 *parity = ODD_MARKING_PARITY; \ |
| 10539 return; \ | 10694 return; \ |
| 10540 } | 10695 } |
| 10541 CODE_AGE_LIST(HANDLE_CODE_AGE) | 10696 CODE_AGE_LIST(HANDLE_CODE_AGE) |
| 10542 #undef HANDLE_CODE_AGE | 10697 #undef HANDLE_CODE_AGE |
| 10698 stub = *builtins->MarkCodeAsExecutedOnce(); |
| 10699 if (code == stub) { |
| 10700 // Treat that's never been executed as old immediatly. |
| 10701 *age = kIsOldCodeAge; |
| 10702 *parity = NO_MARKING_PARITY; |
| 10703 return; |
| 10704 } |
| 10705 stub = *builtins->MarkCodeAsExecutedTwice(); |
| 10706 if (code == stub) { |
| 10707 // Pre-age code that has only been executed once. |
| 10708 *age = kPreAgedCodeAge; |
| 10709 *parity = NO_MARKING_PARITY; |
| 10710 return; |
| 10711 } |
| 10543 UNREACHABLE(); | 10712 UNREACHABLE(); |
| 10544 } | 10713 } |
| 10545 | 10714 |
| 10546 | 10715 |
| 10547 Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) { | 10716 Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) { |
| 10548 Builtins* builtins = isolate->builtins(); | 10717 Builtins* builtins = isolate->builtins(); |
| 10549 switch (age) { | 10718 switch (age) { |
| 10550 #define HANDLE_CODE_AGE(AGE) \ | 10719 #define HANDLE_CODE_AGE(AGE) \ |
| 10551 case k##AGE##CodeAge: { \ | 10720 case k##AGE##CodeAge: { \ |
| 10552 Code* stub = parity == EVEN_MARKING_PARITY \ | 10721 Code* stub = parity == EVEN_MARKING_PARITY \ |
| 10553 ? *builtins->Make##AGE##CodeYoungAgainEvenMarking() \ | 10722 ? *builtins->Make##AGE##CodeYoungAgainEvenMarking() \ |
| 10554 : *builtins->Make##AGE##CodeYoungAgainOddMarking(); \ | 10723 : *builtins->Make##AGE##CodeYoungAgainOddMarking(); \ |
| 10555 return stub; \ | 10724 return stub; \ |
| 10556 } | 10725 } |
| 10557 CODE_AGE_LIST(HANDLE_CODE_AGE) | 10726 CODE_AGE_LIST(HANDLE_CODE_AGE) |
| 10558 #undef HANDLE_CODE_AGE | 10727 #undef HANDLE_CODE_AGE |
| 10728 case kNotExecutedCodeAge: { |
| 10729 ASSERT(parity == NO_MARKING_PARITY); |
| 10730 return *builtins->MarkCodeAsExecutedOnce(); |
| 10731 } |
| 10732 case kExecutedOnceCodeAge: { |
| 10733 ASSERT(parity == NO_MARKING_PARITY); |
| 10734 return *builtins->MarkCodeAsExecutedTwice(); |
| 10735 } |
| 10559 default: | 10736 default: |
| 10560 UNREACHABLE(); | 10737 UNREACHABLE(); |
| 10561 break; | 10738 break; |
| 10562 } | 10739 } |
| 10563 return NULL; | 10740 return NULL; |
| 10564 } | 10741 } |
| 10565 | 10742 |
| 10566 | 10743 |
| 10567 void Code::PrintDeoptLocation(int bailout_id) { | 10744 void Code::PrintDeoptLocation(int bailout_id) { |
| 10568 const char* last_comment = NULL; | 10745 const char* last_comment = NULL; |
| (...skipping 1944 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12513 } | 12690 } |
| 12514 | 12691 |
| 12515 | 12692 |
| 12516 void JSObject::TransitionElementsKind(Handle<JSObject> object, | 12693 void JSObject::TransitionElementsKind(Handle<JSObject> object, |
| 12517 ElementsKind to_kind) { | 12694 ElementsKind to_kind) { |
| 12518 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), | 12695 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), |
| 12519 object->TransitionElementsKind(to_kind)); | 12696 object->TransitionElementsKind(to_kind)); |
| 12520 } | 12697 } |
| 12521 | 12698 |
| 12522 | 12699 |
| 12700 bool AllocationSite::IsNestedSite() { |
| 12701 ASSERT(FLAG_trace_track_allocation_sites); |
| 12702 Object* current = GetHeap()->allocation_sites_list(); |
| 12703 while (current != NULL && current->IsAllocationSite()) { |
| 12704 AllocationSite* current_site = AllocationSite::cast(current); |
| 12705 if (current_site->nested_site() == this) { |
| 12706 return true; |
| 12707 } |
| 12708 current = current_site->weak_next(); |
| 12709 } |
| 12710 return false; |
| 12711 } |
| 12712 |
| 12713 |
| 12523 MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) { | 12714 MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) { |
| 12524 if (!FLAG_track_allocation_sites || !IsJSArray()) { | 12715 if (!FLAG_track_allocation_sites || !IsJSArray()) { |
| 12525 return this; | 12716 return this; |
| 12526 } | 12717 } |
| 12527 | 12718 |
| 12528 AllocationMemento* memento = AllocationMemento::FindForJSObject(this); | 12719 AllocationMemento* memento = AllocationMemento::FindForJSObject(this); |
| 12529 if (memento == NULL || !memento->IsValid()) { | 12720 if (memento == NULL || !memento->IsValid()) { |
| 12530 return this; | 12721 return this; |
| 12531 } | 12722 } |
| 12532 | 12723 |
| 12533 // Walk through to the Allocation Site | 12724 // Walk through to the Allocation Site |
| 12534 AllocationSite* site = memento->GetAllocationSite(); | 12725 AllocationSite* site = memento->GetAllocationSite(); |
| 12535 if (site->IsLiteralSite()) { | 12726 if (site->SitePointsToLiteral() && |
| 12727 site->transition_info()->IsJSArray()) { |
| 12536 JSArray* transition_info = JSArray::cast(site->transition_info()); | 12728 JSArray* transition_info = JSArray::cast(site->transition_info()); |
| 12537 ElementsKind kind = transition_info->GetElementsKind(); | 12729 ElementsKind kind = transition_info->GetElementsKind(); |
| 12538 // if kind is holey ensure that to_kind is as well. | 12730 // if kind is holey ensure that to_kind is as well. |
| 12539 if (IsHoleyElementsKind(kind)) { | 12731 if (IsHoleyElementsKind(kind)) { |
| 12540 to_kind = GetHoleyElementsKind(to_kind); | 12732 to_kind = GetHoleyElementsKind(to_kind); |
| 12541 } | 12733 } |
| 12542 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { | 12734 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { |
| 12543 // If the array is huge, it's not likely to be defined in a local | 12735 // 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. | 12736 // function, so we shouldn't make new instances of it very often. |
| 12545 uint32_t length = 0; | 12737 uint32_t length = 0; |
| 12546 CHECK(transition_info->length()->ToArrayIndex(&length)); | 12738 CHECK(transition_info->length()->ToArrayIndex(&length)); |
| 12547 if (length <= AllocationSite::kMaximumArrayBytesToPretransition) { | 12739 if (length <= AllocationSite::kMaximumArrayBytesToPretransition) { |
| 12548 if (FLAG_trace_track_allocation_sites) { | 12740 if (FLAG_trace_track_allocation_sites) { |
| 12741 bool is_nested = site->IsNestedSite(); |
| 12549 PrintF( | 12742 PrintF( |
| 12550 "AllocationSite: JSArray %p boilerplate updated %s->%s\n", | 12743 "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n", |
| 12551 reinterpret_cast<void*>(this), | 12744 reinterpret_cast<void*>(this), |
| 12745 is_nested ? "(nested)" : "", |
| 12552 ElementsKindToString(kind), | 12746 ElementsKindToString(kind), |
| 12553 ElementsKindToString(to_kind)); | 12747 ElementsKindToString(to_kind)); |
| 12554 } | 12748 } |
| 12555 return transition_info->TransitionElementsKind(to_kind); | 12749 return transition_info->TransitionElementsKind(to_kind); |
| 12556 } | 12750 } |
| 12557 } | 12751 } |
| 12558 } else { | 12752 } else { |
| 12559 ElementsKind kind = site->GetElementsKind(); | 12753 ElementsKind kind = site->GetElementsKind(); |
| 12560 // if kind is holey ensure that to_kind is as well. | 12754 // if kind is holey ensure that to_kind is as well. |
| 12561 if (IsHoleyElementsKind(kind)) { | 12755 if (IsHoleyElementsKind(kind)) { |
| (...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12944 InterceptorInfo* JSObject::GetIndexedInterceptor() { | 13138 InterceptorInfo* JSObject::GetIndexedInterceptor() { |
| 12945 ASSERT(map()->has_indexed_interceptor()); | 13139 ASSERT(map()->has_indexed_interceptor()); |
| 12946 JSFunction* constructor = JSFunction::cast(map()->constructor()); | 13140 JSFunction* constructor = JSFunction::cast(map()->constructor()); |
| 12947 ASSERT(constructor->shared()->IsApiFunction()); | 13141 ASSERT(constructor->shared()->IsApiFunction()); |
| 12948 Object* result = | 13142 Object* result = |
| 12949 constructor->shared()->get_api_func_data()->indexed_property_handler(); | 13143 constructor->shared()->get_api_func_data()->indexed_property_handler(); |
| 12950 return InterceptorInfo::cast(result); | 13144 return InterceptorInfo::cast(result); |
| 12951 } | 13145 } |
| 12952 | 13146 |
| 12953 | 13147 |
| 12954 MaybeObject* JSObject::GetPropertyPostInterceptor( | 13148 Handle<Object> JSObject::GetPropertyPostInterceptor( |
| 12955 Object* receiver, | 13149 Handle<JSObject> object, |
| 12956 Name* name, | 13150 Handle<Object> receiver, |
| 13151 Handle<Name> name, |
| 12957 PropertyAttributes* attributes) { | 13152 PropertyAttributes* attributes) { |
| 12958 // Check local property in holder, ignore interceptor. | 13153 // Check local property in holder, ignore interceptor. |
| 12959 LookupResult result(GetIsolate()); | 13154 Isolate* isolate = object->GetIsolate(); |
| 12960 LocalLookupRealNamedProperty(name, &result); | 13155 LookupResult lookup(isolate); |
| 12961 if (result.IsFound()) { | 13156 object->LocalLookupRealNamedProperty(*name, &lookup); |
| 12962 return GetProperty(receiver, &result, name, attributes); | 13157 Handle<Object> result; |
| 13158 if (lookup.IsFound()) { |
| 13159 result = GetProperty(object, receiver, &lookup, name, attributes); |
| 13160 } else { |
| 13161 // Continue searching via the prototype chain. |
| 13162 Handle<Object> prototype(object->GetPrototype(), isolate); |
| 13163 *attributes = ABSENT; |
| 13164 if (prototype->IsNull()) return isolate->factory()->undefined_value(); |
| 13165 result = GetPropertyWithReceiver(prototype, receiver, name, attributes); |
| 12963 } | 13166 } |
| 12964 // Continue searching via the prototype chain. | 13167 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 } | 13168 } |
| 12970 | 13169 |
| 12971 | 13170 |
| 12972 MaybeObject* JSObject::GetLocalPropertyPostInterceptor( | 13171 MaybeObject* JSObject::GetLocalPropertyPostInterceptor( |
| 12973 Object* receiver, | 13172 Object* receiver, |
| 12974 Name* name, | 13173 Name* name, |
| 12975 PropertyAttributes* attributes) { | 13174 PropertyAttributes* attributes) { |
| 12976 // Check local property in holder, ignore interceptor. | 13175 // Check local property in holder, ignore interceptor. |
| 12977 LookupResult result(GetIsolate()); | 13176 LookupResult result(GetIsolate()); |
| 12978 LocalLookupRealNamedProperty(name, &result); | 13177 LocalLookupRealNamedProperty(name, &result); |
| 12979 if (result.IsFound()) { | 13178 if (result.IsFound()) { |
| 12980 return GetProperty(receiver, &result, name, attributes); | 13179 return GetProperty(receiver, &result, name, attributes); |
| 12981 } | 13180 } |
| 12982 return GetHeap()->undefined_value(); | 13181 return GetHeap()->undefined_value(); |
| 12983 } | 13182 } |
| 12984 | 13183 |
| 12985 | 13184 |
| 12986 MaybeObject* JSObject::GetPropertyWithInterceptor( | 13185 Handle<Object> JSObject::GetPropertyWithInterceptor( |
| 12987 Object* receiver, | 13186 Handle<JSObject> object, |
| 12988 Name* name, | 13187 Handle<Object> receiver, |
| 13188 Handle<Name> name, |
| 12989 PropertyAttributes* attributes) { | 13189 PropertyAttributes* attributes) { |
| 13190 Isolate* isolate = object->GetIsolate(); |
| 13191 |
| 12990 // TODO(rossberg): Support symbols in the API. | 13192 // TODO(rossberg): Support symbols in the API. |
| 12991 if (name->IsSymbol()) return GetHeap()->undefined_value(); | 13193 if (name->IsSymbol()) return isolate->factory()->undefined_value(); |
| 12992 | 13194 |
| 12993 Isolate* isolate = GetIsolate(); | 13195 Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor(), isolate); |
| 12994 InterceptorInfo* interceptor = GetNamedInterceptor(); | 13196 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 | 13197 |
| 13000 if (!interceptor->getter()->IsUndefined()) { | 13198 if (!interceptor->getter()->IsUndefined()) { |
| 13001 v8::NamedPropertyGetterCallback getter = | 13199 v8::NamedPropertyGetterCallback getter = |
| 13002 v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter()); | 13200 v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter()); |
| 13003 LOG(isolate, | 13201 LOG(isolate, |
| 13004 ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name)); | 13202 ApiNamedPropertyAccess("interceptor-named-get", *object, *name)); |
| 13005 PropertyCallbackArguments | 13203 PropertyCallbackArguments |
| 13006 args(isolate, interceptor->data(), receiver, this); | 13204 args(isolate, interceptor->data(), *receiver, *object); |
| 13007 v8::Handle<v8::Value> result = | 13205 v8::Handle<v8::Value> result = |
| 13008 args.Call(getter, v8::Utils::ToLocal(name_handle)); | 13206 args.Call(getter, v8::Utils::ToLocal(name_string)); |
| 13009 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 13207 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 13010 if (!result.IsEmpty()) { | 13208 if (!result.IsEmpty()) { |
| 13011 *attributes = NONE; | 13209 *attributes = NONE; |
| 13012 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | 13210 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); |
| 13013 result_internal->VerifyApiCallResultType(); | 13211 result_internal->VerifyApiCallResultType(); |
| 13014 return *result_internal; | 13212 // Rebox handle to escape this scope. |
| 13213 return handle(*result_internal, isolate); |
| 13015 } | 13214 } |
| 13016 } | 13215 } |
| 13017 | 13216 |
| 13018 MaybeObject* result = holder_handle->GetPropertyPostInterceptor( | 13217 return GetPropertyPostInterceptor(object, receiver, name, attributes); |
| 13019 *receiver_handle, | |
| 13020 *name_handle, | |
| 13021 attributes); | |
| 13022 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | |
| 13023 return result; | |
| 13024 } | 13218 } |
| 13025 | 13219 |
| 13026 | 13220 |
| 13027 bool JSObject::HasRealNamedProperty(Isolate* isolate, Name* key) { | 13221 bool JSObject::HasRealNamedProperty(Handle<JSObject> object, |
| 13222 Handle<Name> key) { |
| 13223 Isolate* isolate = object->GetIsolate(); |
| 13224 SealHandleScope shs(isolate); |
| 13028 // Check access rights if needed. | 13225 // Check access rights if needed. |
| 13029 if (IsAccessCheckNeeded()) { | 13226 if (object->IsAccessCheckNeeded()) { |
| 13030 if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) { | 13227 if (!isolate->MayNamedAccess(*object, *key, v8::ACCESS_HAS)) { |
| 13031 isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 13228 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_HAS); |
| 13032 return false; | 13229 return false; |
| 13033 } | 13230 } |
| 13034 } | 13231 } |
| 13035 | 13232 |
| 13036 LookupResult result(isolate); | 13233 LookupResult result(isolate); |
| 13037 LocalLookupRealNamedProperty(key, &result); | 13234 object->LocalLookupRealNamedProperty(*key, &result); |
| 13038 return result.IsFound() && !result.IsInterceptor(); | 13235 return result.IsFound() && !result.IsInterceptor(); |
| 13039 } | 13236 } |
| 13040 | 13237 |
| 13041 | 13238 |
| 13042 bool JSObject::HasRealElementProperty(Isolate* isolate, uint32_t index) { | 13239 bool JSObject::HasRealElementProperty(Handle<JSObject> object, uint32_t index) { |
| 13240 Isolate* isolate = object->GetIsolate(); |
| 13241 SealHandleScope shs(isolate); |
| 13043 // Check access rights if needed. | 13242 // Check access rights if needed. |
| 13044 if (IsAccessCheckNeeded()) { | 13243 if (object->IsAccessCheckNeeded()) { |
| 13045 if (!isolate->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 13244 if (!isolate->MayIndexedAccess(*object, index, v8::ACCESS_HAS)) { |
| 13046 isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 13245 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_HAS); |
| 13047 return false; | 13246 return false; |
| 13048 } | 13247 } |
| 13049 } | 13248 } |
| 13050 | 13249 |
| 13051 if (IsJSGlobalProxy()) { | 13250 if (object->IsJSGlobalProxy()) { |
| 13052 Object* proto = GetPrototype(); | 13251 HandleScope scope(isolate); |
| 13252 Handle<Object> proto(object->GetPrototype(), isolate); |
| 13053 if (proto->IsNull()) return false; | 13253 if (proto->IsNull()) return false; |
| 13054 ASSERT(proto->IsJSGlobalObject()); | 13254 ASSERT(proto->IsJSGlobalObject()); |
| 13055 return JSObject::cast(proto)->HasRealElementProperty(isolate, index); | 13255 return HasRealElementProperty(Handle<JSObject>::cast(proto), index); |
| 13056 } | 13256 } |
| 13057 | 13257 |
| 13058 return GetElementAttributeWithoutInterceptor(this, index, false) != ABSENT; | 13258 return object->GetElementAttributeWithoutInterceptor( |
| 13259 *object, index, false) != ABSENT; |
| 13059 } | 13260 } |
| 13060 | 13261 |
| 13061 | 13262 |
| 13062 bool JSObject::HasRealNamedCallbackProperty(Isolate* isolate, Name* key) { | 13263 bool JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object, |
| 13264 Handle<Name> key) { |
| 13265 Isolate* isolate = object->GetIsolate(); |
| 13266 SealHandleScope shs(isolate); |
| 13063 // Check access rights if needed. | 13267 // Check access rights if needed. |
| 13064 if (IsAccessCheckNeeded()) { | 13268 if (object->IsAccessCheckNeeded()) { |
| 13065 if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) { | 13269 if (!isolate->MayNamedAccess(*object, *key, v8::ACCESS_HAS)) { |
| 13066 isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 13270 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_HAS); |
| 13067 return false; | 13271 return false; |
| 13068 } | 13272 } |
| 13069 } | 13273 } |
| 13070 | 13274 |
| 13071 LookupResult result(isolate); | 13275 LookupResult result(isolate); |
| 13072 LocalLookupRealNamedProperty(key, &result); | 13276 object->LocalLookupRealNamedProperty(*key, &result); |
| 13073 return result.IsPropertyCallbacks(); | 13277 return result.IsPropertyCallbacks(); |
| 13074 } | 13278 } |
| 13075 | 13279 |
| 13076 | 13280 |
| 13077 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { | 13281 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { |
| 13078 if (HasFastProperties()) { | 13282 if (HasFastProperties()) { |
| 13079 Map* map = this->map(); | 13283 Map* map = this->map(); |
| 13080 if (filter == NONE) return map->NumberOfOwnDescriptors(); | 13284 if (filter == NONE) return map->NumberOfOwnDescriptors(); |
| 13081 if (filter & DONT_ENUM) { | 13285 if (filter & DONT_ENUM) { |
| 13082 int result = map->EnumLength(); | 13286 int result = map->EnumLength(); |
| (...skipping 1005 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14088 template | 14292 template |
| 14089 int Dictionary<SeededNumberDictionaryShape, uint32_t>::NumberOfEnumElements(); | 14293 int Dictionary<SeededNumberDictionaryShape, uint32_t>::NumberOfEnumElements(); |
| 14090 | 14294 |
| 14091 template | 14295 template |
| 14092 int Dictionary<NameDictionaryShape, Name*>::NumberOfEnumElements(); | 14296 int Dictionary<NameDictionaryShape, Name*>::NumberOfEnumElements(); |
| 14093 | 14297 |
| 14094 template | 14298 template |
| 14095 int HashTable<SeededNumberDictionaryShape, uint32_t>::FindEntry(uint32_t); | 14299 int HashTable<SeededNumberDictionaryShape, uint32_t>::FindEntry(uint32_t); |
| 14096 | 14300 |
| 14097 | 14301 |
| 14302 Handle<Object> JSObject::PrepareSlowElementsForSort( |
| 14303 Handle<JSObject> object, uint32_t limit) { |
| 14304 CALL_HEAP_FUNCTION(object->GetIsolate(), |
| 14305 object->PrepareSlowElementsForSort(limit), |
| 14306 Object); |
| 14307 } |
| 14308 |
| 14309 |
| 14098 // Collates undefined and unexisting elements below limit from position | 14310 // Collates undefined and unexisting elements below limit from position |
| 14099 // zero of the elements. The object stays in Dictionary mode. | 14311 // zero of the elements. The object stays in Dictionary mode. |
| 14100 MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) { | 14312 MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) { |
| 14101 ASSERT(HasDictionaryElements()); | 14313 ASSERT(HasDictionaryElements()); |
| 14102 // Must stay in dictionary mode, either because of requires_slow_elements, | 14314 // Must stay in dictionary mode, either because of requires_slow_elements, |
| 14103 // or because we are not going to sort (and therefore compact) all of the | 14315 // or because we are not going to sort (and therefore compact) all of the |
| 14104 // elements. | 14316 // elements. |
| 14105 SeededNumberDictionary* dict = element_dictionary(); | 14317 SeededNumberDictionary* dict = element_dictionary(); |
| 14106 HeapNumber* result_double = NULL; | 14318 HeapNumber* result_double = NULL; |
| 14107 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { | 14319 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14190 ASSERT_NE(NULL, result_double); | 14402 ASSERT_NE(NULL, result_double); |
| 14191 result_double->set_value(static_cast<double>(result)); | 14403 result_double->set_value(static_cast<double>(result)); |
| 14192 return result_double; | 14404 return result_double; |
| 14193 } | 14405 } |
| 14194 | 14406 |
| 14195 | 14407 |
| 14196 // Collects all defined (non-hole) and non-undefined (array) elements at | 14408 // Collects all defined (non-hole) and non-undefined (array) elements at |
| 14197 // the start of the elements array. | 14409 // the start of the elements array. |
| 14198 // If the object is in dictionary mode, it is converted to fast elements | 14410 // If the object is in dictionary mode, it is converted to fast elements |
| 14199 // mode. | 14411 // mode. |
| 14200 MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) { | 14412 Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object, |
| 14201 Heap* heap = GetHeap(); | 14413 uint32_t limit) { |
| 14414 Isolate* isolate = object->GetIsolate(); |
| 14202 | 14415 |
| 14203 ASSERT(!map()->is_observed()); | 14416 ASSERT(!object->map()->is_observed()); |
| 14204 if (HasDictionaryElements()) { | 14417 if (object->HasDictionaryElements()) { |
| 14205 // Convert to fast elements containing only the existing properties. | 14418 // Convert to fast elements containing only the existing properties. |
| 14206 // Ordering is irrelevant, since we are going to sort anyway. | 14419 // Ordering is irrelevant, since we are going to sort anyway. |
| 14207 SeededNumberDictionary* dict = element_dictionary(); | 14420 Handle<SeededNumberDictionary> dict(object->element_dictionary()); |
| 14208 if (IsJSArray() || dict->requires_slow_elements() || | 14421 if (object->IsJSArray() || dict->requires_slow_elements() || |
| 14209 dict->max_number_key() >= limit) { | 14422 dict->max_number_key() >= limit) { |
| 14210 return PrepareSlowElementsForSort(limit); | 14423 return JSObject::PrepareSlowElementsForSort(object, limit); |
| 14211 } | 14424 } |
| 14212 // Convert to fast elements. | 14425 // Convert to fast elements. |
| 14213 | 14426 |
| 14214 Object* obj; | 14427 Handle<Map> new_map = |
| 14215 MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(), | 14428 JSObject::GetElementsTransitionMap(object, FAST_HOLEY_ELEMENTS); |
| 14216 FAST_HOLEY_ELEMENTS); | |
| 14217 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
| 14218 Map* new_map = Map::cast(obj); | |
| 14219 | 14429 |
| 14220 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; | 14430 PretenureFlag tenure = isolate->heap()->InNewSpace(*object) ? |
| 14221 Object* new_array; | 14431 NOT_TENURED: TENURED; |
| 14222 { MaybeObject* maybe_new_array = | 14432 Handle<FixedArray> fast_elements = |
| 14223 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); | 14433 isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure); |
| 14224 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; | 14434 dict->CopyValuesTo(*fast_elements); |
| 14225 } | 14435 object->ValidateElements(); |
| 14226 FixedArray* fast_elements = FixedArray::cast(new_array); | |
| 14227 dict->CopyValuesTo(fast_elements); | |
| 14228 ValidateElements(); | |
| 14229 | 14436 |
| 14230 set_map_and_elements(new_map, fast_elements); | 14437 object->set_map_and_elements(*new_map, *fast_elements); |
| 14231 } else if (HasExternalArrayElements()) { | 14438 } else if (object->HasExternalArrayElements()) { |
| 14232 // External arrays cannot have holes or undefined elements. | 14439 // External arrays cannot have holes or undefined elements. |
| 14233 return Smi::FromInt(ExternalArray::cast(elements())->length()); | 14440 return handle(Smi::FromInt( |
| 14234 } else if (!HasFastDoubleElements()) { | 14441 ExternalArray::cast(object->elements())->length()), isolate); |
| 14235 Object* obj; | 14442 } else if (!object->HasFastDoubleElements()) { |
| 14236 { MaybeObject* maybe_obj = EnsureWritableFastElements(); | 14443 JSObject::EnsureWritableFastElements(object); |
| 14237 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
| 14238 } | |
| 14239 } | 14444 } |
| 14240 ASSERT(HasFastSmiOrObjectElements() || HasFastDoubleElements()); | 14445 ASSERT(object->HasFastSmiOrObjectElements() || |
| 14446 object->HasFastDoubleElements()); |
| 14241 | 14447 |
| 14242 // Collect holes at the end, undefined before that and the rest at the | 14448 // Collect holes at the end, undefined before that and the rest at the |
| 14243 // start, and return the number of non-hole, non-undefined values. | 14449 // start, and return the number of non-hole, non-undefined values. |
| 14244 | 14450 |
| 14245 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); | 14451 Handle<FixedArrayBase> elements_base(object->elements()); |
| 14246 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); | 14452 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); |
| 14247 if (limit > elements_length) { | 14453 if (limit > elements_length) { |
| 14248 limit = elements_length ; | 14454 limit = elements_length ; |
| 14249 } | 14455 } |
| 14250 if (limit == 0) { | 14456 if (limit == 0) { |
| 14251 return Smi::FromInt(0); | 14457 return handle(Smi::FromInt(0), isolate); |
| 14252 } | |
| 14253 | |
| 14254 HeapNumber* result_double = NULL; | |
| 14255 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { | |
| 14256 // Pessimistically allocate space for return value before | |
| 14257 // we start mutating the array. | |
| 14258 Object* new_double; | |
| 14259 { MaybeObject* maybe_new_double = heap->AllocateHeapNumber(0.0); | |
| 14260 if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double; | |
| 14261 } | |
| 14262 result_double = HeapNumber::cast(new_double); | |
| 14263 } | 14458 } |
| 14264 | 14459 |
| 14265 uint32_t result = 0; | 14460 uint32_t result = 0; |
| 14266 if (elements_base->map() == heap->fixed_double_array_map()) { | 14461 if (elements_base->map() == isolate->heap()->fixed_double_array_map()) { |
| 14267 FixedDoubleArray* elements = FixedDoubleArray::cast(elements_base); | 14462 FixedDoubleArray* elements = FixedDoubleArray::cast(*elements_base); |
| 14268 // Split elements into defined and the_hole, in that order. | 14463 // Split elements into defined and the_hole, in that order. |
| 14269 unsigned int holes = limit; | 14464 unsigned int holes = limit; |
| 14270 // Assume most arrays contain no holes and undefined values, so minimize the | 14465 // Assume most arrays contain no holes and undefined values, so minimize the |
| 14271 // number of stores of non-undefined, non-the-hole values. | 14466 // number of stores of non-undefined, non-the-hole values. |
| 14272 for (unsigned int i = 0; i < holes; i++) { | 14467 for (unsigned int i = 0; i < holes; i++) { |
| 14273 if (elements->is_the_hole(i)) { | 14468 if (elements->is_the_hole(i)) { |
| 14274 holes--; | 14469 holes--; |
| 14275 } else { | 14470 } else { |
| 14276 continue; | 14471 continue; |
| 14277 } | 14472 } |
| 14278 // Position i needs to be filled. | 14473 // Position i needs to be filled. |
| 14279 while (holes > i) { | 14474 while (holes > i) { |
| 14280 if (elements->is_the_hole(holes)) { | 14475 if (elements->is_the_hole(holes)) { |
| 14281 holes--; | 14476 holes--; |
| 14282 } else { | 14477 } else { |
| 14283 elements->set(i, elements->get_scalar(holes)); | 14478 elements->set(i, elements->get_scalar(holes)); |
| 14284 break; | 14479 break; |
| 14285 } | 14480 } |
| 14286 } | 14481 } |
| 14287 } | 14482 } |
| 14288 result = holes; | 14483 result = holes; |
| 14289 while (holes < limit) { | 14484 while (holes < limit) { |
| 14290 elements->set_the_hole(holes); | 14485 elements->set_the_hole(holes); |
| 14291 holes++; | 14486 holes++; |
| 14292 } | 14487 } |
| 14293 } else { | 14488 } else { |
| 14294 FixedArray* elements = FixedArray::cast(elements_base); | 14489 FixedArray* elements = FixedArray::cast(*elements_base); |
| 14295 DisallowHeapAllocation no_gc; | 14490 DisallowHeapAllocation no_gc; |
| 14296 | 14491 |
| 14297 // Split elements into defined, undefined and the_hole, in that order. Only | 14492 // Split elements into defined, undefined and the_hole, in that order. Only |
| 14298 // count locations for undefined and the hole, and fill them afterwards. | 14493 // count locations for undefined and the hole, and fill them afterwards. |
| 14299 WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_gc); | 14494 WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_gc); |
| 14300 unsigned int undefs = limit; | 14495 unsigned int undefs = limit; |
| 14301 unsigned int holes = limit; | 14496 unsigned int holes = limit; |
| 14302 // Assume most arrays contain no holes and undefined values, so minimize the | 14497 // Assume most arrays contain no holes and undefined values, so minimize the |
| 14303 // number of stores of non-undefined, non-the-hole values. | 14498 // number of stores of non-undefined, non-the-hole values. |
| 14304 for (unsigned int i = 0; i < undefs; i++) { | 14499 for (unsigned int i = 0; i < undefs; i++) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 14329 while (undefs < holes) { | 14524 while (undefs < holes) { |
| 14330 elements->set_undefined(undefs); | 14525 elements->set_undefined(undefs); |
| 14331 undefs++; | 14526 undefs++; |
| 14332 } | 14527 } |
| 14333 while (holes < limit) { | 14528 while (holes < limit) { |
| 14334 elements->set_the_hole(holes); | 14529 elements->set_the_hole(holes); |
| 14335 holes++; | 14530 holes++; |
| 14336 } | 14531 } |
| 14337 } | 14532 } |
| 14338 | 14533 |
| 14339 if (result <= static_cast<uint32_t>(Smi::kMaxValue)) { | 14534 return isolate->factory()->NewNumberFromUint(result); |
| 14340 return Smi::FromInt(static_cast<int>(result)); | |
| 14341 } | |
| 14342 ASSERT_NE(NULL, result_double); | |
| 14343 result_double->set_value(static_cast<double>(result)); | |
| 14344 return result_double; | |
| 14345 } | 14535 } |
| 14346 | 14536 |
| 14347 | 14537 |
| 14348 ExternalArrayType JSTypedArray::type() { | 14538 ExternalArrayType JSTypedArray::type() { |
| 14349 switch (elements()->map()->instance_type()) { | 14539 switch (elements()->map()->instance_type()) { |
| 14350 case EXTERNAL_BYTE_ARRAY_TYPE: | 14540 case EXTERNAL_BYTE_ARRAY_TYPE: |
| 14351 return kExternalByteArray; | 14541 return kExternalByteArray; |
| 14352 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: | 14542 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: |
| 14353 return kExternalUnsignedByteArray; | 14543 return kExternalUnsignedByteArray; |
| 14354 case EXTERNAL_SHORT_ARRAY_TYPE: | 14544 case EXTERNAL_SHORT_ARRAY_TYPE: |
| (...skipping 1785 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16140 return static_cast<Type*>(type_raw()); | 16330 return static_cast<Type*>(type_raw()); |
| 16141 } | 16331 } |
| 16142 | 16332 |
| 16143 | 16333 |
| 16144 void PropertyCell::set_type(Type* type, WriteBarrierMode ignored) { | 16334 void PropertyCell::set_type(Type* type, WriteBarrierMode ignored) { |
| 16145 ASSERT(IsPropertyCell()); | 16335 ASSERT(IsPropertyCell()); |
| 16146 set_type_raw(type, ignored); | 16336 set_type_raw(type, ignored); |
| 16147 } | 16337 } |
| 16148 | 16338 |
| 16149 | 16339 |
| 16150 Type* PropertyCell::UpdateType(Handle<PropertyCell> cell, | 16340 Handle<Type> PropertyCell::UpdatedType(Handle<PropertyCell> cell, |
| 16151 Handle<Object> value) { | 16341 Handle<Object> value) { |
| 16152 Isolate* isolate = cell->GetIsolate(); | 16342 Isolate* isolate = cell->GetIsolate(); |
| 16153 Handle<Type> old_type(cell->type(), isolate); | 16343 Handle<Type> old_type(cell->type(), isolate); |
| 16154 // TODO(2803): Do not track ConsString as constant because they cannot be | 16344 // TODO(2803): Do not track ConsString as constant because they cannot be |
| 16155 // embedded into code. | 16345 // embedded into code. |
| 16156 Handle<Type> new_type(value->IsConsString() || value->IsTheHole() | 16346 Handle<Type> new_type(value->IsConsString() || value->IsTheHole() |
| 16157 ? Type::Any() | 16347 ? Type::Any() |
| 16158 : Type::Constant(value, isolate), isolate); | 16348 : Type::Constant(value, isolate), isolate); |
| 16159 | 16349 |
| 16160 if (new_type->Is(old_type)) { | 16350 if (new_type->Is(old_type)) { |
| 16161 return *old_type; | 16351 return old_type; |
| 16162 } | 16352 } |
| 16163 | 16353 |
| 16164 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 16354 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 16165 isolate, DependentCode::kPropertyCellChangedGroup); | 16355 isolate, DependentCode::kPropertyCellChangedGroup); |
| 16166 | 16356 |
| 16167 if (old_type->Is(Type::None()) || old_type->Is(Type::Undefined())) { | 16357 if (old_type->Is(Type::None()) || old_type->Is(Type::Undefined())) { |
| 16168 return *new_type; | 16358 return new_type; |
| 16169 } | 16359 } |
| 16170 | 16360 |
| 16171 return Type::Any(); | 16361 return handle(Type::Any(), isolate); |
| 16172 } | 16362 } |
| 16173 | 16363 |
| 16174 | 16364 |
| 16175 void PropertyCell::SetValueInferType(Handle<PropertyCell> cell, | 16365 void PropertyCell::SetValueInferType(Handle<PropertyCell> cell, |
| 16176 Handle<Object> value, | 16366 Handle<Object> value) { |
| 16177 WriteBarrierMode mode) { | 16367 cell->set_value(*value); |
| 16178 CALL_HEAP_FUNCTION_VOID(cell->GetIsolate(), | 16368 if (!Type::Any()->Is(cell->type())) { |
| 16179 cell->SetValueInferType(*value, mode)); | 16369 Handle<Type> new_type = UpdatedType(cell, value); |
| 16370 cell->set_type(*new_type); |
| 16371 } |
| 16180 } | 16372 } |
| 16181 | 16373 |
| 16182 | 16374 |
| 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) { | 16375 void PropertyCell::AddDependentCompilationInfo(CompilationInfo* info) { |
| 16201 Handle<DependentCode> dep(dependent_code()); | 16376 Handle<DependentCode> dep(dependent_code()); |
| 16202 Handle<DependentCode> codes = | 16377 Handle<DependentCode> codes = |
| 16203 DependentCode::Insert(dep, DependentCode::kPropertyCellChangedGroup, | 16378 DependentCode::Insert(dep, DependentCode::kPropertyCellChangedGroup, |
| 16204 info->object_wrapper()); | 16379 info->object_wrapper()); |
| 16205 if (*codes != dependent_code()) set_dependent_code(*codes); | 16380 if (*codes != dependent_code()) set_dependent_code(*codes); |
| 16206 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( | 16381 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( |
| 16207 Handle<HeapObject>(this), info->zone()); | 16382 Handle<HeapObject>(this), info->zone()); |
| 16208 } | 16383 } |
| 16209 | 16384 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 16221 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16396 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 16222 static const char* error_messages_[] = { | 16397 static const char* error_messages_[] = { |
| 16223 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16398 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 16224 }; | 16399 }; |
| 16225 #undef ERROR_MESSAGES_TEXTS | 16400 #undef ERROR_MESSAGES_TEXTS |
| 16226 return error_messages_[reason]; | 16401 return error_messages_[reason]; |
| 16227 } | 16402 } |
| 16228 | 16403 |
| 16229 | 16404 |
| 16230 } } // namespace v8::internal | 16405 } } // namespace v8::internal |
| OLD | NEW |