OLD | NEW |
---|---|
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
428 StackFrameLocator locator; | 428 StackFrameLocator locator; |
429 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 429 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
430 int index = frame->ComputeExpressionsCount() - (argc + 1); | 430 int index = frame->ComputeExpressionsCount() - (argc + 1); |
431 frame->SetExpression(index, *target); | 431 frame->SetExpression(index, *target); |
432 } | 432 } |
433 | 433 |
434 return *delegate; | 434 return *delegate; |
435 } | 435 } |
436 | 436 |
437 | 437 |
438 void CallICBase::ReceiverToObject(Handle<Object> object) { | 438 void CallICBase::ReceiverToObjectIfRequired(Handle<Object> callee, |
439 HandleScope scope; | 439 Handle<Object> object) { |
440 Handle<Object> receiver(object); | 440 if (callee->IsJSFunction()) { |
441 JSFunction* function = JSFunction::cast(*callee); | |
Mads Ager (chromium)
2011/02/21 07:45:11
Let's keep it all in handles here to not mix handl
Martin Maly
2011/02/22 00:40:35
Done.
| |
442 if (function->shared()->strict_mode() || function->IsBuiltin()) { | |
443 // Do not wrap receiver for strict mode functions or for builtins. | |
444 return; | |
445 } | |
446 } | |
441 | 447 |
442 // Change the receiver to the result of calling ToObject on it. | 448 // And only wrap string, number or boolean. |
443 const int argc = this->target()->arguments_count(); | 449 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { |
444 StackFrameLocator locator; | 450 // Change the receiver to the result of calling ToObject on it. |
445 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 451 const int argc = this->target()->arguments_count(); |
446 int index = frame->ComputeExpressionsCount() - (argc + 1); | 452 StackFrameLocator locator; |
447 frame->SetExpression(index, *Factory::ToObject(object)); | 453 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
454 int index = frame->ComputeExpressionsCount() - (argc + 1); | |
455 frame->SetExpression(index, *Factory::ToObject(object)); | |
456 } | |
448 } | 457 } |
449 | 458 |
450 | 459 |
451 MaybeObject* CallICBase::LoadFunction(State state, | 460 MaybeObject* CallICBase::LoadFunction(State state, |
452 Code::ExtraICState extra_ic_state, | 461 Code::ExtraICState extra_ic_state, |
453 Handle<Object> object, | 462 Handle<Object> object, |
454 Handle<String> name) { | 463 Handle<String> name) { |
455 // If the object is undefined or null it's illegal to try to get any | 464 // If the object is undefined or null it's illegal to try to get any |
456 // of its properties; throw a TypeError in that case. | 465 // of its properties; throw a TypeError in that case. |
457 if (object->IsUndefined() || object->IsNull()) { | 466 if (object->IsUndefined() || object->IsNull()) { |
458 return TypeError("non_object_property_call", object, name); | 467 return TypeError("non_object_property_call", object, name); |
459 } | 468 } |
460 | 469 |
461 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { | |
462 ReceiverToObject(object); | |
463 } | |
464 | |
465 // Check if the name is trivially convertible to an index and get | 470 // Check if the name is trivially convertible to an index and get |
466 // the element if so. | 471 // the element if so. |
467 uint32_t index; | 472 uint32_t index; |
468 if (name->AsArrayIndex(&index)) { | 473 if (name->AsArrayIndex(&index)) { |
469 Object* result; | 474 Object* result; |
470 { MaybeObject* maybe_result = object->GetElement(index); | 475 { MaybeObject* maybe_result = object->GetElement(index); |
471 if (!maybe_result->ToObject(&result)) return maybe_result; | 476 if (!maybe_result->ToObject(&result)) return maybe_result; |
472 } | 477 } |
473 | 478 |
474 if (result->IsJSFunction()) return result; | 479 if (result->IsJSFunction()) return result; |
(...skipping 23 matching lines...) Expand all Loading... | |
498 UpdateCaches(&lookup, state, extra_ic_state, object, name); | 503 UpdateCaches(&lookup, state, extra_ic_state, object, name); |
499 } | 504 } |
500 | 505 |
501 // Get the property. | 506 // Get the property. |
502 PropertyAttributes attr; | 507 PropertyAttributes attr; |
503 Object* result; | 508 Object* result; |
504 { MaybeObject* maybe_result = | 509 { MaybeObject* maybe_result = |
505 object->GetProperty(*object, &lookup, *name, &attr); | 510 object->GetProperty(*object, &lookup, *name, &attr); |
506 if (!maybe_result->ToObject(&result)) return maybe_result; | 511 if (!maybe_result->ToObject(&result)) return maybe_result; |
507 } | 512 } |
513 | |
508 if (lookup.type() == INTERCEPTOR) { | 514 if (lookup.type() == INTERCEPTOR) { |
509 // If the object does not have the requested property, check which | 515 // If the object does not have the requested property, check which |
510 // exception we need to throw. | 516 // exception we need to throw. |
511 if (attr == ABSENT) { | 517 if (attr == ABSENT) { |
512 if (IsContextual(object)) { | 518 if (IsContextual(object)) { |
513 return ReferenceError("not_defined", name); | 519 return ReferenceError("not_defined", name); |
514 } | 520 } |
515 return TypeError("undefined_method", object, name); | 521 return TypeError("undefined_method", object, name); |
516 } | 522 } |
517 } | 523 } |
518 | 524 |
519 ASSERT(result != Heap::the_hole_value()); | 525 ASSERT(!result->IsTheHole()); |
520 | 526 |
521 if (result->IsJSFunction()) { | 527 HandleScope scope; |
528 // Wrap result in a handle because ReceiverToObjectIfRequired may allocate | |
529 // new object and cause GC. | |
530 Handle<Object> result_handle(result); | |
531 // Make receiver an object if the callee requires it. Strict mode or builtin | |
532 // functions do not wrap the receiver, non-strict functions and objects | |
533 // called as functions do. | |
534 ReceiverToObjectIfRequired(result_handle, object); | |
535 | |
536 if (result_handle->IsJSFunction()) { | |
522 #ifdef ENABLE_DEBUGGER_SUPPORT | 537 #ifdef ENABLE_DEBUGGER_SUPPORT |
523 // Handle stepping into a function if step into is active. | 538 // Handle stepping into a function if step into is active. |
524 if (Debug::StepInActive()) { | 539 if (Debug::StepInActive()) { |
525 // Protect the result in a handle as the debugger can allocate and might | 540 // Protect the result in a handle as the debugger can allocate and might |
526 // cause GC. | 541 // cause GC. |
527 HandleScope scope; | 542 Handle<JSFunction> function(JSFunction::cast(*result_handle)); |
528 Handle<JSFunction> function(JSFunction::cast(result)); | |
529 Debug::HandleStepIn(function, object, fp(), false); | 543 Debug::HandleStepIn(function, object, fp(), false); |
530 return *function; | 544 return *function; |
531 } | 545 } |
532 #endif | 546 #endif |
533 | 547 |
534 return result; | 548 return *result_handle; |
535 } | 549 } |
536 | 550 |
537 // Try to find a suitable function delegate for the object at hand. | 551 // Try to find a suitable function delegate for the object at hand. |
538 result = TryCallAsFunction(result); | 552 result_handle = Handle<Object>(TryCallAsFunction(*result_handle)); |
539 MaybeObject* answer = result; | 553 if (result_handle->IsJSFunction()) return *result_handle; |
540 if (!result->IsJSFunction()) { | 554 |
541 answer = TypeError("property_not_function", object, name); | 555 return TypeError("property_not_function", object, name); |
542 } | |
543 return answer; | |
544 } | 556 } |
545 | 557 |
546 | 558 |
547 bool CallICBase::TryUpdateExtraICState(LookupResult* lookup, | 559 bool CallICBase::TryUpdateExtraICState(LookupResult* lookup, |
548 Handle<Object> object, | 560 Handle<Object> object, |
549 Code::ExtraICState* extra_ic_state) { | 561 Code::ExtraICState* extra_ic_state) { |
550 ASSERT(kind_ == Code::CALL_IC); | 562 ASSERT(kind_ == Code::CALL_IC); |
551 if (lookup->type() != CONSTANT_FUNCTION) return false; | 563 if (lookup->type() != CONSTANT_FUNCTION) return false; |
552 JSFunction* function = lookup->GetConstantFunction(); | 564 JSFunction* function = lookup->GetConstantFunction(); |
553 if (!function->shared()->HasBuiltinFunctionId()) return false; | 565 if (!function->shared()->HasBuiltinFunctionId()) return false; |
554 | 566 |
555 // Fetch the arguments passed to the called function. | 567 // Fetch the arguments passed to the called function. |
556 const int argc = target()->arguments_count(); | 568 const int argc = target()->arguments_count(); |
557 Address entry = Top::c_entry_fp(Top::GetCurrentThread()); | 569 Address entry = Top::c_entry_fp(Top::GetCurrentThread()); |
558 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); | 570 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); |
559 Arguments args(argc + 1, | 571 Arguments args(argc + 1, |
560 &Memory::Object_at(fp + | 572 &Memory::Object_at(fp + |
561 StandardFrameConstants::kCallerSPOffset + | 573 StandardFrameConstants::kCallerSPOffset + |
562 argc * kPointerSize)); | 574 argc * kPointerSize)); |
563 switch (function->shared()->builtin_function_id()) { | 575 switch (function->shared()->builtin_function_id()) { |
564 case kStringCharCodeAt: | 576 case kStringCharCodeAt: |
565 case kStringCharAt: | 577 case kStringCharAt: |
566 if (object->IsString()) { | 578 if (object->IsString()) { |
567 String* string = String::cast(*object); | 579 String* string = String::cast(*object); |
568 // Check that there's the right wrapper in the receiver slot. | 580 // Check there's the right string value or wrapper in the receiver slot. |
569 ASSERT(string == JSValue::cast(args[0])->value()); | 581 ASSERT(string == args[0] || string == JSValue::cast(args[0])->value()); |
570 // If we're in the default (fastest) state and the index is | 582 // If we're in the default (fastest) state and the index is |
571 // out of bounds, update the state to record this fact. | 583 // out of bounds, update the state to record this fact. |
572 if (*extra_ic_state == DEFAULT_STRING_STUB && | 584 if (*extra_ic_state == DEFAULT_STRING_STUB && |
573 argc >= 1 && args[1]->IsNumber()) { | 585 argc >= 1 && args[1]->IsNumber()) { |
574 double index; | 586 double index; |
575 if (args[1]->IsSmi()) { | 587 if (args[1]->IsSmi()) { |
576 index = Smi::cast(args[1])->value(); | 588 index = Smi::cast(args[1])->value(); |
577 } else { | 589 } else { |
578 ASSERT(args[1]->IsHeapNumber()); | 590 ASSERT(args[1]->IsHeapNumber()); |
579 index = DoubleToInteger(HeapNumber::cast(args[1])->value()); | 591 index = DoubleToInteger(HeapNumber::cast(args[1])->value()); |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
768 return CallICBase::LoadFunction(state, | 780 return CallICBase::LoadFunction(state, |
769 Code::kNoExtraICState, | 781 Code::kNoExtraICState, |
770 object, | 782 object, |
771 Handle<String>::cast(key)); | 783 Handle<String>::cast(key)); |
772 } | 784 } |
773 | 785 |
774 if (object->IsUndefined() || object->IsNull()) { | 786 if (object->IsUndefined() || object->IsNull()) { |
775 return TypeError("non_object_property_call", object, key); | 787 return TypeError("non_object_property_call", object, key); |
776 } | 788 } |
777 | 789 |
778 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { | |
779 ReceiverToObject(object); | |
780 } | |
781 | |
782 if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) { | 790 if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) { |
783 int argc = target()->arguments_count(); | 791 int argc = target()->arguments_count(); |
784 InLoopFlag in_loop = target()->ic_in_loop(); | 792 InLoopFlag in_loop = target()->ic_in_loop(); |
785 MaybeObject* maybe_code = StubCache::ComputeCallMegamorphic( | 793 MaybeObject* maybe_code = StubCache::ComputeCallMegamorphic( |
786 argc, in_loop, Code::KEYED_CALL_IC); | 794 argc, in_loop, Code::KEYED_CALL_IC); |
787 Object* code; | 795 Object* code; |
788 if (maybe_code->ToObject(&code)) { | 796 if (maybe_code->ToObject(&code)) { |
789 set_target(Code::cast(code)); | 797 set_target(Code::cast(code)); |
790 #ifdef DEBUG | 798 #ifdef DEBUG |
791 TraceIC( | 799 TraceIC( |
792 "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : ""); | 800 "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : ""); |
793 #endif | 801 #endif |
794 } | 802 } |
795 } | 803 } |
796 Object* result; | 804 |
797 { MaybeObject* maybe_result = Runtime::GetObjectProperty(object, key); | 805 HandleScope scope; |
798 if (!maybe_result->ToObject(&result)) return maybe_result; | 806 Handle<Object> result = GetProperty(object, key); |
799 } | 807 |
800 if (result->IsJSFunction()) return result; | 808 // Make receiver an object if the callee requires it. Strict mode or builtin |
801 result = TryCallAsFunction(result); | 809 // functions do not wrap the receiver, non-strict functions and objects |
802 MaybeObject* answer = result; | 810 // called as functions do. |
803 if (!result->IsJSFunction()) { | 811 ReceiverToObjectIfRequired(result, object); |
804 answer = TypeError("property_not_function", object, key); | 812 |
805 } | 813 if (result->IsJSFunction()) return *result; |
806 return answer; | 814 result = Handle<Object>(TryCallAsFunction(*result)); |
815 if (result->IsJSFunction()) return *result; | |
816 | |
817 return TypeError("property_not_function", object, key); | |
807 } | 818 } |
808 | 819 |
809 | 820 |
810 #ifdef DEBUG | 821 #ifdef DEBUG |
811 #define TRACE_IC_NAMED(msg, name) \ | 822 #define TRACE_IC_NAMED(msg, name) \ |
812 if (FLAG_trace_ic) PrintF(msg, *(name)->ToCString()) | 823 if (FLAG_trace_ic) PrintF(msg, *(name)->ToCString()) |
813 #else | 824 #else |
814 #define TRACE_IC_NAMED(msg, name) | 825 #define TRACE_IC_NAMED(msg, name) |
815 #endif | 826 #endif |
816 | 827 |
(...skipping 1469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2286 #undef ADDR | 2297 #undef ADDR |
2287 }; | 2298 }; |
2288 | 2299 |
2289 | 2300 |
2290 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2301 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2291 return IC_utilities[id]; | 2302 return IC_utilities[id]; |
2292 } | 2303 } |
2293 | 2304 |
2294 | 2305 |
2295 } } // namespace v8::internal | 2306 } } // namespace v8::internal |
OLD | NEW |