Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(253)

Side by Side Diff: src/ic.cc

Issue 6523052: CallIC and KeyedCallIC not wrapping this. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Last touches. Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | src/x64/stub-cache-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/x64/stub-cache-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698