Chromium Code Reviews| 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(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() || 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 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { |
| 443 const int argc = this->target()->arguments_count(); | 449 // And only wrap string, number or boolean. |
| 444 StackFrameLocator locator; | 450 HandleScope scope; |
| 445 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 451 Handle<Object> receiver(object); |
| 446 int index = frame->ComputeExpressionsCount() - (argc + 1); | 452 |
| 447 frame->SetExpression(index, *Factory::ToObject(object)); | 453 // Change the receiver to the result of calling ToObject on it. |
| 454 const int argc = this->target()->arguments_count(); | |
| 455 StackFrameLocator locator; | |
| 456 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | |
| 457 int index = frame->ComputeExpressionsCount() - (argc + 1); | |
| 458 frame->SetExpression(index, *Factory::ToObject(object)); | |
| 459 } | |
| 448 } | 460 } |
| 449 | 461 |
| 450 | 462 |
| 451 MaybeObject* CallICBase::LoadFunction(State state, | 463 MaybeObject* CallICBase::LoadFunction(State state, |
| 452 Code::ExtraICState extra_ic_state, | 464 Code::ExtraICState extra_ic_state, |
| 453 Handle<Object> object, | 465 Handle<Object> object, |
| 454 Handle<String> name) { | 466 Handle<String> name) { |
| 455 // If the object is undefined or null it's illegal to try to get any | 467 // 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. | 468 // of its properties; throw a TypeError in that case. |
| 457 if (object->IsUndefined() || object->IsNull()) { | 469 if (object->IsUndefined() || object->IsNull()) { |
| 458 return TypeError("non_object_property_call", object, name); | 470 return TypeError("non_object_property_call", object, name); |
| 459 } | 471 } |
| 460 | 472 |
| 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 | 473 // Check if the name is trivially convertible to an index and get |
| 466 // the element if so. | 474 // the element if so. |
| 467 uint32_t index; | 475 uint32_t index; |
| 468 if (name->AsArrayIndex(&index)) { | 476 if (name->AsArrayIndex(&index)) { |
| 469 Object* result; | 477 Object* result; |
| 470 { MaybeObject* maybe_result = object->GetElement(index); | 478 { MaybeObject* maybe_result = object->GetElement(index); |
| 471 if (!maybe_result->ToObject(&result)) return maybe_result; | 479 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 472 } | 480 } |
| 473 | 481 |
| 474 if (result->IsJSFunction()) return result; | 482 if (result->IsJSFunction()) return result; |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 498 UpdateCaches(&lookup, state, extra_ic_state, object, name); | 506 UpdateCaches(&lookup, state, extra_ic_state, object, name); |
| 499 } | 507 } |
| 500 | 508 |
| 501 // Get the property. | 509 // Get the property. |
| 502 PropertyAttributes attr; | 510 PropertyAttributes attr; |
| 503 Object* result; | 511 Object* result; |
| 504 { MaybeObject* maybe_result = | 512 { MaybeObject* maybe_result = |
| 505 object->GetProperty(*object, &lookup, *name, &attr); | 513 object->GetProperty(*object, &lookup, *name, &attr); |
| 506 if (!maybe_result->ToObject(&result)) return maybe_result; | 514 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 507 } | 515 } |
| 516 | |
| 517 // Make receiver an object if the callee requires it. Strict mode or builtin | |
| 518 // functions do not wrap the receiver, non-strict functions and objects | |
| 519 // called as 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. |
| 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 and objects | |
| 814 // called as functions do. | |
| 815 ReceiverToObjectIfRequired(result, object); | |
|
Mads Ager (chromium)
2011/02/17 21:57:01
I should have caught this earlier: result is a raw
| |
| 816 | |
| 800 if (result->IsJSFunction()) return result; | 817 if (result->IsJSFunction()) return result; |
| 801 result = TryCallAsFunction(result); | 818 result = TryCallAsFunction(result); |
| 802 MaybeObject* answer = result; | 819 MaybeObject* answer = result; |
| 803 if (!result->IsJSFunction()) { | 820 if (!result->IsJSFunction()) { |
| 804 answer = TypeError("property_not_function", object, key); | 821 answer = TypeError("property_not_function", object, key); |
| 805 } | 822 } |
| 806 return answer; | 823 return answer; |
| 807 } | 824 } |
| 808 | 825 |
| 809 | 826 |
| (...skipping 1476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2286 #undef ADDR | 2303 #undef ADDR |
| 2287 }; | 2304 }; |
| 2288 | 2305 |
| 2289 | 2306 |
| 2290 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2307 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2291 return IC_utilities[id]; | 2308 return IC_utilities[id]; |
| 2292 } | 2309 } |
| 2293 | 2310 |
| 2294 | 2311 |
| 2295 } } // namespace v8::internal | 2312 } } // namespace v8::internal |
| OLD | NEW |