| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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_PPC | 5 #if V8_TARGET_ARCH_PPC |
| 6 | 6 |
| 7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 }; | 82 }; |
| 83 | 83 |
| 84 | 84 |
| 85 // Generate code for a JS function. On entry to the function the receiver | 85 // Generate code for a JS function. On entry to the function the receiver |
| 86 // and arguments have been pushed on the stack left to right. The actual | 86 // and arguments have been pushed on the stack left to right. The actual |
| 87 // argument count matches the formal parameter count expected by the | 87 // argument count matches the formal parameter count expected by the |
| 88 // function. | 88 // function. |
| 89 // | 89 // |
| 90 // The live registers are: | 90 // The live registers are: |
| 91 // o r4: the JS function object being called (i.e., ourselves) | 91 // o r4: the JS function object being called (i.e., ourselves) |
| 92 // o r6: the new target value |
| 92 // o cp: our context | 93 // o cp: our context |
| 93 // o fp: our caller's frame pointer (aka r31) | 94 // o fp: our caller's frame pointer (aka r31) |
| 94 // o sp: stack pointer | 95 // o sp: stack pointer |
| 95 // o lr: return address | 96 // o lr: return address |
| 96 // o ip: our own function entry (required by the prologue) | 97 // o ip: our own function entry (required by the prologue) |
| 97 // | 98 // |
| 98 // The function builds a JS frame. Please see JavaScriptFrameConstants in | 99 // The function builds a JS frame. Please see JavaScriptFrameConstants in |
| 99 // frames-ppc.h for its layout. | 100 // frames-ppc.h for its layout. |
| 100 void FullCodeGenerator::Generate() { | 101 void FullCodeGenerator::Generate() { |
| 101 CompilationInfo* info = info_; | 102 CompilationInfo* info = info_; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 180 if (info->scope()->num_heap_slots() > 0) { | 181 if (info->scope()->num_heap_slots() > 0) { |
| 181 // Argument to NewContext is the function, which is still in r4. | 182 // Argument to NewContext is the function, which is still in r4. |
| 182 Comment cmnt(masm_, "[ Allocate context"); | 183 Comment cmnt(masm_, "[ Allocate context"); |
| 183 bool need_write_barrier = true; | 184 bool need_write_barrier = true; |
| 184 int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 185 int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 185 if (info->scope()->is_script_scope()) { | 186 if (info->scope()->is_script_scope()) { |
| 186 __ push(r4); | 187 __ push(r4); |
| 187 __ Push(info->scope()->GetScopeInfo(info->isolate())); | 188 __ Push(info->scope()->GetScopeInfo(info->isolate())); |
| 188 __ CallRuntime(Runtime::kNewScriptContext, 2); | 189 __ CallRuntime(Runtime::kNewScriptContext, 2); |
| 189 PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG); | 190 PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG); |
| 190 } else if (slots <= FastNewContextStub::kMaximumSlots) { | 191 // The new target value is not used, clobbering is safe. |
| 191 FastNewContextStub stub(isolate(), slots); | 192 DCHECK_NULL(info->scope()->new_target_var()); |
| 192 __ CallStub(&stub); | |
| 193 // Result of FastNewContextStub is always in new space. | |
| 194 need_write_barrier = false; | |
| 195 } else { | 193 } else { |
| 196 __ push(r4); | 194 if (info->scope()->new_target_var() != nullptr) { |
| 197 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 195 __ push(r6); // Preserve new target. |
| 196 } |
| 197 if (slots <= FastNewContextStub::kMaximumSlots) { |
| 198 FastNewContextStub stub(isolate(), slots); |
| 199 __ CallStub(&stub); |
| 200 // Result of FastNewContextStub is always in new space. |
| 201 need_write_barrier = false; |
| 202 } else { |
| 203 __ push(r4); |
| 204 __ CallRuntime(Runtime::kNewFunctionContext, 1); |
| 205 } |
| 206 if (info->scope()->new_target_var() != nullptr) { |
| 207 __ pop(r6); // Preserve new target. |
| 208 } |
| 198 } | 209 } |
| 199 function_in_register_r4 = false; | 210 function_in_register_r4 = false; |
| 200 // Context is returned in r3. It replaces the context passed to us. | 211 // Context is returned in r3. It replaces the context passed to us. |
| 201 // It's saved in the stack and kept live in cp. | 212 // It's saved in the stack and kept live in cp. |
| 202 __ mr(cp, r3); | 213 __ mr(cp, r3); |
| 203 __ StoreP(r3, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 214 __ StoreP(r3, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 204 // Copy any necessary parameters into the context. | 215 // Copy any necessary parameters into the context. |
| 205 int num_parameters = info->scope()->num_parameters(); | 216 int num_parameters = info->scope()->num_parameters(); |
| 206 int first_parameter = info->scope()->has_this_declaration() ? -1 : 0; | 217 int first_parameter = info->scope()->has_this_declaration() ? -1 : 0; |
| 207 for (int i = first_parameter; i < num_parameters; i++) { | 218 for (int i = first_parameter; i < num_parameters; i++) { |
| 208 Variable* var = (i == -1) ? scope()->receiver() : scope()->parameter(i); | 219 Variable* var = (i == -1) ? scope()->receiver() : scope()->parameter(i); |
| 209 if (var->IsContextSlot()) { | 220 if (var->IsContextSlot()) { |
| 210 int parameter_offset = StandardFrameConstants::kCallerSPOffset + | 221 int parameter_offset = StandardFrameConstants::kCallerSPOffset + |
| 211 (num_parameters - 1 - i) * kPointerSize; | 222 (num_parameters - 1 - i) * kPointerSize; |
| 212 // Load parameter from stack. | 223 // Load parameter from stack. |
| 213 __ LoadP(r3, MemOperand(fp, parameter_offset), r0); | 224 __ LoadP(r3, MemOperand(fp, parameter_offset), r0); |
| 214 // Store it in the context. | 225 // Store it in the context. |
| 215 MemOperand target = ContextMemOperand(cp, var->index()); | 226 MemOperand target = ContextMemOperand(cp, var->index()); |
| 216 __ StoreP(r3, target, r0); | 227 __ StoreP(r3, target, r0); |
| 217 | 228 |
| 218 // Update the write barrier. | 229 // Update the write barrier. |
| 219 if (need_write_barrier) { | 230 if (need_write_barrier) { |
| 220 __ RecordWriteContextSlot(cp, target.offset(), r3, r6, | 231 __ RecordWriteContextSlot(cp, target.offset(), r3, r5, |
| 221 kLRHasBeenSaved, kDontSaveFPRegs); | 232 kLRHasBeenSaved, kDontSaveFPRegs); |
| 222 } else if (FLAG_debug_code) { | 233 } else if (FLAG_debug_code) { |
| 223 Label done; | 234 Label done; |
| 224 __ JumpIfInNewSpace(cp, r3, &done); | 235 __ JumpIfInNewSpace(cp, r3, &done); |
| 225 __ Abort(kExpectedNewSpaceObject); | 236 __ Abort(kExpectedNewSpaceObject); |
| 226 __ bind(&done); | 237 __ bind(&done); |
| 227 } | 238 } |
| 228 } | 239 } |
| 229 } | 240 } |
| 230 } | 241 } |
| 242 |
| 243 // Register holding this function and new target are both trashed in case we |
| 244 // bailout here. But since that can happen only when new target is not used |
| 245 // and we allocate a context, the value of |function_in_register| is correct. |
| 231 PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS); | 246 PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS); |
| 232 | 247 |
| 233 // Function register is trashed in case we bailout here. But since that | |
| 234 // could happen only when we allocate a context the value of | |
| 235 // |function_in_register_r4| is correct. | |
| 236 | |
| 237 // Possibly set up a local binding to the this function which is used in | 248 // Possibly set up a local binding to the this function which is used in |
| 238 // derived constructors with super calls. | 249 // derived constructors with super calls. |
| 239 Variable* this_function_var = scope()->this_function_var(); | 250 Variable* this_function_var = scope()->this_function_var(); |
| 240 if (this_function_var != nullptr) { | 251 if (this_function_var != nullptr) { |
| 241 Comment cmnt(masm_, "[ This function"); | 252 Comment cmnt(masm_, "[ This function"); |
| 242 if (!function_in_register_r4) { | 253 if (!function_in_register_r4) { |
| 243 __ LoadP(r4, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 254 __ LoadP(r4, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 244 // The write barrier clobbers register again, keep it marked as such. | 255 // The write barrier clobbers register again, keep it marked as such. |
| 245 } | 256 } |
| 246 SetVar(this_function_var, r4, r3, r5); | 257 SetVar(this_function_var, r4, r3, r5); |
| 247 } | 258 } |
| 248 | 259 |
| 260 // Possibly set up a local binding to the new target value. |
| 249 Variable* new_target_var = scope()->new_target_var(); | 261 Variable* new_target_var = scope()->new_target_var(); |
| 250 if (new_target_var != nullptr) { | 262 if (new_target_var != nullptr) { |
| 251 Comment cmnt(masm_, "[ new.target"); | 263 Comment cmnt(masm_, "[ new.target"); |
| 252 | 264 SetVar(new_target_var, r6, r3, r5); |
| 253 // Get the frame pointer for the calling frame. | |
| 254 __ LoadP(r5, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | |
| 255 | |
| 256 // Skip the arguments adaptor frame if it exists. | |
| 257 __ LoadP(r4, MemOperand(r5, StandardFrameConstants::kContextOffset)); | |
| 258 __ CmpSmiLiteral(r4, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0); | |
| 259 Label skip; | |
| 260 __ bne(&skip); | |
| 261 __ LoadP(r5, MemOperand(r5, StandardFrameConstants::kCallerFPOffset)); | |
| 262 __ bind(&skip); | |
| 263 | |
| 264 // Check the marker in the calling frame. | |
| 265 __ LoadP(r4, MemOperand(r5, StandardFrameConstants::kMarkerOffset)); | |
| 266 __ CmpSmiLiteral(r4, Smi::FromInt(StackFrame::CONSTRUCT), r0); | |
| 267 Label non_construct_frame, done; | |
| 268 function_in_register_r4 = false; | |
| 269 | |
| 270 __ bne(&non_construct_frame); | |
| 271 __ LoadP(r3, MemOperand(r5, ConstructFrameConstants::kNewTargetOffset)); | |
| 272 __ b(&done); | |
| 273 | |
| 274 __ bind(&non_construct_frame); | |
| 275 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); | |
| 276 __ bind(&done); | |
| 277 | |
| 278 SetVar(new_target_var, r3, r5, r6); | |
| 279 } | 265 } |
| 280 | 266 |
| 281 Variable* arguments = scope()->arguments(); | 267 Variable* arguments = scope()->arguments(); |
| 282 if (arguments != NULL) { | 268 if (arguments != NULL) { |
| 283 // Function uses arguments object. | 269 // Function uses arguments object. |
| 284 Comment cmnt(masm_, "[ Allocate arguments object"); | 270 Comment cmnt(masm_, "[ Allocate arguments object"); |
| 285 DCHECK(r4.is(ArgumentsAccessNewDescriptor::function())); | 271 DCHECK(r4.is(ArgumentsAccessNewDescriptor::function())); |
| 286 if (!function_in_register_r4) { | 272 if (!function_in_register_r4) { |
| 287 // Load this again, if it's used by the local context below. | 273 // Load this again, if it's used by the local context below. |
| 288 __ LoadP(r4, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 274 __ LoadP(r4, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| (...skipping 4630 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4919 return ON_STACK_REPLACEMENT; | 4905 return ON_STACK_REPLACEMENT; |
| 4920 } | 4906 } |
| 4921 | 4907 |
| 4922 DCHECK(interrupt_address == | 4908 DCHECK(interrupt_address == |
| 4923 isolate->builtins()->OsrAfterStackCheck()->entry()); | 4909 isolate->builtins()->OsrAfterStackCheck()->entry()); |
| 4924 return OSR_AFTER_STACK_CHECK; | 4910 return OSR_AFTER_STACK_CHECK; |
| 4925 } | 4911 } |
| 4926 } // namespace internal | 4912 } // namespace internal |
| 4927 } // namespace v8 | 4913 } // namespace v8 |
| 4928 #endif // V8_TARGET_ARCH_PPC | 4914 #endif // V8_TARGET_ARCH_PPC |
| OLD | NEW |