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 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
427 const int argc = this->target()->arguments_count(); | 427 const int argc = this->target()->arguments_count(); |
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 |
Martin Maly
2011/02/17 05:25:55
Since the logic now includes checking the function
| |
438 void CallICBase::ReceiverToObject(Handle<Object> object) { | 438 void CallICBase::ReceiverToObjectIfRequired(Object* callee, |
439 HandleScope scope; | 439 Handle<Object> object) { |
440 Handle<Object> receiver(object); | 440 if (callee->IsJSFunction()) { |
441 JSFunction* function = JSFunction::cast(callee); | |
442 if (function->shared()->strict_mode() || | |
443 function->IsBuiltin()) { | |
444 // Do not wrap receiver for strict mode functions or for builtins. | |
445 return; | |
446 } | |
447 } | |
441 | 448 |
442 // Change the receiver to the result of calling ToObject on it. | 449 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { |
443 const int argc = this->target()->arguments_count(); | 450 // And only wrap string, number or boolean. |
444 StackFrameLocator locator; | 451 HandleScope scope; |
445 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 452 Handle<Object> receiver(object); |
446 int index = frame->ComputeExpressionsCount() - (argc + 1); | 453 |
447 frame->SetExpression(index, *Factory::ToObject(object)); | 454 // Change the receiver to the result of calling ToObject on it. |
455 const int argc = this->target()->arguments_count(); | |
456 StackFrameLocator locator; | |
457 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | |
458 int index = frame->ComputeExpressionsCount() - (argc + 1); | |
459 frame->SetExpression(index, *Factory::ToObject(object)); | |
460 } | |
448 } | 461 } |
449 | 462 |
450 | 463 |
451 MaybeObject* CallICBase::LoadFunction(State state, | 464 MaybeObject* CallICBase::LoadFunction(State state, |
452 Code::ExtraICState extra_ic_state, | 465 Code::ExtraICState extra_ic_state, |
453 Handle<Object> object, | 466 Handle<Object> object, |
454 Handle<String> name) { | 467 Handle<String> name) { |
455 // If the object is undefined or null it's illegal to try to get any | 468 // 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. | 469 // of its properties; throw a TypeError in that case. |
457 if (object->IsUndefined() || object->IsNull()) { | 470 if (object->IsUndefined() || object->IsNull()) { |
458 return TypeError("non_object_property_call", object, name); | 471 return TypeError("non_object_property_call", object, name); |
459 } | 472 } |
460 | 473 |
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 | 474 // Check if the name is trivially convertible to an index and get |
466 // the element if so. | 475 // the element if so. |
467 uint32_t index; | 476 uint32_t index; |
468 if (name->AsArrayIndex(&index)) { | 477 if (name->AsArrayIndex(&index)) { |
469 Object* result; | 478 Object* result; |
470 { MaybeObject* maybe_result = object->GetElement(index); | 479 { MaybeObject* maybe_result = object->GetElement(index); |
471 if (!maybe_result->ToObject(&result)) return maybe_result; | 480 if (!maybe_result->ToObject(&result)) return maybe_result; |
472 } | 481 } |
473 | 482 |
474 if (result->IsJSFunction()) return result; | 483 if (result->IsJSFunction()) return result; |
(...skipping 23 matching lines...) Expand all Loading... | |
498 UpdateCaches(&lookup, state, extra_ic_state, object, name); | 507 UpdateCaches(&lookup, state, extra_ic_state, object, name); |
499 } | 508 } |
500 | 509 |
501 // Get the property. | 510 // Get the property. |
502 PropertyAttributes attr; | 511 PropertyAttributes attr; |
503 Object* result; | 512 Object* result; |
504 { MaybeObject* maybe_result = | 513 { MaybeObject* maybe_result = |
505 object->GetProperty(*object, &lookup, *name, &attr); | 514 object->GetProperty(*object, &lookup, *name, &attr); |
506 if (!maybe_result->ToObject(&result)) return maybe_result; | 515 if (!maybe_result->ToObject(&result)) return maybe_result; |
507 } | 516 } |
517 | |
518 // Make receiver an object if the callee requires it. Strict mode or builtin | |
519 // functions do not wrap the receiver, non-strict functions do. | |
520 ReceiverToObjectIfRequired(result, object); | |
521 | |
508 if (lookup.type() == INTERCEPTOR) { | 522 if (lookup.type() == INTERCEPTOR) { |
509 // If the object does not have the requested property, check which | 523 // If the object does not have the requested property, check which |
510 // exception we need to throw. | 524 // exception we need to throw. |
511 if (attr == ABSENT) { | 525 if (attr == ABSENT) { |
512 if (IsContextual(object)) { | 526 if (IsContextual(object)) { |
513 return ReferenceError("not_defined", name); | 527 return ReferenceError("not_defined", name); |
514 } | 528 } |
515 return TypeError("undefined_method", object, name); | 529 return TypeError("undefined_method", object, name); |
516 } | 530 } |
517 } | 531 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
558 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); | 572 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); |
559 Arguments args(argc + 1, | 573 Arguments args(argc + 1, |
560 &Memory::Object_at(fp + | 574 &Memory::Object_at(fp + |
561 StandardFrameConstants::kCallerSPOffset + | 575 StandardFrameConstants::kCallerSPOffset + |
562 argc * kPointerSize)); | 576 argc * kPointerSize)); |
563 switch (function->shared()->builtin_function_id()) { | 577 switch (function->shared()->builtin_function_id()) { |
564 case kStringCharCodeAt: | 578 case kStringCharCodeAt: |
565 case kStringCharAt: | 579 case kStringCharAt: |
566 if (object->IsString()) { | 580 if (object->IsString()) { |
567 String* string = String::cast(*object); | 581 String* string = String::cast(*object); |
568 // Check that there's the right wrapper in the receiver slot. | 582 // Check there's the right string value or wrapper in the receiver slot. |
Martin Maly
2011/02/17 05:25:55
Good catch, Vitaly, this assert did trigger in deb
| |
569 ASSERT(string == JSValue::cast(args[0])->value()); | 583 ASSERT(string == args[0] || string == JSValue::cast(args[0])->value()); |
570 // If we're in the default (fastest) state and the index is | 584 // If we're in the default (fastest) state and the index is |
571 // out of bounds, update the state to record this fact. | 585 // out of bounds, update the state to record this fact. |
572 if (*extra_ic_state == DEFAULT_STRING_STUB && | 586 if (*extra_ic_state == DEFAULT_STRING_STUB && |
573 argc >= 1 && args[1]->IsNumber()) { | 587 argc >= 1 && args[1]->IsNumber()) { |
574 double index; | 588 double index; |
575 if (args[1]->IsSmi()) { | 589 if (args[1]->IsSmi()) { |
576 index = Smi::cast(args[1])->value(); | 590 index = Smi::cast(args[1])->value(); |
577 } else { | 591 } else { |
578 ASSERT(args[1]->IsHeapNumber()); | 592 ASSERT(args[1]->IsHeapNumber()); |
579 index = DoubleToInteger(HeapNumber::cast(args[1])->value()); | 593 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, | 782 return CallICBase::LoadFunction(state, |
769 Code::kNoExtraICState, | 783 Code::kNoExtraICState, |
770 object, | 784 object, |
771 Handle<String>::cast(key)); | 785 Handle<String>::cast(key)); |
772 } | 786 } |
773 | 787 |
774 if (object->IsUndefined() || object->IsNull()) { | 788 if (object->IsUndefined() || object->IsNull()) { |
775 return TypeError("non_object_property_call", object, key); | 789 return TypeError("non_object_property_call", object, key); |
776 } | 790 } |
777 | 791 |
778 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { | |
779 ReceiverToObject(object); | |
780 } | |
781 | |
782 if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) { | 792 if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) { |
783 int argc = target()->arguments_count(); | 793 int argc = target()->arguments_count(); |
784 InLoopFlag in_loop = target()->ic_in_loop(); | 794 InLoopFlag in_loop = target()->ic_in_loop(); |
785 MaybeObject* maybe_code = StubCache::ComputeCallMegamorphic( | 795 MaybeObject* maybe_code = StubCache::ComputeCallMegamorphic( |
786 argc, in_loop, Code::KEYED_CALL_IC); | 796 argc, in_loop, Code::KEYED_CALL_IC); |
787 Object* code; | 797 Object* code; |
788 if (maybe_code->ToObject(&code)) { | 798 if (maybe_code->ToObject(&code)) { |
789 set_target(Code::cast(code)); | 799 set_target(Code::cast(code)); |
790 #ifdef DEBUG | 800 #ifdef DEBUG |
791 TraceIC( | 801 TraceIC( |
792 "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : ""); | 802 "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : ""); |
793 #endif | 803 #endif |
794 } | 804 } |
795 } | 805 } |
806 | |
796 Object* result; | 807 Object* result; |
797 { MaybeObject* maybe_result = Runtime::GetObjectProperty(object, key); | 808 { MaybeObject* maybe_result = Runtime::GetObjectProperty(object, key); |
798 if (!maybe_result->ToObject(&result)) return maybe_result; | 809 if (!maybe_result->ToObject(&result)) return maybe_result; |
799 } | 810 } |
811 | |
812 // Make receiver an object if the callee requires it. Strict mode or builtin | |
813 // functions do not wrap the receiver, non-strict functions do. | |
814 ReceiverToObjectIfRequired(result, object); | |
815 | |
800 if (result->IsJSFunction()) return result; | 816 if (result->IsJSFunction()) return result; |
801 result = TryCallAsFunction(result); | 817 result = TryCallAsFunction(result); |
802 MaybeObject* answer = result; | 818 MaybeObject* answer = result; |
803 if (!result->IsJSFunction()) { | 819 if (!result->IsJSFunction()) { |
804 answer = TypeError("property_not_function", object, key); | 820 answer = TypeError("property_not_function", object, key); |
805 } | 821 } |
806 return answer; | 822 return answer; |
807 } | 823 } |
808 | 824 |
809 | 825 |
(...skipping 1476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2286 #undef ADDR | 2302 #undef ADDR |
2287 }; | 2303 }; |
2288 | 2304 |
2289 | 2305 |
2290 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2306 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2291 return IC_utilities[id]; | 2307 return IC_utilities[id]; |
2292 } | 2308 } |
2293 | 2309 |
2294 | 2310 |
2295 } } // namespace v8::internal | 2311 } } // namespace v8::internal |
OLD | NEW |