OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 2033 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2044 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); | 2044 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); |
2045 __ CallStub(&stub); | 2045 __ CallStub(&stub); |
2046 RecordJSReturnSite(expr); | 2046 RecordJSReturnSite(expr); |
2047 // Restore context register. | 2047 // Restore context register. |
2048 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2048 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
2049 // Discard the function left on TOS. | 2049 // Discard the function left on TOS. |
2050 context()->DropAndPlug(1, rax); | 2050 context()->DropAndPlug(1, rax); |
2051 } | 2051 } |
2052 | 2052 |
2053 | 2053 |
| 2054 void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, |
| 2055 int arg_count) { |
| 2056 // Push copy of the first argument or undefined if it doesn't exist. |
| 2057 if (arg_count > 0) { |
| 2058 __ push(Operand(rsp, arg_count * kPointerSize)); |
| 2059 } else { |
| 2060 __ PushRoot(Heap::kUndefinedValueRootIndex); |
| 2061 } |
| 2062 |
| 2063 // Push the receiver of the enclosing function and do runtime call. |
| 2064 __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize)); |
| 2065 |
| 2066 // Push the strict mode flag. |
| 2067 __ Push(Smi::FromInt(strict_mode_flag())); |
| 2068 |
| 2069 __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP |
| 2070 ? Runtime::kResolvePossiblyDirectEvalNoLookup |
| 2071 : Runtime::kResolvePossiblyDirectEval, 4); |
| 2072 } |
| 2073 |
| 2074 |
2054 void FullCodeGenerator::VisitCall(Call* expr) { | 2075 void FullCodeGenerator::VisitCall(Call* expr) { |
2055 #ifdef DEBUG | 2076 #ifdef DEBUG |
2056 // We want to verify that RecordJSReturnSite gets called on all paths | 2077 // We want to verify that RecordJSReturnSite gets called on all paths |
2057 // through this function. Avoid early returns. | 2078 // through this function. Avoid early returns. |
2058 expr->return_is_recorded_ = false; | 2079 expr->return_is_recorded_ = false; |
2059 #endif | 2080 #endif |
2060 | 2081 |
2061 Comment cmnt(masm_, "[ Call"); | 2082 Comment cmnt(masm_, "[ Call"); |
2062 Expression* fun = expr->expression(); | 2083 Expression* fun = expr->expression(); |
2063 Variable* var = fun->AsVariableProxy()->AsVariable(); | 2084 Variable* var = fun->AsVariableProxy()->AsVariable(); |
2064 | 2085 |
2065 if (var != NULL && var->is_possibly_eval()) { | 2086 if (var != NULL && var->is_possibly_eval()) { |
2066 // In a call to eval, we first call %ResolvePossiblyDirectEval to | 2087 // In a call to eval, we first call %ResolvePossiblyDirectEval to |
2067 // resolve the function we need to call and the receiver of the | 2088 // resolve the function we need to call and the receiver of the |
2068 // call. Then we call the resolved function using the given | 2089 // call. Then we call the resolved function using the given |
2069 // arguments. | 2090 // arguments. |
2070 ZoneList<Expression*>* args = expr->arguments(); | 2091 ZoneList<Expression*>* args = expr->arguments(); |
2071 int arg_count = args->length(); | 2092 int arg_count = args->length(); |
2072 { PreservePositionScope pos_scope(masm()->positions_recorder()); | 2093 { PreservePositionScope pos_scope(masm()->positions_recorder()); |
2073 VisitForStackValue(fun); | 2094 VisitForStackValue(fun); |
2074 __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot. | 2095 __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot. |
2075 | 2096 |
2076 // Push the arguments. | 2097 // Push the arguments. |
2077 for (int i = 0; i < arg_count; i++) { | 2098 for (int i = 0; i < arg_count; i++) { |
2078 VisitForStackValue(args->at(i)); | 2099 VisitForStackValue(args->at(i)); |
2079 } | 2100 } |
2080 | 2101 |
2081 // Push copy of the function - found below the arguments. | 2102 // If we know that eval can only be shadowed by eval-introduced |
2082 __ push(Operand(rsp, (arg_count + 1) * kPointerSize)); | 2103 // variables we attempt to load the global eval function directly |
2083 | 2104 // in generated code. If we succeed, there is no need to perform a |
2084 // Push copy of the first argument or undefined if it doesn't exist. | 2105 // context lookup in the runtime system. |
2085 if (arg_count > 0) { | 2106 Label done; |
2086 __ push(Operand(rsp, arg_count * kPointerSize)); | 2107 if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) { |
2087 } else { | 2108 Label slow; |
2088 __ PushRoot(Heap::kUndefinedValueRootIndex); | 2109 EmitLoadGlobalSlotCheckExtensions(var->AsSlot(), |
| 2110 NOT_INSIDE_TYPEOF, |
| 2111 &slow); |
| 2112 // Push the function and resolve eval. |
| 2113 __ push(rax); |
| 2114 EmitResolvePossiblyDirectEval(SKIP_CONTEXT_LOOKUP, arg_count); |
| 2115 __ jmp(&done); |
| 2116 __ bind(&slow); |
2089 } | 2117 } |
2090 | 2118 |
2091 // Push the receiver of the enclosing function and do runtime call. | 2119 // Push copy of the function (found below the arguments) and |
2092 __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize)); | 2120 // resolve eval. |
2093 // Push the strict mode flag. | 2121 __ push(Operand(rsp, (arg_count + 1) * kPointerSize)); |
2094 __ Push(Smi::FromInt(strict_mode_flag())); | 2122 EmitResolvePossiblyDirectEval(PERFORM_CONTEXT_LOOKUP, arg_count); |
2095 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4); | 2123 if (done.is_linked()) { |
| 2124 __ bind(&done); |
| 2125 } |
2096 | 2126 |
2097 // The runtime call returns a pair of values in rax (function) and | 2127 // The runtime call returns a pair of values in rax (function) and |
2098 // rdx (receiver). Touch up the stack with the right values. | 2128 // rdx (receiver). Touch up the stack with the right values. |
2099 __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx); | 2129 __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx); |
2100 __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax); | 2130 __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax); |
2101 } | 2131 } |
2102 // Record source position for debugger. | 2132 // Record source position for debugger. |
2103 SetSourcePosition(expr->position()); | 2133 SetSourcePosition(expr->position()); |
2104 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2134 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
2105 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); | 2135 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); |
(...skipping 1773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3879 __ ret(0); | 3909 __ ret(0); |
3880 } | 3910 } |
3881 | 3911 |
3882 | 3912 |
3883 #undef __ | 3913 #undef __ |
3884 | 3914 |
3885 | 3915 |
3886 } } // namespace v8::internal | 3916 } } // namespace v8::internal |
3887 | 3917 |
3888 #endif // V8_TARGET_ARCH_X64 | 3918 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |