| OLD | NEW | 
|---|
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 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 2686 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2697 | 2697 | 
| 2698   // ------------------------------------------------------------------------ | 2698   // ------------------------------------------------------------------------ | 
| 2699   // Fast-case: Use inline caching. | 2699   // Fast-case: Use inline caching. | 
| 2700   // --- | 2700   // --- | 
| 2701   // According to ECMA-262, section 11.2.3, page 44, the function to call | 2701   // According to ECMA-262, section 11.2.3, page 44, the function to call | 
| 2702   // must be resolved after the arguments have been evaluated. The IC code | 2702   // must be resolved after the arguments have been evaluated. The IC code | 
| 2703   // automatically handles this by loading the arguments before the function | 2703   // automatically handles this by loading the arguments before the function | 
| 2704   // is resolved in cache misses (this also holds for megamorphic calls). | 2704   // is resolved in cache misses (this also holds for megamorphic calls). | 
| 2705   // ------------------------------------------------------------------------ | 2705   // ------------------------------------------------------------------------ | 
| 2706 | 2706 | 
| 2707   if (var != NULL && !var->is_this() && var->is_global()) { | 2707   if (var != NULL && var->is_possibly_eval()) { | 
|  | 2708     // ---------------------------------- | 
|  | 2709     // JavaScript example: 'eval(arg)'  // eval is not known to be shadowed | 
|  | 2710     // ---------------------------------- | 
|  | 2711 | 
|  | 2712     // In a call to eval, we first call %ResolvePossiblyDirectEval to | 
|  | 2713     // resolve the function we need to call and the receiver of the | 
|  | 2714     // call.  Then we call the resolved function using the given | 
|  | 2715     // arguments. | 
|  | 2716 | 
|  | 2717     // Prepare the stack for the call to the resolved function. | 
|  | 2718     Load(function); | 
|  | 2719 | 
|  | 2720     // Allocate a frame slot for the receiver. | 
|  | 2721     frame_->Push(Factory::undefined_value()); | 
|  | 2722     int arg_count = args->length(); | 
|  | 2723     for (int i = 0; i < arg_count; i++) { | 
|  | 2724       Load(args->at(i)); | 
|  | 2725     } | 
|  | 2726 | 
|  | 2727     // Prepare the stack for the call to ResolvePossiblyDirectEval. | 
|  | 2728     frame_->PushElementAt(arg_count + 1); | 
|  | 2729     if (arg_count > 0) { | 
|  | 2730       frame_->PushElementAt(arg_count); | 
|  | 2731     } else { | 
|  | 2732       frame_->Push(Factory::undefined_value()); | 
|  | 2733     } | 
|  | 2734 | 
|  | 2735     // Resolve the call. | 
|  | 2736     Result result = | 
|  | 2737         frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 2); | 
|  | 2738 | 
|  | 2739     // Touch up the stack with the right values for the function and the | 
|  | 2740     // receiver.  Use a scratch register to avoid destroying the result. | 
|  | 2741     Result scratch = allocator_->Allocate(); | 
|  | 2742     ASSERT(scratch.is_valid()); | 
|  | 2743     __ movq(scratch.reg(), | 
|  | 2744             FieldOperand(result.reg(), FixedArray::OffsetOfElementAt(0))); | 
|  | 2745     frame_->SetElementAt(arg_count + 1, &scratch); | 
|  | 2746 | 
|  | 2747     // We can reuse the result register now. | 
|  | 2748     frame_->Spill(result.reg()); | 
|  | 2749     __ movq(result.reg(), | 
|  | 2750             FieldOperand(result.reg(), FixedArray::OffsetOfElementAt(1))); | 
|  | 2751     frame_->SetElementAt(arg_count, &result); | 
|  | 2752 | 
|  | 2753     // Call the function. | 
|  | 2754     CodeForSourcePosition(node->position()); | 
|  | 2755     InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | 
|  | 2756     CallFunctionStub call_function(arg_count, in_loop); | 
|  | 2757     result = frame_->CallStub(&call_function, arg_count + 1); | 
|  | 2758 | 
|  | 2759     // Restore the context and overwrite the function on the stack with | 
|  | 2760     // the result. | 
|  | 2761     frame_->RestoreContextRegister(); | 
|  | 2762     frame_->SetElementAt(0, &result); | 
|  | 2763 | 
|  | 2764   } else if (var != NULL && !var->is_this() && var->is_global()) { | 
| 2708     // ---------------------------------- | 2765     // ---------------------------------- | 
| 2709     // JavaScript example: 'foo(1, 2, 3)'  // foo is global | 2766     // JavaScript example: 'foo(1, 2, 3)'  // foo is global | 
| 2710     // ---------------------------------- | 2767     // ---------------------------------- | 
| 2711 | 2768 | 
| 2712     // Push the name of the function and the receiver onto the stack. | 2769     // Push the name of the function and the receiver onto the stack. | 
| 2713     frame_->Push(var->name()); | 2770     frame_->Push(var->name()); | 
| 2714 | 2771 | 
| 2715     // Pass the global object as the receiver and let the IC stub | 2772     // Pass the global object as the receiver and let the IC stub | 
| 2716     // patch the stack to use the global proxy as 'this' in the | 2773     // patch the stack to use the global proxy as 'this' in the | 
| 2717     // invoked function. | 2774     // invoked function. | 
| 2718     LoadGlobal(); | 2775     LoadGlobal(); | 
| 2719 | 2776 | 
| 2720     // Load the arguments. | 2777     // Load the arguments. | 
| 2721     int arg_count = args->length(); | 2778     int arg_count = args->length(); | 
| 2722     for (int i = 0; i < arg_count; i++) { | 2779     for (int i = 0; i < arg_count; i++) { | 
| 2723       Load(args->at(i)); | 2780       Load(args->at(i)); | 
| 2724     } | 2781     } | 
| 2725 | 2782 | 
| 2726     // Call the IC initialization code. | 2783     // Call the IC initialization code. | 
| 2727     CodeForSourcePosition(node->position()); | 2784     CodeForSourcePosition(node->position()); | 
| 2728     Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT, | 2785     Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT, | 
| 2729                                        arg_count, | 2786                                        arg_count, | 
| 2730                                        loop_nesting()); | 2787                                        loop_nesting()); | 
| 2731     frame_->RestoreContextRegister(); | 2788     frame_->RestoreContextRegister(); | 
| 2732     // Replace the function on the stack with the result. | 2789     // Replace the function on the stack with the result. | 
| 2733     frame_->SetElementAt(0, &result); | 2790     frame_->SetElementAt(0, &result); | 
|  | 2791 | 
| 2734   } else if (var != NULL && var->slot() != NULL && | 2792   } else if (var != NULL && var->slot() != NULL && | 
| 2735              var->slot()->type() == Slot::LOOKUP) { | 2793              var->slot()->type() == Slot::LOOKUP) { | 
| 2736     // ---------------------------------- | 2794     // ---------------------------------- | 
| 2737     // JavaScript example: 'with (obj) foo(1, 2, 3)'  // foo is in obj | 2795     // JavaScript example: 'with (obj) foo(1, 2, 3)'  // foo is in obj | 
| 2738     // ---------------------------------- | 2796     // ---------------------------------- | 
| 2739 | 2797 | 
| 2740     // Load the function from the context.  Sync the frame so we can | 2798     // Load the function from the context.  Sync the frame so we can | 
| 2741     // push the arguments directly into place. | 2799     // push the arguments directly into place. | 
| 2742     frame_->SyncRange(0, frame_->element_count() - 1); | 2800     frame_->SyncRange(0, frame_->element_count() - 1); | 
| 2743     frame_->EmitPush(rsi); | 2801     frame_->EmitPush(rsi); | 
| 2744     frame_->EmitPush(var->name()); | 2802     frame_->EmitPush(var->name()); | 
| 2745     frame_->CallRuntime(Runtime::kLoadContextSlot, 2); | 2803     frame_->CallRuntime(Runtime::kLoadContextSlot, 2); | 
| 2746     // The runtime call returns a pair of values in rax and rdx.  The | 2804     // The runtime call returns a pair of values in rax and rdx.  The | 
| 2747     // looked-up function is in rax and the receiver is in rdx.  These | 2805     // looked-up function is in rax and the receiver is in rdx.  These | 
| 2748     // register references are not ref counted here.  We spill them | 2806     // register references are not ref counted here.  We spill them | 
| 2749     // eagerly since they are arguments to an inevitable call (and are | 2807     // eagerly since they are arguments to an inevitable call (and are | 
| 2750     // not sharable by the arguments). | 2808     // not sharable by the arguments). | 
| 2751     ASSERT(!allocator()->is_used(rax)); | 2809     ASSERT(!allocator()->is_used(rax)); | 
| 2752     frame_->EmitPush(rax); | 2810     frame_->EmitPush(rax); | 
| 2753 | 2811 | 
| 2754     // Load the receiver. | 2812     // Load the receiver. | 
| 2755     ASSERT(!allocator()->is_used(rdx)); | 2813     ASSERT(!allocator()->is_used(rdx)); | 
| 2756     frame_->EmitPush(rdx); | 2814     frame_->EmitPush(rdx); | 
| 2757 | 2815 | 
| 2758     // Call the function. | 2816     // Call the function. | 
| 2759     CallWithArguments(args, node->position()); | 2817     CallWithArguments(args, node->position()); | 
|  | 2818 | 
| 2760   } else if (property != NULL) { | 2819   } else if (property != NULL) { | 
| 2761     // Check if the key is a literal string. | 2820     // Check if the key is a literal string. | 
| 2762     Literal* literal = property->key()->AsLiteral(); | 2821     Literal* literal = property->key()->AsLiteral(); | 
| 2763 | 2822 | 
| 2764     if (literal != NULL && literal->handle()->IsSymbol()) { | 2823     if (literal != NULL && literal->handle()->IsSymbol()) { | 
| 2765       // ------------------------------------------------------------------ | 2824       // ------------------------------------------------------------------ | 
| 2766       // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' | 2825       // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' | 
| 2767       // ------------------------------------------------------------------ | 2826       // ------------------------------------------------------------------ | 
| 2768 | 2827 | 
| 2769       Handle<String> name = Handle<String>::cast(literal->handle()); | 2828       Handle<String> name = Handle<String>::cast(literal->handle()); | 
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2815         // Use global object as receiver. | 2874         // Use global object as receiver. | 
| 2816         LoadGlobalReceiver(); | 2875         LoadGlobalReceiver(); | 
| 2817       } else { | 2876       } else { | 
| 2818         // The reference's size is non-negative. | 2877         // The reference's size is non-negative. | 
| 2819         frame_->PushElementAt(ref.size()); | 2878         frame_->PushElementAt(ref.size()); | 
| 2820       } | 2879       } | 
| 2821 | 2880 | 
| 2822       // Call the function. | 2881       // Call the function. | 
| 2823       CallWithArguments(args, node->position()); | 2882       CallWithArguments(args, node->position()); | 
| 2824     } | 2883     } | 
|  | 2884 | 
| 2825   } else { | 2885   } else { | 
| 2826     // ---------------------------------- | 2886     // ---------------------------------- | 
| 2827     // JavaScript example: 'foo(1, 2, 3)'  // foo is not global | 2887     // JavaScript example: 'foo(1, 2, 3)'  // foo is not global | 
| 2828     // ---------------------------------- | 2888     // ---------------------------------- | 
| 2829 | 2889 | 
| 2830     // Load the function. | 2890     // Load the function. | 
| 2831     Load(function); | 2891     Load(function); | 
| 2832 | 2892 | 
| 2833     // Pass the global proxy as the receiver. | 2893     // Pass the global proxy as the receiver. | 
| 2834     LoadGlobalReceiver(); | 2894     LoadGlobalReceiver(); | 
| 2835 | 2895 | 
| 2836     // Call the function. | 2896     // Call the function. | 
| 2837     CallWithArguments(args, node->position()); | 2897     CallWithArguments(args, node->position()); | 
| 2838   } | 2898   } | 
| 2839 } | 2899 } | 
| 2840 | 2900 | 
| 2841 | 2901 | 
| 2842 void CodeGenerator::VisitCallEval(CallEval* node) { |  | 
| 2843   Comment cmnt(masm_, "[ CallEval"); |  | 
| 2844 |  | 
| 2845   // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve |  | 
| 2846   // the function we need to call and the receiver of the call. |  | 
| 2847   // Then we call the resolved function using the given arguments. |  | 
| 2848 |  | 
| 2849   ZoneList<Expression*>* args = node->arguments(); |  | 
| 2850   Expression* function = node->expression(); |  | 
| 2851 |  | 
| 2852   // Prepare the stack for the call to the resolved function. |  | 
| 2853   Load(function); |  | 
| 2854 |  | 
| 2855   // Allocate a frame slot for the receiver. |  | 
| 2856   frame_->Push(Factory::undefined_value()); |  | 
| 2857   int arg_count = args->length(); |  | 
| 2858   for (int i = 0; i < arg_count; i++) { |  | 
| 2859     Load(args->at(i)); |  | 
| 2860   } |  | 
| 2861 |  | 
| 2862   // Prepare the stack for the call to ResolvePossiblyDirectEval. |  | 
| 2863   frame_->PushElementAt(arg_count + 1); |  | 
| 2864   if (arg_count > 0) { |  | 
| 2865     frame_->PushElementAt(arg_count); |  | 
| 2866   } else { |  | 
| 2867     frame_->Push(Factory::undefined_value()); |  | 
| 2868   } |  | 
| 2869 |  | 
| 2870   // Resolve the call. |  | 
| 2871   Result result = |  | 
| 2872       frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 2); |  | 
| 2873 |  | 
| 2874   // Touch up the stack with the right values for the function and the |  | 
| 2875   // receiver.  Use a scratch register to avoid destroying the result. |  | 
| 2876   Result scratch = allocator_->Allocate(); |  | 
| 2877   ASSERT(scratch.is_valid()); |  | 
| 2878   __ movq(scratch.reg(), |  | 
| 2879           FieldOperand(result.reg(), FixedArray::OffsetOfElementAt(0))); |  | 
| 2880   frame_->SetElementAt(arg_count + 1, &scratch); |  | 
| 2881 |  | 
| 2882   // We can reuse the result register now. |  | 
| 2883   frame_->Spill(result.reg()); |  | 
| 2884   __ movq(result.reg(), |  | 
| 2885           FieldOperand(result.reg(), FixedArray::OffsetOfElementAt(1))); |  | 
| 2886   frame_->SetElementAt(arg_count, &result); |  | 
| 2887 |  | 
| 2888   // Call the function. |  | 
| 2889   CodeForSourcePosition(node->position()); |  | 
| 2890   InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |  | 
| 2891   CallFunctionStub call_function(arg_count, in_loop); |  | 
| 2892   result = frame_->CallStub(&call_function, arg_count + 1); |  | 
| 2893 |  | 
| 2894   // Restore the context and overwrite the function on the stack with |  | 
| 2895   // the result. |  | 
| 2896   frame_->RestoreContextRegister(); |  | 
| 2897   frame_->SetElementAt(0, &result); |  | 
| 2898 } |  | 
| 2899 |  | 
| 2900 |  | 
| 2901 void CodeGenerator::VisitCallNew(CallNew* node) { | 2902 void CodeGenerator::VisitCallNew(CallNew* node) { | 
| 2902   Comment cmnt(masm_, "[ CallNew"); | 2903   Comment cmnt(masm_, "[ CallNew"); | 
| 2903 | 2904 | 
| 2904   // According to ECMA-262, section 11.2.2, page 44, the function | 2905   // According to ECMA-262, section 11.2.2, page 44, the function | 
| 2905   // expression in new calls must be evaluated before the | 2906   // expression in new calls must be evaluated before the | 
| 2906   // arguments. This is different from ordinary calls, where the | 2907   // arguments. This is different from ordinary calls, where the | 
| 2907   // actual function to call is resolved after the arguments have been | 2908   // actual function to call is resolved after the arguments have been | 
| 2908   // evaluated. | 2909   // evaluated. | 
| 2909 | 2910 | 
| 2910   // Compute function to call and use the global object as the | 2911   // Compute function to call and use the global object as the | 
| (...skipping 4763 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 7674 int CompareStub::MinorKey() { | 7675 int CompareStub::MinorKey() { | 
| 7675   // Encode the two parameters in a unique 16 bit value. | 7676   // Encode the two parameters in a unique 16 bit value. | 
| 7676   ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); | 7677   ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); | 
| 7677   return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); | 7678   return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); | 
| 7678 } | 7679 } | 
| 7679 | 7680 | 
| 7680 | 7681 | 
| 7681 #undef __ | 7682 #undef __ | 
| 7682 | 7683 | 
| 7683 } }  // namespace v8::internal | 7684 } }  // namespace v8::internal | 
| OLD | NEW | 
|---|