| 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 24 matching lines...) Expand all Loading... |
| 35 #include "frames-inl.h" | 35 #include "frames-inl.h" |
| 36 #include "isolate.h" | 36 #include "isolate.h" |
| 37 #include "list-inl.h" | 37 #include "list-inl.h" |
| 38 #include "property-details.h" | 38 #include "property-details.h" |
| 39 | 39 |
| 40 namespace v8 { | 40 namespace v8 { |
| 41 namespace internal { | 41 namespace internal { |
| 42 | 42 |
| 43 | 43 |
| 44 template <class C> | 44 template <class C> |
| 45 static C* FindInPrototypeChain(Object* obj, bool* found_it) { | 45 static C* FindInstanceOf(Object* obj) { |
| 46 ASSERT(!*found_it); | 46 for (Object* cur = obj; !cur->IsNull(); cur = cur->GetPrototype()) { |
| 47 Heap* heap = HEAP; | 47 if (Is<C>(cur)) return C::cast(cur); |
| 48 while (!Is<C>(obj)) { | |
| 49 if (obj == heap->null_value()) return NULL; | |
| 50 obj = obj->GetPrototype(); | |
| 51 } | 48 } |
| 52 *found_it = true; | 49 return NULL; |
| 53 return C::cast(obj); | |
| 54 } | 50 } |
| 55 | 51 |
| 56 | 52 |
| 57 // Entry point that never should be called. | 53 // Entry point that never should be called. |
| 58 MaybeObject* Accessors::IllegalSetter(JSObject*, Object*, void*) { | 54 MaybeObject* Accessors::IllegalSetter(JSObject*, Object*, void*) { |
| 59 UNREACHABLE(); | 55 UNREACHABLE(); |
| 60 return NULL; | 56 return NULL; |
| 61 } | 57 } |
| 62 | 58 |
| 63 | 59 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 74 } | 70 } |
| 75 | 71 |
| 76 | 72 |
| 77 // | 73 // |
| 78 // Accessors::ArrayLength | 74 // Accessors::ArrayLength |
| 79 // | 75 // |
| 80 | 76 |
| 81 | 77 |
| 82 MaybeObject* Accessors::ArrayGetLength(Object* object, void*) { | 78 MaybeObject* Accessors::ArrayGetLength(Object* object, void*) { |
| 83 // Traverse the prototype chain until we reach an array. | 79 // Traverse the prototype chain until we reach an array. |
| 84 bool found_it = false; | 80 JSArray* holder = FindInstanceOf<JSArray>(object); |
| 85 JSArray* holder = FindInPrototypeChain<JSArray>(object, &found_it); | 81 return holder == NULL ? Smi::FromInt(0) : holder->length(); |
| 86 if (!found_it) return Smi::FromInt(0); | |
| 87 return holder->length(); | |
| 88 } | 82 } |
| 89 | 83 |
| 90 | 84 |
| 91 // The helper function will 'flatten' Number objects. | 85 // The helper function will 'flatten' Number objects. |
| 92 Object* Accessors::FlattenNumber(Object* value) { | 86 Object* Accessors::FlattenNumber(Object* value) { |
| 93 if (value->IsNumber() || !value->IsJSValue()) return value; | 87 if (value->IsNumber() || !value->IsJSValue()) return value; |
| 94 JSValue* wrapper = JSValue::cast(value); | 88 JSValue* wrapper = JSValue::cast(value); |
| 95 ASSERT(Isolate::Current()->context()->native_context()->number_function()-> | 89 ASSERT(Isolate::Current()->context()->native_context()->number_function()-> |
| 96 has_initial_map()); | 90 has_initial_map()); |
| 97 Map* number_map = Isolate::Current()->context()->native_context()-> | 91 Map* number_map = Isolate::Current()->context()->native_context()-> |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 }; | 435 }; |
| 442 | 436 |
| 443 | 437 |
| 444 // | 438 // |
| 445 // Accessors::FunctionPrototype | 439 // Accessors::FunctionPrototype |
| 446 // | 440 // |
| 447 | 441 |
| 448 | 442 |
| 449 MaybeObject* Accessors::FunctionGetPrototype(Object* object, void*) { | 443 MaybeObject* Accessors::FunctionGetPrototype(Object* object, void*) { |
| 450 Heap* heap = Isolate::Current()->heap(); | 444 Heap* heap = Isolate::Current()->heap(); |
| 451 bool found_it = false; | 445 JSFunction* function = FindInstanceOf<JSFunction>(object); |
| 452 JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it); | 446 if (function == NULL) return heap->undefined_value(); |
| 453 if (!found_it) return heap->undefined_value(); | |
| 454 while (!function->should_have_prototype()) { | 447 while (!function->should_have_prototype()) { |
| 455 found_it = false; | 448 function = FindInstanceOf<JSFunction>(function->GetPrototype()); |
| 456 function = FindInPrototypeChain<JSFunction>(object->GetPrototype(), | |
| 457 &found_it); | |
| 458 // There has to be one because we hit the getter. | 449 // There has to be one because we hit the getter. |
| 459 ASSERT(found_it); | 450 ASSERT(function != NULL); |
| 460 } | 451 } |
| 461 | 452 |
| 462 if (!function->has_prototype()) { | 453 if (!function->has_prototype()) { |
| 463 Object* prototype; | 454 Object* prototype; |
| 464 { MaybeObject* maybe_prototype = heap->AllocateFunctionPrototype(function); | 455 { MaybeObject* maybe_prototype = heap->AllocateFunctionPrototype(function); |
| 465 if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype; | 456 if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype; |
| 466 } | 457 } |
| 467 Object* result; | 458 Object* result; |
| 468 { MaybeObject* maybe_result = function->SetPrototype(prototype); | 459 { MaybeObject* maybe_result = function->SetPrototype(prototype); |
| 469 if (!maybe_result->ToObject(&result)) return maybe_result; | 460 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 470 } | 461 } |
| 471 } | 462 } |
| 472 return function->prototype(); | 463 return function->prototype(); |
| 473 } | 464 } |
| 474 | 465 |
| 475 | 466 |
| 476 MaybeObject* Accessors::FunctionSetPrototype(JSObject* object, | 467 MaybeObject* Accessors::FunctionSetPrototype(JSObject* object, |
| 477 Object* value, | 468 Object* value, |
| 478 void*) { | 469 void*) { |
| 479 Heap* heap = object->GetHeap(); | 470 Heap* heap = object->GetHeap(); |
| 480 bool found_it = false; | 471 JSFunction* function = FindInstanceOf<JSFunction>(object); |
| 481 JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it); | 472 if (function == NULL) return heap->undefined_value(); |
| 482 if (!found_it) return heap->undefined_value(); | |
| 483 if (!function->should_have_prototype()) { | 473 if (!function->should_have_prototype()) { |
| 484 // Since we hit this accessor, object will have no prototype property. | 474 // Since we hit this accessor, object will have no prototype property. |
| 485 return object->SetLocalPropertyIgnoreAttributes(heap->prototype_symbol(), | 475 return object->SetLocalPropertyIgnoreAttributes(heap->prototype_symbol(), |
| 486 value, | 476 value, |
| 487 NONE); | 477 NONE); |
| 488 } | 478 } |
| 489 | 479 |
| 490 Object* prototype; | 480 Object* prototype; |
| 491 { MaybeObject* maybe_prototype = function->SetPrototype(value); | 481 { MaybeObject* maybe_prototype = function->SetPrototype(value); |
| 492 if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype; | 482 if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype; |
| 493 } | 483 } |
| 494 ASSERT(function->prototype() == value); | 484 ASSERT(function->prototype() == value); |
| 495 return function; | 485 return function; |
| 496 } | 486 } |
| 497 | 487 |
| 498 | 488 |
| 499 const AccessorDescriptor Accessors::FunctionPrototype = { | 489 const AccessorDescriptor Accessors::FunctionPrototype = { |
| 500 FunctionGetPrototype, | 490 FunctionGetPrototype, |
| 501 FunctionSetPrototype, | 491 FunctionSetPrototype, |
| 502 0 | 492 0 |
| 503 }; | 493 }; |
| 504 | 494 |
| 505 | 495 |
| 506 // | 496 // |
| 507 // Accessors::FunctionLength | 497 // Accessors::FunctionLength |
| 508 // | 498 // |
| 509 | 499 |
| 510 | 500 |
| 511 MaybeObject* Accessors::FunctionGetLength(Object* object, void*) { | 501 MaybeObject* Accessors::FunctionGetLength(Object* object, void*) { |
| 512 bool found_it = false; | 502 JSFunction* function = FindInstanceOf<JSFunction>(object); |
| 513 JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it); | 503 if (function == NULL) return Smi::FromInt(0); |
| 514 if (!found_it) return Smi::FromInt(0); | |
| 515 // Check if already compiled. | 504 // Check if already compiled. |
| 516 if (!function->shared()->is_compiled()) { | 505 if (function->shared()->is_compiled()) { |
| 517 // If the function isn't compiled yet, the length is not computed | |
| 518 // correctly yet. Compile it now and return the right length. | |
| 519 HandleScope scope; | |
| 520 Handle<JSFunction> handle(function); | |
| 521 if (!JSFunction::CompileLazy(handle, KEEP_EXCEPTION)) { | |
| 522 return Failure::Exception(); | |
| 523 } | |
| 524 return Smi::FromInt(handle->shared()->length()); | |
| 525 } else { | |
| 526 return Smi::FromInt(function->shared()->length()); | 506 return Smi::FromInt(function->shared()->length()); |
| 527 } | 507 } |
| 508 // If the function isn't compiled yet, the length is not computed correctly |
| 509 // yet. Compile it now and return the right length. |
| 510 HandleScope scope; |
| 511 Handle<JSFunction> handle(function); |
| 512 if (JSFunction::CompileLazy(handle, KEEP_EXCEPTION)) { |
| 513 return Smi::FromInt(handle->shared()->length()); |
| 514 } |
| 515 return Failure::Exception(); |
| 528 } | 516 } |
| 529 | 517 |
| 530 | 518 |
| 531 const AccessorDescriptor Accessors::FunctionLength = { | 519 const AccessorDescriptor Accessors::FunctionLength = { |
| 532 FunctionGetLength, | 520 FunctionGetLength, |
| 533 ReadOnlySetAccessor, | 521 ReadOnlySetAccessor, |
| 534 0 | 522 0 |
| 535 }; | 523 }; |
| 536 | 524 |
| 537 | 525 |
| 538 // | 526 // |
| 539 // Accessors::FunctionName | 527 // Accessors::FunctionName |
| 540 // | 528 // |
| 541 | 529 |
| 542 | 530 |
| 543 MaybeObject* Accessors::FunctionGetName(Object* object, void*) { | 531 MaybeObject* Accessors::FunctionGetName(Object* object, void*) { |
| 544 bool found_it = false; | 532 JSFunction* holder = FindInstanceOf<JSFunction>(object); |
| 545 JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it); | 533 return holder == NULL ? HEAP->undefined_value() : holder->shared()->name(); |
| 546 if (!found_it) return HEAP->undefined_value(); | |
| 547 return holder->shared()->name(); | |
| 548 } | 534 } |
| 549 | 535 |
| 550 | 536 |
| 551 const AccessorDescriptor Accessors::FunctionName = { | 537 const AccessorDescriptor Accessors::FunctionName = { |
| 552 FunctionGetName, | 538 FunctionGetName, |
| 553 ReadOnlySetAccessor, | 539 ReadOnlySetAccessor, |
| 554 0 | 540 0 |
| 555 }; | 541 }; |
| 556 | 542 |
| 557 | 543 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 582 args_slots.Dispose(); | 568 args_slots.Dispose(); |
| 583 | 569 |
| 584 // Return the freshly allocated arguments object. | 570 // Return the freshly allocated arguments object. |
| 585 return *arguments; | 571 return *arguments; |
| 586 } | 572 } |
| 587 | 573 |
| 588 | 574 |
| 589 MaybeObject* Accessors::FunctionGetArguments(Object* object, void*) { | 575 MaybeObject* Accessors::FunctionGetArguments(Object* object, void*) { |
| 590 Isolate* isolate = Isolate::Current(); | 576 Isolate* isolate = Isolate::Current(); |
| 591 HandleScope scope(isolate); | 577 HandleScope scope(isolate); |
| 592 bool found_it = false; | 578 JSFunction* holder = FindInstanceOf<JSFunction>(object); |
| 593 JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it); | 579 if (holder == NULL) return isolate->heap()->undefined_value(); |
| 594 if (!found_it) return isolate->heap()->undefined_value(); | |
| 595 Handle<JSFunction> function(holder, isolate); | 580 Handle<JSFunction> function(holder, isolate); |
| 596 | 581 |
| 597 if (function->shared()->native()) return isolate->heap()->null_value(); | 582 if (function->shared()->native()) return isolate->heap()->null_value(); |
| 598 // Find the top invocation of the function by traversing frames. | 583 // Find the top invocation of the function by traversing frames. |
| 599 List<JSFunction*> functions(2); | 584 List<JSFunction*> functions(2); |
| 600 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) { | 585 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) { |
| 601 JavaScriptFrame* frame = it.frame(); | 586 JavaScriptFrame* frame = it.frame(); |
| 602 frame->GetFunctions(&functions); | 587 frame->GetFunctions(&functions); |
| 603 for (int i = functions.length() - 1; i >= 0; i--) { | 588 for (int i = functions.length() - 1; i >= 0; i--) { |
| 604 // Skip all frames that aren't invocations of the given function. | 589 // Skip all frames that aren't invocations of the given function. |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 720 JavaScriptFrameIterator frame_iterator_; | 705 JavaScriptFrameIterator frame_iterator_; |
| 721 List<JSFunction*> functions_; | 706 List<JSFunction*> functions_; |
| 722 int index_; | 707 int index_; |
| 723 }; | 708 }; |
| 724 | 709 |
| 725 | 710 |
| 726 MaybeObject* Accessors::FunctionGetCaller(Object* object, void*) { | 711 MaybeObject* Accessors::FunctionGetCaller(Object* object, void*) { |
| 727 Isolate* isolate = Isolate::Current(); | 712 Isolate* isolate = Isolate::Current(); |
| 728 HandleScope scope(isolate); | 713 HandleScope scope(isolate); |
| 729 AssertNoAllocation no_alloc; | 714 AssertNoAllocation no_alloc; |
| 730 bool found_it = false; | 715 JSFunction* holder = FindInstanceOf<JSFunction>(object); |
| 731 JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it); | 716 if (holder == NULL) return isolate->heap()->undefined_value(); |
| 732 if (!found_it) return isolate->heap()->undefined_value(); | |
| 733 if (holder->shared()->native()) return isolate->heap()->null_value(); | 717 if (holder->shared()->native()) return isolate->heap()->null_value(); |
| 734 Handle<JSFunction> function(holder, isolate); | 718 Handle<JSFunction> function(holder, isolate); |
| 735 | 719 |
| 736 FrameFunctionIterator it(isolate, no_alloc); | 720 FrameFunctionIterator it(isolate, no_alloc); |
| 737 | 721 |
| 738 // Find the function from the frames. | 722 // Find the function from the frames. |
| 739 if (!it.Find(*function)) { | 723 if (!it.Find(*function)) { |
| 740 // No frame corresponding to the given function found. Return null. | 724 // No frame corresponding to the given function found. Return null. |
| 741 return isolate->heap()->null_value(); | 725 return isolate->heap()->null_value(); |
| 742 } | 726 } |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 864 info->set_data(Smi::FromInt(index)); | 848 info->set_data(Smi::FromInt(index)); |
| 865 Handle<Object> getter = v8::FromCData(&ModuleGetExport); | 849 Handle<Object> getter = v8::FromCData(&ModuleGetExport); |
| 866 Handle<Object> setter = v8::FromCData(&ModuleSetExport); | 850 Handle<Object> setter = v8::FromCData(&ModuleSetExport); |
| 867 info->set_getter(*getter); | 851 info->set_getter(*getter); |
| 868 if (!(attributes & ReadOnly)) info->set_setter(*setter); | 852 if (!(attributes & ReadOnly)) info->set_setter(*setter); |
| 869 return info; | 853 return info; |
| 870 } | 854 } |
| 871 | 855 |
| 872 | 856 |
| 873 } } // namespace v8::internal | 857 } } // namespace v8::internal |
| OLD | NEW |