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 |