OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 Handle<JSGlobalProxy> ReinitializeJSGlobalProxy( | 127 Handle<JSGlobalProxy> ReinitializeJSGlobalProxy( |
128 Handle<JSFunction> constructor, | 128 Handle<JSFunction> constructor, |
129 Handle<JSGlobalProxy> global) { | 129 Handle<JSGlobalProxy> global) { |
130 CALL_HEAP_FUNCTION( | 130 CALL_HEAP_FUNCTION( |
131 constructor->GetIsolate(), | 131 constructor->GetIsolate(), |
132 constructor->GetHeap()->ReinitializeJSGlobalProxy(*constructor, *global), | 132 constructor->GetHeap()->ReinitializeJSGlobalProxy(*constructor, *global), |
133 JSGlobalProxy); | 133 JSGlobalProxy); |
134 } | 134 } |
135 | 135 |
136 | 136 |
137 Handle<Object> GetProperty(Handle<JSReceiver> obj, | 137 MaybeHandle<Object> GetProperty(Handle<JSReceiver> obj, |
138 const char* name) { | 138 const char* name) { |
139 Isolate* isolate = obj->GetIsolate(); | 139 Isolate* isolate = obj->GetIsolate(); |
140 Handle<String> str = isolate->factory()->InternalizeUtf8String(name); | 140 Handle<String> str = isolate->factory()->InternalizeUtf8String(name); |
141 ASSERT(!str.is_null()); | 141 ASSERT(!str.is_null()); |
142 return Object::GetPropertyOrElement(obj, str); | 142 return Object::GetPropertyOrElement(obj, str); |
143 } | 143 } |
144 | 144 |
145 | 145 |
146 // Wrappers for scripts are kept alive and cached in weak global | 146 // Wrappers for scripts are kept alive and cached in weak global |
147 // handles referred from foreign objects held by the scripts as long as | 147 // handles referred from foreign objects held by the scripts as long as |
148 // they are used. When they are not used anymore, the garbage | 148 // they are used. When they are not used anymore, the garbage |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 static bool ContainsOnlyValidKeys(Handle<FixedArray> array) { | 419 static bool ContainsOnlyValidKeys(Handle<FixedArray> array) { |
420 int len = array->length(); | 420 int len = array->length(); |
421 for (int i = 0; i < len; i++) { | 421 for (int i = 0; i < len; i++) { |
422 Object* e = array->get(i); | 422 Object* e = array->get(i); |
423 if (!(e->IsString() || e->IsNumber())) return false; | 423 if (!(e->IsString() || e->IsNumber())) return false; |
424 } | 424 } |
425 return true; | 425 return true; |
426 } | 426 } |
427 | 427 |
428 | 428 |
429 Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSReceiver> object, | 429 MaybeHandle<FixedArray> GetKeysInFixedArrayFor(Handle<JSReceiver> object, |
430 KeyCollectionType type, | 430 KeyCollectionType type) { |
431 bool* threw) { | |
432 USE(ContainsOnlyValidKeys); | 431 USE(ContainsOnlyValidKeys); |
433 Isolate* isolate = object->GetIsolate(); | 432 Isolate* isolate = object->GetIsolate(); |
434 Handle<FixedArray> content = isolate->factory()->empty_fixed_array(); | 433 Handle<FixedArray> content = isolate->factory()->empty_fixed_array(); |
435 Handle<JSObject> arguments_boilerplate = Handle<JSObject>( | 434 Handle<JSObject> arguments_boilerplate = Handle<JSObject>( |
436 isolate->context()->native_context()->sloppy_arguments_boilerplate(), | 435 isolate->context()->native_context()->sloppy_arguments_boilerplate(), |
437 isolate); | 436 isolate); |
438 Handle<JSFunction> arguments_function = Handle<JSFunction>( | 437 Handle<JSFunction> arguments_function = Handle<JSFunction>( |
439 JSFunction::cast(arguments_boilerplate->map()->constructor()), | 438 JSFunction::cast(arguments_boilerplate->map()->constructor()), |
440 isolate); | 439 isolate); |
441 | 440 |
442 // Only collect keys if access is permitted. | 441 // Only collect keys if access is permitted. |
443 for (Handle<Object> p = object; | 442 for (Handle<Object> p = object; |
444 *p != isolate->heap()->null_value(); | 443 *p != isolate->heap()->null_value(); |
445 p = Handle<Object>(p->GetPrototype(isolate), isolate)) { | 444 p = Handle<Object>(p->GetPrototype(isolate), isolate)) { |
446 if (p->IsJSProxy()) { | 445 if (p->IsJSProxy()) { |
447 Handle<JSProxy> proxy(JSProxy::cast(*p), isolate); | 446 Handle<JSProxy> proxy(JSProxy::cast(*p), isolate); |
448 Handle<Object> args[] = { proxy }; | 447 Handle<Object> args[] = { proxy }; |
| 448 bool has_pending_exception; |
449 Handle<Object> names = Execution::Call(isolate, | 449 Handle<Object> names = Execution::Call(isolate, |
450 isolate->proxy_enumerate(), | 450 isolate->proxy_enumerate(), |
451 object, | 451 object, |
452 ARRAY_SIZE(args), | 452 ARRAY_SIZE(args), |
453 args, | 453 args, |
454 threw); | 454 &has_pending_exception); |
455 if (*threw) return content; | 455 if (has_pending_exception) return MaybeHandle<FixedArray>(); |
456 content = FixedArray::AddKeysFromJSArray(content, | 456 ASSIGN_RETURN_ON_EXCEPTION( |
457 Handle<JSArray>::cast(names)); | 457 isolate, content, |
| 458 FixedArray::AddKeysFromJSArray(content, Handle<JSArray>::cast(names)), |
| 459 FixedArray); |
458 break; | 460 break; |
459 } | 461 } |
460 | 462 |
461 Handle<JSObject> current(JSObject::cast(*p), isolate); | 463 Handle<JSObject> current(JSObject::cast(*p), isolate); |
462 | 464 |
463 // Check access rights if required. | 465 // Check access rights if required. |
464 if (current->IsAccessCheckNeeded() && | 466 if (current->IsAccessCheckNeeded() && |
465 !isolate->MayNamedAccessWrapper(current, | 467 !isolate->MayNamedAccessWrapper(current, |
466 isolate->factory()->undefined_value(), | 468 isolate->factory()->undefined_value(), |
467 v8::ACCESS_KEYS)) { | 469 v8::ACCESS_KEYS)) { |
468 isolate->ReportFailedAccessCheckWrapper(current, v8::ACCESS_KEYS); | 470 isolate->ReportFailedAccessCheckWrapper(current, v8::ACCESS_KEYS); |
469 if (isolate->has_scheduled_exception()) { | 471 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray); |
470 isolate->PromoteScheduledException(); | |
471 *threw = true; | |
472 } | |
473 break; | 472 break; |
474 } | 473 } |
475 | 474 |
476 // Compute the element keys. | 475 // Compute the element keys. |
477 Handle<FixedArray> element_keys = | 476 Handle<FixedArray> element_keys = |
478 isolate->factory()->NewFixedArray(current->NumberOfEnumElements()); | 477 isolate->factory()->NewFixedArray(current->NumberOfEnumElements()); |
479 current->GetEnumElementKeys(*element_keys); | 478 current->GetEnumElementKeys(*element_keys); |
480 content = FixedArray::UnionOfKeys(content, element_keys); | 479 ASSIGN_RETURN_ON_EXCEPTION( |
| 480 isolate, content, |
| 481 FixedArray::UnionOfKeys(content, element_keys), |
| 482 FixedArray); |
481 ASSERT(ContainsOnlyValidKeys(content)); | 483 ASSERT(ContainsOnlyValidKeys(content)); |
482 | 484 |
483 // Add the element keys from the interceptor. | 485 // Add the element keys from the interceptor. |
484 if (current->HasIndexedInterceptor()) { | 486 if (current->HasIndexedInterceptor()) { |
485 v8::Handle<v8::Array> result = | 487 v8::Handle<v8::Array> result = |
486 GetKeysForIndexedInterceptor(object, current); | 488 GetKeysForIndexedInterceptor(object, current); |
487 if (!result.IsEmpty()) | 489 if (!result.IsEmpty()) { |
488 content = FixedArray::AddKeysFromJSArray( | 490 ASSIGN_RETURN_ON_EXCEPTION( |
489 content, v8::Utils::OpenHandle(*result)); | 491 isolate, content, |
| 492 FixedArray::AddKeysFromJSArray( |
| 493 content, v8::Utils::OpenHandle(*result)), |
| 494 FixedArray); |
| 495 } |
490 ASSERT(ContainsOnlyValidKeys(content)); | 496 ASSERT(ContainsOnlyValidKeys(content)); |
491 } | 497 } |
492 | 498 |
493 // We can cache the computed property keys if access checks are | 499 // We can cache the computed property keys if access checks are |
494 // not needed and no interceptors are involved. | 500 // not needed and no interceptors are involved. |
495 // | 501 // |
496 // We do not use the cache if the object has elements and | 502 // We do not use the cache if the object has elements and |
497 // therefore it does not make sense to cache the property names | 503 // therefore it does not make sense to cache the property names |
498 // for arguments objects. Arguments objects will always have | 504 // for arguments objects. Arguments objects will always have |
499 // elements. | 505 // elements. |
500 // Wrapped strings have elements, but don't have an elements | 506 // Wrapped strings have elements, but don't have an elements |
501 // array or dictionary. So the fast inline test for whether to | 507 // array or dictionary. So the fast inline test for whether to |
502 // use the cache says yes, so we should not create a cache. | 508 // use the cache says yes, so we should not create a cache. |
503 bool cache_enum_keys = | 509 bool cache_enum_keys = |
504 ((current->map()->constructor() != *arguments_function) && | 510 ((current->map()->constructor() != *arguments_function) && |
505 !current->IsJSValue() && | 511 !current->IsJSValue() && |
506 !current->IsAccessCheckNeeded() && | 512 !current->IsAccessCheckNeeded() && |
507 !current->HasNamedInterceptor() && | 513 !current->HasNamedInterceptor() && |
508 !current->HasIndexedInterceptor()); | 514 !current->HasIndexedInterceptor()); |
509 // Compute the property keys and cache them if possible. | 515 // Compute the property keys and cache them if possible. |
510 content = FixedArray::UnionOfKeys( | 516 ASSIGN_RETURN_ON_EXCEPTION( |
511 content, GetEnumPropertyKeys(current, cache_enum_keys)); | 517 isolate, content, |
| 518 FixedArray::UnionOfKeys( |
| 519 content, GetEnumPropertyKeys(current, cache_enum_keys)), |
| 520 FixedArray); |
512 ASSERT(ContainsOnlyValidKeys(content)); | 521 ASSERT(ContainsOnlyValidKeys(content)); |
513 | 522 |
514 // Add the property keys from the interceptor. | 523 // Add the property keys from the interceptor. |
515 if (current->HasNamedInterceptor()) { | 524 if (current->HasNamedInterceptor()) { |
516 v8::Handle<v8::Array> result = | 525 v8::Handle<v8::Array> result = |
517 GetKeysForNamedInterceptor(object, current); | 526 GetKeysForNamedInterceptor(object, current); |
518 if (!result.IsEmpty()) | 527 if (!result.IsEmpty()) { |
519 content = FixedArray::AddKeysFromJSArray( | 528 ASSIGN_RETURN_ON_EXCEPTION( |
520 content, v8::Utils::OpenHandle(*result)); | 529 isolate, content, |
| 530 FixedArray::AddKeysFromJSArray( |
| 531 content, v8::Utils::OpenHandle(*result)), |
| 532 FixedArray); |
| 533 } |
521 ASSERT(ContainsOnlyValidKeys(content)); | 534 ASSERT(ContainsOnlyValidKeys(content)); |
522 } | 535 } |
523 | 536 |
524 // If we only want local properties we bail out after the first | 537 // If we only want local properties we bail out after the first |
525 // iteration. | 538 // iteration. |
526 if (type == LOCAL_ONLY) | 539 if (type == LOCAL_ONLY) |
527 break; | 540 break; |
528 } | 541 } |
529 return content; | 542 return content; |
530 } | 543 } |
531 | 544 |
532 | 545 |
533 Handle<JSArray> GetKeysFor(Handle<JSReceiver> object, bool* threw) { | 546 MaybeHandle<JSArray> GetKeysFor(Handle<JSReceiver> object) { |
534 Isolate* isolate = object->GetIsolate(); | 547 Isolate* isolate = object->GetIsolate(); |
535 isolate->counters()->for_in()->Increment(); | 548 isolate->counters()->for_in()->Increment(); |
536 Handle<FixedArray> elements = | 549 Handle<FixedArray> elements; |
537 GetKeysInFixedArrayFor(object, INCLUDE_PROTOS, threw); | 550 ASSIGN_RETURN_ON_EXCEPTION( |
| 551 isolate, elements, |
| 552 GetKeysInFixedArrayFor(object, INCLUDE_PROTOS), |
| 553 JSArray); |
538 return isolate->factory()->NewJSArrayWithElements(elements); | 554 return isolate->factory()->NewJSArrayWithElements(elements); |
539 } | 555 } |
540 | 556 |
541 | 557 |
542 Handle<FixedArray> ReduceFixedArrayTo(Handle<FixedArray> array, int length) { | 558 Handle<FixedArray> ReduceFixedArrayTo(Handle<FixedArray> array, int length) { |
543 ASSERT(array->length() >= length); | 559 ASSERT(array->length() >= length); |
544 if (array->length() == length) return array; | 560 if (array->length() == length) return array; |
545 | 561 |
546 Handle<FixedArray> new_array = | 562 Handle<FixedArray> new_array = |
547 array->GetIsolate()->factory()->NewFixedArray(length); | 563 array->GetIsolate()->factory()->NewFixedArray(length); |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
698 Handle<Code> code) { | 714 Handle<Code> code) { |
699 heap->EnsureWeakObjectToCodeTable(); | 715 heap->EnsureWeakObjectToCodeTable(); |
700 Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(*object)); | 716 Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(*object)); |
701 dep = DependentCode::Insert(dep, DependentCode::kWeaklyEmbeddedGroup, code); | 717 dep = DependentCode::Insert(dep, DependentCode::kWeaklyEmbeddedGroup, code); |
702 CALL_HEAP_FUNCTION_VOID(heap->isolate(), | 718 CALL_HEAP_FUNCTION_VOID(heap->isolate(), |
703 heap->AddWeakObjectToCodeDependency(*object, *dep)); | 719 heap->AddWeakObjectToCodeDependency(*object, *dep)); |
704 } | 720 } |
705 | 721 |
706 | 722 |
707 } } // namespace v8::internal | 723 } } // namespace v8::internal |
OLD | NEW |