OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 | 138 |
139 #ifdef DEBUG | 139 #ifdef DEBUG |
140 if (strlen(FLAG_stop_at) > 0 && | 140 if (strlen(FLAG_stop_at) > 0 && |
141 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 141 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
142 __ stop("stop_at"); | 142 __ stop("stop_at"); |
143 } | 143 } |
144 #endif | 144 #endif |
145 | 145 |
146 // r1: Callee's JS function. | 146 // r1: Callee's JS function. |
147 // cp: Callee's context. | 147 // cp: Callee's context. |
| 148 // pp: Callee's constant pool pointer (if FLAG_enable_ool_constant_pool) |
148 // fp: Caller's frame pointer. | 149 // fp: Caller's frame pointer. |
149 // lr: Caller's pc. | 150 // lr: Caller's pc. |
150 | 151 |
151 // Strict mode functions and builtins need to replace the receiver | 152 // Strict mode functions and builtins need to replace the receiver |
152 // with undefined when called as functions (without an explicit | 153 // with undefined when called as functions (without an explicit |
153 // receiver object). r5 is zero for method calls and non-zero for | 154 // receiver object). r5 is zero for method calls and non-zero for |
154 // function calls. | 155 // function calls. |
155 if (!info_->is_classic_mode() || info_->is_native()) { | 156 if (!info_->is_classic_mode() || info_->is_native()) { |
156 __ cmp(r5, Operand::Zero()); | 157 __ cmp(r5, Operand::Zero()); |
157 int receiver_offset = scope()->num_parameters() * kPointerSize; | 158 int receiver_offset = scope()->num_parameters() * kPointerSize; |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 "-------------------- Deferred %s --------------------", | 274 "-------------------- Deferred %s --------------------", |
274 code->instruction_index(), | 275 code->instruction_index(), |
275 code->instr()->hydrogen_value()->id(), | 276 code->instr()->hydrogen_value()->id(), |
276 code->instr()->Mnemonic()); | 277 code->instr()->Mnemonic()); |
277 __ bind(code->entry()); | 278 __ bind(code->entry()); |
278 if (NeedsDeferredFrame()) { | 279 if (NeedsDeferredFrame()) { |
279 Comment(";;; Build frame"); | 280 Comment(";;; Build frame"); |
280 ASSERT(!frame_is_built_); | 281 ASSERT(!frame_is_built_); |
281 ASSERT(info()->IsStub()); | 282 ASSERT(info()->IsStub()); |
282 frame_is_built_ = true; | 283 frame_is_built_ = true; |
283 __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); | 284 __ PushFixedFrame(); |
284 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); | 285 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); |
285 __ push(scratch0()); | 286 __ push(scratch0()); |
286 __ add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); | 287 __ add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); |
287 Comment(";;; Deferred code"); | 288 Comment(";;; Deferred code"); |
288 } | 289 } |
289 code->Generate(); | 290 code->Generate(); |
290 if (NeedsDeferredFrame()) { | 291 if (NeedsDeferredFrame()) { |
291 Comment(";;; Destroy frame"); | 292 Comment(";;; Destroy frame"); |
292 ASSERT(frame_is_built_); | 293 ASSERT(frame_is_built_); |
293 __ pop(ip); | 294 __ pop(ip); |
294 __ ldm(ia_w, sp, cp.bit() | fp.bit() | lr.bit()); | 295 __ PopFixedFrame(); |
295 frame_is_built_ = false; | 296 frame_is_built_ = false; |
296 } | 297 } |
297 __ jmp(code->exit()); | 298 __ jmp(code->exit()); |
298 } | 299 } |
299 } | 300 } |
300 | 301 |
301 // Force constant pool emission at the end of the deferred code to make | 302 // Force constant pool emission at the end of the deferred code to make |
302 // sure that no constant pools are emitted after. | 303 // sure that no constant pools are emitted after. |
303 masm()->CheckConstPool(true, false); | 304 masm()->CheckConstPool(true, false); |
304 | 305 |
(...skipping 30 matching lines...) Expand all Loading... |
335 } else { | 336 } else { |
336 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); | 337 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); |
337 } | 338 } |
338 if (deopt_jump_table_[i].needs_frame) { | 339 if (deopt_jump_table_[i].needs_frame) { |
339 ASSERT(!info()->saves_caller_doubles()); | 340 ASSERT(!info()->saves_caller_doubles()); |
340 __ mov(ip, Operand(ExternalReference::ForDeoptEntry(entry))); | 341 __ mov(ip, Operand(ExternalReference::ForDeoptEntry(entry))); |
341 if (needs_frame.is_bound()) { | 342 if (needs_frame.is_bound()) { |
342 __ b(&needs_frame); | 343 __ b(&needs_frame); |
343 } else { | 344 } else { |
344 __ bind(&needs_frame); | 345 __ bind(&needs_frame); |
345 __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); | 346 __ PushFixedFrame(); |
346 // This variant of deopt can only be used with stubs. Since we don't | 347 // This variant of deopt can only be used with stubs. Since we don't |
347 // have a function pointer to install in the stack frame that we're | 348 // have a function pointer to install in the stack frame that we're |
348 // building, install a special marker there instead. | 349 // building, install a special marker there instead. |
349 ASSERT(info()->IsStub()); | 350 ASSERT(info()->IsStub()); |
350 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); | 351 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); |
351 __ push(scratch0()); | 352 __ push(scratch0()); |
352 __ add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); | 353 __ add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); |
353 __ mov(lr, Operand(pc), LeaveCC, al); | 354 __ mov(lr, Operand(pc), LeaveCC, al); |
354 __ mov(pc, ip); | 355 __ mov(pc, ip); |
355 } | 356 } |
(...skipping 3228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3584 __ bind(&invoke); | 3585 __ bind(&invoke); |
3585 ASSERT(instr->HasPointerMap()); | 3586 ASSERT(instr->HasPointerMap()); |
3586 LPointerMap* pointers = instr->pointer_map(); | 3587 LPointerMap* pointers = instr->pointer_map(); |
3587 SafepointGenerator safepoint_generator( | 3588 SafepointGenerator safepoint_generator( |
3588 this, pointers, Safepoint::kLazyDeopt); | 3589 this, pointers, Safepoint::kLazyDeopt); |
3589 // The number of arguments is stored in receiver which is r0, as expected | 3590 // The number of arguments is stored in receiver which is r0, as expected |
3590 // by InvokeFunction. | 3591 // by InvokeFunction. |
3591 ParameterCount actual(receiver); | 3592 ParameterCount actual(receiver); |
3592 __ InvokeFunction(function, actual, CALL_FUNCTION, | 3593 __ InvokeFunction(function, actual, CALL_FUNCTION, |
3593 safepoint_generator, CALL_AS_METHOD); | 3594 safepoint_generator, CALL_AS_METHOD); |
| 3595 __ RestoreConstantPoolPointer(); |
3594 } | 3596 } |
3595 | 3597 |
3596 | 3598 |
3597 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 3599 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
3598 LOperand* argument = instr->value(); | 3600 LOperand* argument = instr->value(); |
3599 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { | 3601 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { |
3600 Abort(kDoPushArgumentNotImplementedForDoubleType); | 3602 Abort(kDoPushArgumentNotImplementedForDoubleType); |
3601 } else { | 3603 } else { |
3602 Register argument_reg = EmitLoadRegister(argument, ip); | 3604 Register argument_reg = EmitLoadRegister(argument, ip); |
3603 __ push(argument_reg); | 3605 __ push(argument_reg); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3684 | 3686 |
3685 // Set r0 to arguments count if adaption is not needed. Assumes that r0 | 3687 // Set r0 to arguments count if adaption is not needed. Assumes that r0 |
3686 // is available to write to at this point. | 3688 // is available to write to at this point. |
3687 if (dont_adapt_arguments) { | 3689 if (dont_adapt_arguments) { |
3688 __ mov(r0, Operand(arity)); | 3690 __ mov(r0, Operand(arity)); |
3689 } | 3691 } |
3690 | 3692 |
3691 // Invoke function. | 3693 // Invoke function. |
3692 __ SetCallKind(r5, call_kind); | 3694 __ SetCallKind(r5, call_kind); |
3693 __ ldr(ip, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); | 3695 __ ldr(ip, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); |
| 3696 __ LoadConstantPoolPointer(r1); |
3694 __ Call(ip); | 3697 __ Call(ip); |
3695 | 3698 |
| 3699 |
3696 // Set up deoptimization. | 3700 // Set up deoptimization. |
3697 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 3701 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
3698 } else { | 3702 } else { |
3699 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3703 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
3700 ParameterCount count(arity); | 3704 ParameterCount count(arity); |
3701 ParameterCount expected(formal_parameter_count); | 3705 ParameterCount expected(formal_parameter_count); |
3702 __ InvokeFunction( | 3706 __ InvokeFunction( |
3703 function, expected, count, CALL_FUNCTION, generator, call_kind); | 3707 function, expected, count, CALL_FUNCTION, generator, call_kind); |
3704 } | 3708 } |
| 3709 __ RestoreConstantPoolPointer(); |
3705 } | 3710 } |
3706 | 3711 |
3707 | 3712 |
3708 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 3713 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
3709 ASSERT(ToRegister(instr->result()).is(r0)); | 3714 ASSERT(ToRegister(instr->result()).is(r0)); |
3710 CallKnownFunction(instr->hydrogen()->function(), | 3715 CallKnownFunction(instr->hydrogen()->function(), |
3711 instr->hydrogen()->formal_parameter_count(), | 3716 instr->hydrogen()->formal_parameter_count(), |
3712 instr->arity(), | 3717 instr->arity(), |
3713 instr, | 3718 instr, |
3714 CALL_AS_METHOD, | 3719 CALL_AS_METHOD, |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4018 ASSERT(ToRegister(instr->context()).is(cp)); | 4023 ASSERT(ToRegister(instr->context()).is(cp)); |
4019 ASSERT(ToRegister(instr->function()).is(r1)); | 4024 ASSERT(ToRegister(instr->function()).is(r1)); |
4020 ASSERT(instr->HasPointerMap()); | 4025 ASSERT(instr->HasPointerMap()); |
4021 | 4026 |
4022 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 4027 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
4023 if (known_function.is_null()) { | 4028 if (known_function.is_null()) { |
4024 LPointerMap* pointers = instr->pointer_map(); | 4029 LPointerMap* pointers = instr->pointer_map(); |
4025 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 4030 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
4026 ParameterCount count(instr->arity()); | 4031 ParameterCount count(instr->arity()); |
4027 __ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD); | 4032 __ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD); |
| 4033 __ RestoreConstantPoolPointer(); |
4028 } else { | 4034 } else { |
4029 CallKnownFunction(known_function, | 4035 CallKnownFunction(known_function, |
4030 instr->hydrogen()->formal_parameter_count(), | 4036 instr->hydrogen()->formal_parameter_count(), |
4031 instr->arity(), | 4037 instr->arity(), |
4032 instr, | 4038 instr, |
4033 CALL_AS_METHOD, | 4039 CALL_AS_METHOD, |
4034 R1_CONTAINS_TARGET); | 4040 R1_CONTAINS_TARGET); |
4035 } | 4041 } |
4036 } | 4042 } |
4037 | 4043 |
4038 | 4044 |
4039 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { | 4045 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { |
4040 ASSERT(ToRegister(instr->context()).is(cp)); | 4046 ASSERT(ToRegister(instr->context()).is(cp)); |
4041 ASSERT(ToRegister(instr->result()).is(r0)); | 4047 ASSERT(ToRegister(instr->result()).is(r0)); |
4042 | 4048 |
4043 int arity = instr->arity(); | 4049 int arity = instr->arity(); |
4044 Handle<Code> ic = | 4050 Handle<Code> ic = |
4045 isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); | 4051 isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); |
4046 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); | 4052 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); |
| 4053 __ RestoreConstantPoolPointer(); |
4047 } | 4054 } |
4048 | 4055 |
4049 | 4056 |
4050 void LCodeGen::DoCallNamed(LCallNamed* instr) { | 4057 void LCodeGen::DoCallNamed(LCallNamed* instr) { |
4051 ASSERT(ToRegister(instr->context()).is(cp)); | 4058 ASSERT(ToRegister(instr->context()).is(cp)); |
4052 ASSERT(ToRegister(instr->result()).is(r0)); | 4059 ASSERT(ToRegister(instr->result()).is(r0)); |
4053 | 4060 |
4054 int arity = instr->arity(); | 4061 int arity = instr->arity(); |
4055 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 4062 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; |
4056 Handle<Code> ic = | 4063 Handle<Code> ic = |
4057 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); | 4064 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); |
4058 __ mov(r2, Operand(instr->name())); | 4065 __ mov(r2, Operand(instr->name())); |
4059 CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS); | 4066 CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS); |
| 4067 __ RestoreConstantPoolPointer(); |
4060 } | 4068 } |
4061 | 4069 |
4062 | 4070 |
4063 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 4071 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
4064 ASSERT(ToRegister(instr->context()).is(cp)); | 4072 ASSERT(ToRegister(instr->context()).is(cp)); |
4065 ASSERT(ToRegister(instr->function()).is(r1)); | 4073 ASSERT(ToRegister(instr->function()).is(r1)); |
4066 ASSERT(ToRegister(instr->result()).is(r0)); | 4074 ASSERT(ToRegister(instr->result()).is(r0)); |
4067 | 4075 |
4068 int arity = instr->arity(); | 4076 int arity = instr->arity(); |
4069 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); | 4077 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); |
4070 if (instr->hydrogen()->IsTailCall()) { | 4078 if (instr->hydrogen()->IsTailCall()) { |
4071 if (NeedsEagerFrame()) __ mov(sp, fp); | 4079 if (NeedsEagerFrame()) __ mov(sp, fp); |
4072 __ Jump(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); | 4080 __ Jump(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); |
4073 } else { | 4081 } else { |
4074 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4082 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 4083 __ RestoreConstantPoolPointer(); |
4075 } | 4084 } |
4076 } | 4085 } |
4077 | 4086 |
4078 | 4087 |
4079 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | 4088 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { |
4080 ASSERT(ToRegister(instr->context()).is(cp)); | 4089 ASSERT(ToRegister(instr->context()).is(cp)); |
4081 ASSERT(ToRegister(instr->result()).is(r0)); | 4090 ASSERT(ToRegister(instr->result()).is(r0)); |
4082 | 4091 |
4083 int arity = instr->arity(); | 4092 int arity = instr->arity(); |
4084 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; | 4093 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; |
4085 Handle<Code> ic = | 4094 Handle<Code> ic = |
4086 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); | 4095 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); |
4087 __ mov(r2, Operand(instr->name())); | 4096 __ mov(r2, Operand(instr->name())); |
4088 CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS); | 4097 CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS); |
| 4098 __ RestoreConstantPoolPointer(); |
4089 } | 4099 } |
4090 | 4100 |
4091 | 4101 |
4092 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | 4102 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { |
4093 ASSERT(ToRegister(instr->result()).is(r0)); | 4103 ASSERT(ToRegister(instr->result()).is(r0)); |
4094 CallKnownFunction(instr->hydrogen()->target(), | 4104 CallKnownFunction(instr->hydrogen()->target(), |
4095 instr->hydrogen()->formal_parameter_count(), | 4105 instr->hydrogen()->formal_parameter_count(), |
4096 instr->arity(), | 4106 instr->arity(), |
4097 instr, | 4107 instr, |
4098 CALL_AS_FUNCTION, | 4108 CALL_AS_FUNCTION, |
(...skipping 1779 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5878 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5888 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
5879 __ ldr(result, FieldMemOperand(scratch, | 5889 __ ldr(result, FieldMemOperand(scratch, |
5880 FixedArray::kHeaderSize - kPointerSize)); | 5890 FixedArray::kHeaderSize - kPointerSize)); |
5881 __ bind(&done); | 5891 __ bind(&done); |
5882 } | 5892 } |
5883 | 5893 |
5884 | 5894 |
5885 #undef __ | 5895 #undef __ |
5886 | 5896 |
5887 } } // namespace v8::internal | 5897 } } // namespace v8::internal |
OLD | NEW |