| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #if V8_TARGET_ARCH_S390 | 5 #if V8_TARGET_ARCH_S390 |
| 6 | 6 |
| 7 #include "src/full-codegen/full-codegen.h" | 7 #include "src/full-codegen/full-codegen.h" |
| 8 #include "src/ast/compile-time-value.h" | 8 #include "src/ast/compile-time-value.h" |
| 9 #include "src/ast/scopes.h" | 9 #include "src/ast/scopes.h" |
| 10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
| (...skipping 733 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 if (variable->binding_needs_init()) { | 744 if (variable->binding_needs_init()) { |
| 745 Comment cmnt(masm_, "[ VariableDeclaration"); | 745 Comment cmnt(masm_, "[ VariableDeclaration"); |
| 746 EmitDebugCheckDeclarationContext(variable); | 746 EmitDebugCheckDeclarationContext(variable); |
| 747 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 747 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 748 __ StoreP(ip, ContextMemOperand(cp, variable->index())); | 748 __ StoreP(ip, ContextMemOperand(cp, variable->index())); |
| 749 // No write barrier since the_hole_value is in old space. | 749 // No write barrier since the_hole_value is in old space. |
| 750 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | 750 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); |
| 751 } | 751 } |
| 752 break; | 752 break; |
| 753 | 753 |
| 754 case VariableLocation::LOOKUP: { | 754 case VariableLocation::LOOKUP: |
| 755 Comment cmnt(masm_, "[ VariableDeclaration"); | |
| 756 DCHECK_EQ(VAR, variable->mode()); | |
| 757 DCHECK(!variable->binding_needs_init()); | |
| 758 __ mov(r4, Operand(variable->name())); | |
| 759 __ Push(r4); | |
| 760 __ CallRuntime(Runtime::kDeclareEvalVar); | |
| 761 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | |
| 762 break; | |
| 763 } | |
| 764 | |
| 765 case VariableLocation::MODULE: | 755 case VariableLocation::MODULE: |
| 766 UNREACHABLE(); | 756 UNREACHABLE(); |
| 767 } | 757 } |
| 768 } | 758 } |
| 769 | 759 |
| 770 void FullCodeGenerator::VisitFunctionDeclaration( | 760 void FullCodeGenerator::VisitFunctionDeclaration( |
| 771 FunctionDeclaration* declaration) { | 761 FunctionDeclaration* declaration) { |
| 772 VariableProxy* proxy = declaration->proxy(); | 762 VariableProxy* proxy = declaration->proxy(); |
| 773 Variable* variable = proxy->var(); | 763 Variable* variable = proxy->var(); |
| 774 switch (variable->location()) { | 764 switch (variable->location()) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 800 __ StoreP(result_register(), ContextMemOperand(cp, variable->index())); | 790 __ StoreP(result_register(), ContextMemOperand(cp, variable->index())); |
| 801 int offset = Context::SlotOffset(variable->index()); | 791 int offset = Context::SlotOffset(variable->index()); |
| 802 // We know that we have written a function, which is not a smi. | 792 // We know that we have written a function, which is not a smi. |
| 803 __ RecordWriteContextSlot(cp, offset, result_register(), r4, | 793 __ RecordWriteContextSlot(cp, offset, result_register(), r4, |
| 804 kLRHasBeenSaved, kDontSaveFPRegs, | 794 kLRHasBeenSaved, kDontSaveFPRegs, |
| 805 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 795 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
| 806 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | 796 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); |
| 807 break; | 797 break; |
| 808 } | 798 } |
| 809 | 799 |
| 810 case VariableLocation::LOOKUP: { | 800 case VariableLocation::LOOKUP: |
| 811 Comment cmnt(masm_, "[ FunctionDeclaration"); | |
| 812 __ mov(r4, Operand(variable->name())); | |
| 813 PushOperand(r4); | |
| 814 // Push initial value for function declaration. | |
| 815 VisitForStackValue(declaration->fun()); | |
| 816 CallRuntimeWithOperands(Runtime::kDeclareEvalFunction); | |
| 817 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | |
| 818 break; | |
| 819 } | |
| 820 | |
| 821 case VariableLocation::MODULE: | 801 case VariableLocation::MODULE: |
| 822 UNREACHABLE(); | 802 UNREACHABLE(); |
| 823 } | 803 } |
| 824 } | 804 } |
| 825 | 805 |
| 826 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 806 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 827 // Call the runtime to declare the globals. | 807 // Call the runtime to declare the globals. |
| 828 __ mov(r3, Operand(pairs)); | 808 __ mov(r3, Operand(pairs)); |
| 829 __ LoadSmiLiteral(r2, Smi::FromInt(DeclareGlobalsFlags())); | 809 __ LoadSmiLiteral(r2, Smi::FromInt(DeclareGlobalsFlags())); |
| 830 __ EmitLoadTypeFeedbackVector(r4); | 810 __ EmitLoadTypeFeedbackVector(r4); |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1115 void FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer, | 1095 void FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer, |
| 1116 int offset, | 1096 int offset, |
| 1117 FeedbackVectorSlot slot) { | 1097 FeedbackVectorSlot slot) { |
| 1118 DCHECK(NeedsHomeObject(initializer)); | 1098 DCHECK(NeedsHomeObject(initializer)); |
| 1119 __ Move(StoreDescriptor::ReceiverRegister(), r2); | 1099 __ Move(StoreDescriptor::ReceiverRegister(), r2); |
| 1120 __ LoadP(StoreDescriptor::ValueRegister(), | 1100 __ LoadP(StoreDescriptor::ValueRegister(), |
| 1121 MemOperand(sp, offset * kPointerSize)); | 1101 MemOperand(sp, offset * kPointerSize)); |
| 1122 CallStoreIC(slot, isolate()->factory()->home_object_symbol()); | 1102 CallStoreIC(slot, isolate()->factory()->home_object_symbol()); |
| 1123 } | 1103 } |
| 1124 | 1104 |
| 1125 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, | |
| 1126 TypeofMode typeof_mode, | |
| 1127 Label* slow) { | |
| 1128 Register current = cp; | |
| 1129 Register next = r3; | |
| 1130 Register temp = r4; | |
| 1131 | |
| 1132 int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval(); | |
| 1133 for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) { | |
| 1134 if (!s->NeedsContext()) continue; | |
| 1135 if (s->calls_sloppy_eval()) { | |
| 1136 // Check that extension is "the hole". | |
| 1137 __ LoadP(temp, ContextMemOperand(current, Context::EXTENSION_INDEX)); | |
| 1138 __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow); | |
| 1139 } | |
| 1140 // Load next context in chain. | |
| 1141 __ LoadP(next, ContextMemOperand(current, Context::PREVIOUS_INDEX)); | |
| 1142 // Walk the rest of the chain without clobbering cp. | |
| 1143 current = next; | |
| 1144 to_check--; | |
| 1145 } | |
| 1146 | |
| 1147 // All extension objects were empty and it is safe to use a normal global | |
| 1148 // load machinery. | |
| 1149 EmitGlobalVariableLoad(proxy, typeof_mode); | |
| 1150 } | |
| 1151 | |
| 1152 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | |
| 1153 Label* slow) { | |
| 1154 DCHECK(var->IsContextSlot()); | |
| 1155 Register context = cp; | |
| 1156 Register next = r5; | |
| 1157 Register temp = r6; | |
| 1158 | |
| 1159 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | |
| 1160 if (s->NeedsContext()) { | |
| 1161 if (s->calls_sloppy_eval()) { | |
| 1162 // Check that extension is "the hole". | |
| 1163 __ LoadP(temp, ContextMemOperand(context, Context::EXTENSION_INDEX)); | |
| 1164 __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow); | |
| 1165 } | |
| 1166 __ LoadP(next, ContextMemOperand(context, Context::PREVIOUS_INDEX)); | |
| 1167 // Walk the rest of the chain without clobbering cp. | |
| 1168 context = next; | |
| 1169 } | |
| 1170 } | |
| 1171 // Check that last extension is "the hole". | |
| 1172 __ LoadP(temp, ContextMemOperand(context, Context::EXTENSION_INDEX)); | |
| 1173 __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow); | |
| 1174 | |
| 1175 // This function is used only for loads, not stores, so it's safe to | |
| 1176 // return an cp-based operand (the write barrier cannot be allowed to | |
| 1177 // destroy the cp register). | |
| 1178 return ContextMemOperand(context, var->index()); | |
| 1179 } | |
| 1180 | |
| 1181 void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy, | |
| 1182 TypeofMode typeof_mode, | |
| 1183 Label* slow, Label* done) { | |
| 1184 // Generate fast-case code for variables that might be shadowed by | |
| 1185 // eval-introduced variables. Eval is used a lot without | |
| 1186 // introducing variables. In those cases, we do not want to | |
| 1187 // perform a runtime call for all variables in the scope | |
| 1188 // containing the eval. | |
| 1189 Variable* var = proxy->var(); | |
| 1190 if (var->mode() == DYNAMIC_GLOBAL) { | |
| 1191 EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow); | |
| 1192 __ b(done); | |
| 1193 } else if (var->mode() == DYNAMIC_LOCAL) { | |
| 1194 Variable* local = var->local_if_not_shadowed(); | |
| 1195 __ LoadP(r2, ContextSlotOperandCheckExtensions(local, slow)); | |
| 1196 if (local->binding_needs_init()) { | |
| 1197 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); | |
| 1198 __ bne(done); | |
| 1199 __ mov(r2, Operand(var->name())); | |
| 1200 __ push(r2); | |
| 1201 __ CallRuntime(Runtime::kThrowReferenceError); | |
| 1202 } else { | |
| 1203 __ b(done); | |
| 1204 } | |
| 1205 } | |
| 1206 } | |
| 1207 | |
| 1208 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, | 1105 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, |
| 1209 TypeofMode typeof_mode) { | 1106 TypeofMode typeof_mode) { |
| 1210 // Record position before possible IC call. | 1107 // Record position before possible IC call. |
| 1211 SetExpressionPosition(proxy); | 1108 SetExpressionPosition(proxy); |
| 1212 PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); | 1109 PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); |
| 1213 Variable* var = proxy->var(); | 1110 Variable* var = proxy->var(); |
| 1214 | 1111 |
| 1215 // Three cases: global variables, lookup variables, and all other types of | 1112 // Two cases: global variables and all other types of variables. |
| 1216 // variables. | |
| 1217 switch (var->location()) { | 1113 switch (var->location()) { |
| 1218 case VariableLocation::UNALLOCATED: { | 1114 case VariableLocation::UNALLOCATED: { |
| 1219 Comment cmnt(masm_, "[ Global variable"); | 1115 Comment cmnt(masm_, "[ Global variable"); |
| 1220 EmitGlobalVariableLoad(proxy, typeof_mode); | 1116 EmitGlobalVariableLoad(proxy, typeof_mode); |
| 1221 context()->Plug(r2); | 1117 context()->Plug(r2); |
| 1222 break; | 1118 break; |
| 1223 } | 1119 } |
| 1224 | 1120 |
| 1225 case VariableLocation::PARAMETER: | 1121 case VariableLocation::PARAMETER: |
| 1226 case VariableLocation::LOCAL: | 1122 case VariableLocation::LOCAL: |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1239 __ push(r2); | 1135 __ push(r2); |
| 1240 __ CallRuntime(Runtime::kThrowReferenceError); | 1136 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1241 __ bind(&done); | 1137 __ bind(&done); |
| 1242 context()->Plug(r2); | 1138 context()->Plug(r2); |
| 1243 break; | 1139 break; |
| 1244 } | 1140 } |
| 1245 context()->Plug(var); | 1141 context()->Plug(var); |
| 1246 break; | 1142 break; |
| 1247 } | 1143 } |
| 1248 | 1144 |
| 1249 case VariableLocation::LOOKUP: { | 1145 case VariableLocation::LOOKUP: |
| 1250 Comment cmnt(masm_, "[ Lookup variable"); | |
| 1251 Label done, slow; | |
| 1252 // Generate code for loading from variables potentially shadowed | |
| 1253 // by eval-introduced variables. | |
| 1254 EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done); | |
| 1255 __ bind(&slow); | |
| 1256 __ Push(var->name()); | |
| 1257 Runtime::FunctionId function_id = | |
| 1258 typeof_mode == NOT_INSIDE_TYPEOF | |
| 1259 ? Runtime::kLoadLookupSlot | |
| 1260 : Runtime::kLoadLookupSlotInsideTypeof; | |
| 1261 __ CallRuntime(function_id); | |
| 1262 __ bind(&done); | |
| 1263 context()->Plug(r2); | |
| 1264 break; | |
| 1265 } | |
| 1266 | |
| 1267 case VariableLocation::MODULE: | 1146 case VariableLocation::MODULE: |
| 1268 UNREACHABLE(); | 1147 UNREACHABLE(); |
| 1269 } | 1148 } |
| 1270 } | 1149 } |
| 1271 | 1150 |
| 1272 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) { | 1151 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) { |
| 1273 Expression* expression = (property == NULL) ? NULL : property->value(); | 1152 Expression* expression = (property == NULL) ? NULL : property->value(); |
| 1274 if (expression == NULL) { | 1153 if (expression == NULL) { |
| 1275 __ LoadRoot(r3, Heap::kNullValueRootIndex); | 1154 __ LoadRoot(r3, Heap::kNullValueRootIndex); |
| 1276 PushOperand(r3); | 1155 PushOperand(r3); |
| (...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2060 __ LoadP(r5, location); | 1939 __ LoadP(r5, location); |
| 2061 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); | 1940 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); |
| 2062 __ beq(&uninitialized_this); | 1941 __ beq(&uninitialized_this); |
| 2063 __ mov(r3, Operand(var->name())); | 1942 __ mov(r3, Operand(var->name())); |
| 2064 __ push(r3); | 1943 __ push(r3); |
| 2065 __ CallRuntime(Runtime::kThrowReferenceError); | 1944 __ CallRuntime(Runtime::kThrowReferenceError); |
| 2066 __ bind(&uninitialized_this); | 1945 __ bind(&uninitialized_this); |
| 2067 EmitStoreToStackLocalOrContextSlot(var, location); | 1946 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2068 } else { | 1947 } else { |
| 2069 DCHECK(var->mode() != CONST || op == Token::INIT); | 1948 DCHECK(var->mode() != CONST || op == Token::INIT); |
| 2070 if (var->IsLookupSlot()) { | 1949 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); |
| 2071 // Assignment to var. | 1950 DCHECK(!var->IsLookupSlot()); |
| 2072 __ Push(var->name()); | 1951 // Assignment to var or initializing assignment to let/const in harmony |
| 2073 __ Push(r2); | 1952 // mode. |
| 2074 __ CallRuntime(is_strict(language_mode()) | 1953 MemOperand location = VarOperand(var, r3); |
| 2075 ? Runtime::kStoreLookupSlot_Strict | 1954 if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { |
| 2076 : Runtime::kStoreLookupSlot_Sloppy); | 1955 // Check for an uninitialized let binding. |
| 2077 } else { | 1956 __ LoadP(r4, location); |
| 2078 // Assignment to var or initializing assignment to let/const in harmony | 1957 __ CompareRoot(r4, Heap::kTheHoleValueRootIndex); |
| 2079 // mode. | 1958 __ Check(eq, kLetBindingReInitialization); |
| 2080 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); | |
| 2081 MemOperand location = VarOperand(var, r3); | |
| 2082 if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { | |
| 2083 // Check for an uninitialized let binding. | |
| 2084 __ LoadP(r4, location); | |
| 2085 __ CompareRoot(r4, Heap::kTheHoleValueRootIndex); | |
| 2086 __ Check(eq, kLetBindingReInitialization); | |
| 2087 } | |
| 2088 EmitStoreToStackLocalOrContextSlot(var, location); | |
| 2089 } | 1959 } |
| 1960 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2090 } | 1961 } |
| 2091 } | 1962 } |
| 2092 | 1963 |
| 2093 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1964 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
| 2094 // Assignment to a property, using a named store IC. | 1965 // Assignment to a property, using a named store IC. |
| 2095 Property* prop = expr->target()->AsProperty(); | 1966 Property* prop = expr->target()->AsProperty(); |
| 2096 DCHECK(prop != NULL); | 1967 DCHECK(prop != NULL); |
| 2097 DCHECK(prop->key()->IsLiteral()); | 1968 DCHECK(prop->key()->IsLiteral()); |
| 2098 | 1969 |
| 2099 PopOperand(StoreDescriptor::ReceiverRegister()); | 1970 PopOperand(StoreDescriptor::ReceiverRegister()); |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2294 __ LoadP(r3, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); | 2165 __ LoadP(r3, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); |
| 2295 __ mov(r2, Operand(arg_count)); | 2166 __ mov(r2, Operand(arg_count)); |
| 2296 CallIC(code); | 2167 CallIC(code); |
| 2297 OperandStackDepthDecrement(arg_count + 1); | 2168 OperandStackDepthDecrement(arg_count + 1); |
| 2298 | 2169 |
| 2299 RecordJSReturnSite(expr); | 2170 RecordJSReturnSite(expr); |
| 2300 RestoreContext(); | 2171 RestoreContext(); |
| 2301 context()->DropAndPlug(1, r2); | 2172 context()->DropAndPlug(1, r2); |
| 2302 } | 2173 } |
| 2303 | 2174 |
| 2304 void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) { | |
| 2305 int arg_count = expr->arguments()->length(); | |
| 2306 // r6: copy of the first argument or undefined if it doesn't exist. | |
| 2307 if (arg_count > 0) { | |
| 2308 __ LoadP(r6, MemOperand(sp, arg_count * kPointerSize), r0); | |
| 2309 } else { | |
| 2310 __ LoadRoot(r6, Heap::kUndefinedValueRootIndex); | |
| 2311 } | |
| 2312 | |
| 2313 // r5: the receiver of the enclosing function. | |
| 2314 __ LoadP(r5, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | |
| 2315 | |
| 2316 // r4: language mode. | |
| 2317 __ LoadSmiLiteral(r4, Smi::FromInt(language_mode())); | |
| 2318 | |
| 2319 // r3: the start position of the scope the calls resides in. | |
| 2320 __ LoadSmiLiteral(r3, Smi::FromInt(scope()->start_position())); | |
| 2321 | |
| 2322 // r2: the source position of the eval call. | |
| 2323 __ LoadSmiLiteral(r2, Smi::FromInt(expr->position())); | |
| 2324 | |
| 2325 // Do the runtime call. | |
| 2326 __ Push(r6, r5, r4, r3, r2); | |
| 2327 __ CallRuntime(Runtime::kResolvePossiblyDirectEval); | |
| 2328 } | |
| 2329 | |
| 2330 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. | |
| 2331 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { | |
| 2332 VariableProxy* callee = expr->expression()->AsVariableProxy(); | |
| 2333 if (callee->var()->IsLookupSlot()) { | |
| 2334 Label slow, done; | |
| 2335 SetExpressionPosition(callee); | |
| 2336 // Generate code for loading from variables potentially shadowed by | |
| 2337 // eval-introduced variables. | |
| 2338 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); | |
| 2339 | |
| 2340 __ bind(&slow); | |
| 2341 // Call the runtime to find the function to call (returned in r2) and | |
| 2342 // the object holding it (returned in r3). | |
| 2343 __ Push(callee->name()); | |
| 2344 __ CallRuntime(Runtime::kLoadLookupSlotForCall); | |
| 2345 PushOperands(r2, r3); // Function, receiver. | |
| 2346 PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS); | |
| 2347 | |
| 2348 // If fast case code has been generated, emit code to push the function | |
| 2349 // and receiver and have the slow path jump around this code. | |
| 2350 if (done.is_linked()) { | |
| 2351 Label call; | |
| 2352 __ b(&call); | |
| 2353 __ bind(&done); | |
| 2354 // Push function. | |
| 2355 __ push(r2); | |
| 2356 // Pass undefined as the receiver, which is the WithBaseObject of a | |
| 2357 // non-object environment record. If the callee is sloppy, it will patch | |
| 2358 // it up to be the global receiver. | |
| 2359 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); | |
| 2360 __ push(r3); | |
| 2361 __ bind(&call); | |
| 2362 } | |
| 2363 } else { | |
| 2364 VisitForStackValue(callee); | |
| 2365 // refEnv.WithBaseObject() | |
| 2366 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); | |
| 2367 PushOperand(r4); // Reserved receiver slot. | |
| 2368 } | |
| 2369 } | |
| 2370 | |
| 2371 void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) { | |
| 2372 // In a call to eval, we first call | |
| 2373 // Runtime_ResolvePossiblyDirectEval to resolve the function we need | |
| 2374 // to call. Then we call the resolved function using the given arguments. | |
| 2375 ZoneList<Expression*>* args = expr->arguments(); | |
| 2376 int arg_count = args->length(); | |
| 2377 | |
| 2378 PushCalleeAndWithBaseObject(expr); | |
| 2379 | |
| 2380 // Push the arguments. | |
| 2381 for (int i = 0; i < arg_count; i++) { | |
| 2382 VisitForStackValue(args->at(i)); | |
| 2383 } | |
| 2384 | |
| 2385 // Push a copy of the function (found below the arguments) and | |
| 2386 // resolve eval. | |
| 2387 __ LoadP(r3, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); | |
| 2388 __ push(r3); | |
| 2389 EmitResolvePossiblyDirectEval(expr); | |
| 2390 | |
| 2391 // Touch up the stack with the resolved function. | |
| 2392 __ StoreP(r2, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); | |
| 2393 | |
| 2394 PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS); | |
| 2395 | |
| 2396 // Record source position for debugger. | |
| 2397 SetCallPosition(expr); | |
| 2398 Handle<Code> code = CodeFactory::CallIC(isolate(), ConvertReceiverMode::kAny, | |
| 2399 expr->tail_call_mode()) | |
| 2400 .code(); | |
| 2401 __ LoadSmiLiteral(r5, SmiFromSlot(expr->CallFeedbackICSlot())); | |
| 2402 __ LoadP(r3, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); | |
| 2403 __ mov(r2, Operand(arg_count)); | |
| 2404 __ Call(code, RelocInfo::CODE_TARGET); | |
| 2405 OperandStackDepthDecrement(arg_count + 1); | |
| 2406 RecordJSReturnSite(expr); | |
| 2407 RestoreContext(); | |
| 2408 context()->DropAndPlug(1, r2); | |
| 2409 } | |
| 2410 | |
| 2411 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 2175 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
| 2412 Comment cmnt(masm_, "[ CallNew"); | 2176 Comment cmnt(masm_, "[ CallNew"); |
| 2413 // According to ECMA-262, section 11.2.2, page 44, the function | 2177 // According to ECMA-262, section 11.2.2, page 44, the function |
| 2414 // expression in new calls must be evaluated before the | 2178 // expression in new calls must be evaluated before the |
| 2415 // arguments. | 2179 // arguments. |
| 2416 | 2180 |
| 2417 // Push constructor on the stack. If it's not a function it's used as | 2181 // Push constructor on the stack. If it's not a function it's used as |
| 2418 // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is | 2182 // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is |
| 2419 // ignored. | 2183 // ignored. |
| 2420 DCHECK(!expr->expression()->IsSuperPropertyReference()); | 2184 DCHECK(!expr->expression()->IsSuperPropertyReference()); |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2815 // Delete of an unqualified identifier is disallowed in strict mode but | 2579 // Delete of an unqualified identifier is disallowed in strict mode but |
| 2816 // "delete this" is allowed. | 2580 // "delete this" is allowed. |
| 2817 bool is_this = var->is_this(); | 2581 bool is_this = var->is_this(); |
| 2818 DCHECK(is_sloppy(language_mode()) || is_this); | 2582 DCHECK(is_sloppy(language_mode()) || is_this); |
| 2819 if (var->IsUnallocated()) { | 2583 if (var->IsUnallocated()) { |
| 2820 __ LoadGlobalObject(r4); | 2584 __ LoadGlobalObject(r4); |
| 2821 __ mov(r3, Operand(var->name())); | 2585 __ mov(r3, Operand(var->name())); |
| 2822 __ Push(r4, r3); | 2586 __ Push(r4, r3); |
| 2823 __ CallRuntime(Runtime::kDeleteProperty_Sloppy); | 2587 __ CallRuntime(Runtime::kDeleteProperty_Sloppy); |
| 2824 context()->Plug(r2); | 2588 context()->Plug(r2); |
| 2825 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 2589 } else { |
| 2590 DCHECK(!var->IsLookupSlot()); |
| 2591 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2826 // Result of deleting non-global, non-dynamic variables is false. | 2592 // Result of deleting non-global, non-dynamic variables is false. |
| 2827 // The subexpression does not have side effects. | 2593 // The subexpression does not have side effects. |
| 2828 context()->Plug(is_this); | 2594 context()->Plug(is_this); |
| 2829 } else { | |
| 2830 // Non-global variable. Call the runtime to try to delete from the | |
| 2831 // context where the variable was introduced. | |
| 2832 __ Push(var->name()); | |
| 2833 __ CallRuntime(Runtime::kDeleteLookupSlot); | |
| 2834 context()->Plug(r2); | |
| 2835 } | 2595 } |
| 2836 } else { | 2596 } else { |
| 2837 // Result of deleting non-property, non-variable reference is true. | 2597 // Result of deleting non-property, non-variable reference is true. |
| 2838 // The subexpression may have side effects. | 2598 // The subexpression may have side effects. |
| 2839 VisitForEffect(expr->expression()); | 2599 VisitForEffect(expr->expression()); |
| 2840 context()->Plug(true); | 2600 context()->Plug(true); |
| 2841 } | 2601 } |
| 2842 break; | 2602 break; |
| 2843 } | 2603 } |
| 2844 | 2604 |
| (...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3498 DCHECK(kOSRBranchInstruction == br_instr); | 3258 DCHECK(kOSRBranchInstruction == br_instr); |
| 3499 | 3259 |
| 3500 DCHECK(interrupt_address == | 3260 DCHECK(interrupt_address == |
| 3501 isolate->builtins()->OnStackReplacement()->entry()); | 3261 isolate->builtins()->OnStackReplacement()->entry()); |
| 3502 return ON_STACK_REPLACEMENT; | 3262 return ON_STACK_REPLACEMENT; |
| 3503 } | 3263 } |
| 3504 | 3264 |
| 3505 } // namespace internal | 3265 } // namespace internal |
| 3506 } // namespace v8 | 3266 } // namespace v8 |
| 3507 #endif // V8_TARGET_ARCH_S390 | 3267 #endif // V8_TARGET_ARCH_S390 |
| OLD | NEW |