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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 Safepoint::DeoptMode deopt_mode_; | 58 Safepoint::DeoptMode deopt_mode_; |
59 }; | 59 }; |
60 | 60 |
61 | 61 |
62 #define __ masm()-> | 62 #define __ masm()-> |
63 | 63 |
64 bool LCodeGen::GenerateCode() { | 64 bool LCodeGen::GenerateCode() { |
65 HPhase phase("Z_Code generation", chunk()); | 65 HPhase phase("Z_Code generation", chunk()); |
66 ASSERT(is_unused()); | 66 ASSERT(is_unused()); |
67 status_ = GENERATING; | 67 status_ = GENERATING; |
| 68 CpuFeatures::Scope scope1(VFP3); |
| 69 CpuFeatures::Scope scope2(ARMv7); |
68 | 70 |
69 CodeStub::GenerateFPStubs(); | 71 CodeStub::GenerateFPStubs(); |
70 | 72 |
71 // Open a frame scope to indicate that there is a frame on the stack. The | 73 // Open a frame scope to indicate that there is a frame on the stack. The |
72 // NONE indicates that the scope shouldn't actually generate code to set up | 74 // NONE indicates that the scope shouldn't actually generate code to set up |
73 // the frame (that is done in GeneratePrologue). | 75 // the frame (that is done in GeneratePrologue). |
74 FrameScope frame_scope(masm_, StackFrame::NONE); | 76 FrameScope frame_scope(masm_, StackFrame::NONE); |
75 | 77 |
76 return GeneratePrologue() && | 78 return GeneratePrologue() && |
77 GenerateBody() && | 79 GenerateBody() && |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 size_t length = builder.position(); | 111 size_t length = builder.position(); |
110 Vector<char> copy = Vector<char>::New(length + 1); | 112 Vector<char> copy = Vector<char>::New(length + 1); |
111 memcpy(copy.start(), builder.Finalize(), copy.length()); | 113 memcpy(copy.start(), builder.Finalize(), copy.length()); |
112 masm()->RecordComment(copy.start()); | 114 masm()->RecordComment(copy.start()); |
113 } | 115 } |
114 | 116 |
115 | 117 |
116 bool LCodeGen::GeneratePrologue() { | 118 bool LCodeGen::GeneratePrologue() { |
117 ASSERT(is_generating()); | 119 ASSERT(is_generating()); |
118 | 120 |
119 if (info()->IsOptimizing()) { | 121 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
120 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | |
121 | 122 |
122 #ifdef DEBUG | 123 #ifdef DEBUG |
123 if (strlen(FLAG_stop_at) > 0 && | 124 if (strlen(FLAG_stop_at) > 0 && |
124 info_->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { | 125 info_->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { |
125 __ stop("stop_at"); | 126 __ stop("stop_at"); |
126 } | 127 } |
127 #endif | 128 #endif |
128 | 129 |
129 // r1: Callee's JS function. | 130 // r1: Callee's JS function. |
130 // cp: Callee's context. | 131 // cp: Callee's context. |
131 // fp: Caller's frame pointer. | 132 // fp: Caller's frame pointer. |
132 // lr: Caller's pc. | 133 // lr: Caller's pc. |
133 | 134 |
134 // Strict mode functions and builtins need to replace the receiver | 135 // Strict mode functions and builtins need to replace the receiver |
135 // with undefined when called as functions (without an explicit | 136 // with undefined when called as functions (without an explicit |
136 // receiver object). r5 is zero for method calls and non-zero for | 137 // receiver object). r5 is zero for method calls and non-zero for |
137 // function calls. | 138 // function calls. |
138 if (!info_->is_classic_mode() || info_->is_native()) { | 139 if (!info_->is_classic_mode() || info_->is_native()) { |
139 Label ok; | 140 Label ok; |
140 __ cmp(r5, Operand(0)); | 141 __ cmp(r5, Operand(0)); |
141 __ b(eq, &ok); | 142 __ b(eq, &ok); |
142 int receiver_offset = scope()->num_parameters() * kPointerSize; | 143 int receiver_offset = scope()->num_parameters() * kPointerSize; |
143 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); | 144 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); |
144 __ str(r2, MemOperand(sp, receiver_offset)); | 145 __ str(r2, MemOperand(sp, receiver_offset)); |
145 __ bind(&ok); | 146 __ bind(&ok); |
146 } | |
147 } | 147 } |
148 | 148 |
| 149 |
149 info()->set_prologue_offset(masm_->pc_offset()); | 150 info()->set_prologue_offset(masm_->pc_offset()); |
150 if (NeedsEagerFrame()) { | 151 // The following three instructions must remain together and unmodified for |
151 // The following three instructions must remain together and unmodified for | 152 // code aging to work properly. |
152 // code aging to work properly. | 153 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); |
153 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); | 154 // Add unused load of ip to ensure prologue sequence is identical for |
154 // Add unused load of ip to ensure prologue sequence is identical for | 155 // full-codegen and lithium-codegen. |
155 // full-codegen and lithium-codegen. | 156 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
156 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 157 __ add(fp, sp, Operand(2 * kPointerSize)); // Adjust FP to point to saved FP. |
157 __ add(fp, sp, Operand(2 * kPointerSize)); | |
158 frame_is_built_ = true; | |
159 } | |
160 | 158 |
161 // Reserve space for the stack slots needed by the code. | 159 // Reserve space for the stack slots needed by the code. |
162 int slots = GetStackSlotCount(); | 160 int slots = GetStackSlotCount(); |
163 if (slots > 0) { | 161 if (slots > 0) { |
164 if (FLAG_debug_code) { | 162 if (FLAG_debug_code) { |
165 __ mov(r0, Operand(slots)); | 163 __ mov(r0, Operand(slots)); |
166 __ mov(r2, Operand(kSlotsZapValue)); | 164 __ mov(r2, Operand(kSlotsZapValue)); |
167 Label loop; | 165 Label loop; |
168 __ bind(&loop); | 166 __ bind(&loop); |
169 __ push(r2); | 167 __ push(r2); |
170 __ sub(r0, r0, Operand(1), SetCC); | 168 __ sub(r0, r0, Operand(1), SetCC); |
171 __ b(ne, &loop); | 169 __ b(ne, &loop); |
172 } else { | 170 } else { |
173 __ sub(sp, sp, Operand(slots * kPointerSize)); | 171 __ sub(sp, sp, Operand(slots * kPointerSize)); |
174 } | 172 } |
175 } | 173 } |
176 | 174 |
177 // Possibly allocate a local context. | 175 // Possibly allocate a local context. |
178 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 176 int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
179 if (heap_slots > 0) { | 177 if (heap_slots > 0) { |
180 Comment(";;; Allocate local context"); | 178 Comment(";;; Allocate local context"); |
181 // Argument to NewContext is the function, which is in r1. | 179 // Argument to NewContext is the function, which is in r1. |
182 __ push(r1); | 180 __ push(r1); |
183 if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 181 if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
184 FastNewContextStub stub(heap_slots); | 182 FastNewContextStub stub(heap_slots); |
185 __ CallStub(&stub); | 183 __ CallStub(&stub); |
186 } else { | 184 } else { |
187 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 185 __ CallRuntime(Runtime::kNewFunctionContext, 1); |
188 } | 186 } |
(...skipping 15 matching lines...) Expand all Loading... |
204 __ str(r0, target); | 202 __ str(r0, target); |
205 // Update the write barrier. This clobbers r3 and r0. | 203 // Update the write barrier. This clobbers r3 and r0. |
206 __ RecordWriteContextSlot( | 204 __ RecordWriteContextSlot( |
207 cp, target.offset(), r0, r3, kLRHasBeenSaved, kSaveFPRegs); | 205 cp, target.offset(), r0, r3, kLRHasBeenSaved, kSaveFPRegs); |
208 } | 206 } |
209 } | 207 } |
210 Comment(";;; End allocate local context"); | 208 Comment(";;; End allocate local context"); |
211 } | 209 } |
212 | 210 |
213 // Trace the call. | 211 // Trace the call. |
214 if (FLAG_trace && info()->IsOptimizing()) { | 212 if (FLAG_trace) { |
215 __ CallRuntime(Runtime::kTraceEnter, 0); | 213 __ CallRuntime(Runtime::kTraceEnter, 0); |
216 } | 214 } |
217 return !is_aborted(); | 215 return !is_aborted(); |
218 } | 216 } |
219 | 217 |
220 | 218 |
221 bool LCodeGen::GenerateBody() { | 219 bool LCodeGen::GenerateBody() { |
222 ASSERT(is_generating()); | 220 ASSERT(is_generating()); |
223 bool emit_instructions = true; | 221 bool emit_instructions = true; |
224 for (current_instruction_ = 0; | 222 for (current_instruction_ = 0; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 return !is_aborted(); | 260 return !is_aborted(); |
263 } | 261 } |
264 | 262 |
265 | 263 |
266 bool LCodeGen::GenerateDeferredCode() { | 264 bool LCodeGen::GenerateDeferredCode() { |
267 ASSERT(is_generating()); | 265 ASSERT(is_generating()); |
268 if (deferred_.length() > 0) { | 266 if (deferred_.length() > 0) { |
269 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { | 267 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { |
270 LDeferredCode* code = deferred_[i]; | 268 LDeferredCode* code = deferred_[i]; |
271 __ bind(code->entry()); | 269 __ bind(code->entry()); |
272 if (NeedsDeferredFrame()) { | |
273 Comment(";;; Deferred build frame", | |
274 code->instruction_index(), | |
275 code->instr()->Mnemonic()); | |
276 ASSERT(!frame_is_built_); | |
277 ASSERT(info()->IsStub()); | |
278 frame_is_built_ = true; | |
279 __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); | |
280 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); | |
281 __ push(scratch0()); | |
282 __ add(fp, sp, Operand(2 * kPointerSize)); | |
283 } | |
284 Comment(";;; Deferred code @%d: %s.", | 270 Comment(";;; Deferred code @%d: %s.", |
285 code->instruction_index(), | 271 code->instruction_index(), |
286 code->instr()->Mnemonic()); | 272 code->instr()->Mnemonic()); |
287 code->Generate(); | 273 code->Generate(); |
288 if (NeedsDeferredFrame()) { | |
289 Comment(";;; Deferred destroy frame", | |
290 code->instruction_index(), | |
291 code->instr()->Mnemonic()); | |
292 ASSERT(frame_is_built_); | |
293 __ pop(ip); | |
294 __ ldm(ia_w, sp, cp.bit() | fp.bit() | lr.bit()); | |
295 frame_is_built_ = false; | |
296 } | |
297 __ jmp(code->exit()); | 274 __ jmp(code->exit()); |
298 } | 275 } |
299 } | 276 } |
300 | 277 |
301 // Force constant pool emission at the end of the deferred code to make | 278 // Force constant pool emission at the end of the deferred code to make |
302 // sure that no constant pools are emitted after. | 279 // sure that no constant pools are emitted after. |
303 masm()->CheckConstPool(true, false); | 280 masm()->CheckConstPool(true, false); |
304 | 281 |
305 return !is_aborted(); | 282 return !is_aborted(); |
306 } | 283 } |
307 | 284 |
308 | 285 |
309 bool LCodeGen::GenerateDeoptJumpTable() { | 286 bool LCodeGen::GenerateDeoptJumpTable() { |
310 // Check that the jump table is accessible from everywhere in the function | 287 // Check that the jump table is accessible from everywhere in the function |
311 // code, i.e. that offsets to the table can be encoded in the 24bit signed | 288 // code, i.e. that offsets to the table can be encoded in the 24bit signed |
312 // immediate of a branch instruction. | 289 // immediate of a branch instruction. |
313 // To simplify we consider the code size from the first instruction to the | 290 // To simplify we consider the code size from the first instruction to the |
314 // end of the jump table. We also don't consider the pc load delta. | 291 // end of the jump table. We also don't consider the pc load delta. |
315 // Each entry in the jump table generates one instruction and inlines one | 292 // Each entry in the jump table generates one instruction and inlines one |
316 // 32bit data after it. | 293 // 32bit data after it. |
317 if (!is_int24((masm()->pc_offset() / Assembler::kInstrSize) + | 294 if (!is_int24((masm()->pc_offset() / Assembler::kInstrSize) + |
318 deopt_jump_table_.length() * 7)) { | 295 deopt_jump_table_.length() * 2)) { |
319 Abort("Generated code is too large"); | 296 Abort("Generated code is too large"); |
320 } | 297 } |
321 | 298 |
| 299 // Block the constant pool emission during the jump table emission. |
| 300 __ BlockConstPoolFor(deopt_jump_table_.length()); |
322 __ RecordComment("[ Deoptimisation jump table"); | 301 __ RecordComment("[ Deoptimisation jump table"); |
323 Label table_start; | 302 Label table_start; |
324 __ bind(&table_start); | 303 __ bind(&table_start); |
325 Label needs_frame_not_call; | |
326 Label needs_frame_is_call; | |
327 for (int i = 0; i < deopt_jump_table_.length(); i++) { | 304 for (int i = 0; i < deopt_jump_table_.length(); i++) { |
328 __ bind(&deopt_jump_table_[i].label); | 305 __ bind(&deopt_jump_table_[i].label); |
329 Address entry = deopt_jump_table_[i].address; | 306 __ ldr(pc, MemOperand(pc, Assembler::kInstrSize - Assembler::kPcLoadDelta)); |
330 if (deopt_jump_table_[i].needs_frame) { | 307 __ dd(reinterpret_cast<uint32_t>(deopt_jump_table_[i].address)); |
331 __ mov(ip, Operand(ExternalReference::ForDeoptEntry(entry))); | |
332 if (deopt_jump_table_[i].is_lazy_deopt) { | |
333 if (needs_frame_is_call.is_bound()) { | |
334 __ b(&needs_frame_is_call); | |
335 } else { | |
336 __ bind(&needs_frame_is_call); | |
337 __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); | |
338 // This variant of deopt can only be used with stubs. Since we don't | |
339 // have a function pointer to install in the stack frame that we're | |
340 // building, install a special marker there instead. | |
341 ASSERT(info()->IsStub()); | |
342 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); | |
343 __ push(scratch0()); | |
344 __ add(fp, sp, Operand(2 * kPointerSize)); | |
345 __ mov(lr, Operand(pc), LeaveCC, al); | |
346 __ mov(pc, ip); | |
347 } | |
348 } else { | |
349 if (needs_frame_not_call.is_bound()) { | |
350 __ b(&needs_frame_not_call); | |
351 } else { | |
352 __ bind(&needs_frame_not_call); | |
353 __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); | |
354 // This variant of deopt can only be used with stubs. Since we don't | |
355 // have a function pointer to install in the stack frame that we're | |
356 // building, install a special marker there instead. | |
357 ASSERT(info()->IsStub()); | |
358 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); | |
359 __ push(scratch0()); | |
360 __ add(fp, sp, Operand(2 * kPointerSize)); | |
361 __ mov(pc, ip); | |
362 } | |
363 } | |
364 } else { | |
365 if (deopt_jump_table_[i].is_lazy_deopt) { | |
366 __ mov(lr, Operand(pc), LeaveCC, al); | |
367 __ mov(pc, Operand(ExternalReference::ForDeoptEntry(entry))); | |
368 } else { | |
369 __ mov(pc, Operand(ExternalReference::ForDeoptEntry(entry))); | |
370 } | |
371 } | |
372 masm()->CheckConstPool(false, false); | |
373 } | 308 } |
| 309 ASSERT(masm()->InstructionsGeneratedSince(&table_start) == |
| 310 deopt_jump_table_.length() * 2); |
374 __ RecordComment("]"); | 311 __ RecordComment("]"); |
375 | 312 |
376 // Force constant pool emission at the end of the deopt jump table to make | |
377 // sure that no constant pools are emitted after. | |
378 masm()->CheckConstPool(true, false); | |
379 | |
380 // The deoptimization jump table is the last part of the instruction | 313 // The deoptimization jump table is the last part of the instruction |
381 // sequence. Mark the generated code as done unless we bailed out. | 314 // sequence. Mark the generated code as done unless we bailed out. |
382 if (!is_aborted()) status_ = DONE; | 315 if (!is_aborted()) status_ = DONE; |
383 return !is_aborted(); | 316 return !is_aborted(); |
384 } | 317 } |
385 | 318 |
386 | 319 |
387 bool LCodeGen::GenerateSafepointTable() { | 320 bool LCodeGen::GenerateSafepointTable() { |
388 ASSERT(is_done()); | 321 ASSERT(is_done()); |
389 safepoints_.Emit(masm(), GetStackSlotCount()); | 322 safepoints_.Emit(masm(), GetStackSlotCount()); |
390 return !is_aborted(); | 323 return !is_aborted(); |
391 } | 324 } |
392 | 325 |
393 | 326 |
394 Register LCodeGen::ToRegister(int index) const { | 327 Register LCodeGen::ToRegister(int index) const { |
395 return Register::FromAllocationIndex(index); | 328 return Register::FromAllocationIndex(index); |
396 } | 329 } |
397 | 330 |
398 | 331 |
399 DwVfpRegister LCodeGen::ToDoubleRegister(int index) const { | 332 DoubleRegister LCodeGen::ToDoubleRegister(int index) const { |
400 return DwVfpRegister::FromAllocationIndex(index); | 333 return DoubleRegister::FromAllocationIndex(index); |
401 } | 334 } |
402 | 335 |
403 | 336 |
404 Register LCodeGen::ToRegister(LOperand* op) const { | 337 Register LCodeGen::ToRegister(LOperand* op) const { |
405 ASSERT(op->IsRegister()); | 338 ASSERT(op->IsRegister()); |
406 return ToRegister(op->index()); | 339 return ToRegister(op->index()); |
407 } | 340 } |
408 | 341 |
409 | 342 |
410 Register LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) { | 343 Register LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) { |
(...skipping 20 matching lines...) Expand all Loading... |
431 return scratch; | 364 return scratch; |
432 } else if (op->IsStackSlot() || op->IsArgument()) { | 365 } else if (op->IsStackSlot() || op->IsArgument()) { |
433 __ ldr(scratch, ToMemOperand(op)); | 366 __ ldr(scratch, ToMemOperand(op)); |
434 return scratch; | 367 return scratch; |
435 } | 368 } |
436 UNREACHABLE(); | 369 UNREACHABLE(); |
437 return scratch; | 370 return scratch; |
438 } | 371 } |
439 | 372 |
440 | 373 |
441 DwVfpRegister LCodeGen::ToDoubleRegister(LOperand* op) const { | 374 DoubleRegister LCodeGen::ToDoubleRegister(LOperand* op) const { |
442 ASSERT(op->IsDoubleRegister()); | 375 ASSERT(op->IsDoubleRegister()); |
443 return ToDoubleRegister(op->index()); | 376 return ToDoubleRegister(op->index()); |
444 } | 377 } |
445 | 378 |
446 | 379 |
447 DwVfpRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op, | 380 DoubleRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op, |
448 SwVfpRegister flt_scratch, | 381 SwVfpRegister flt_scratch, |
449 DwVfpRegister dbl_scratch) { | 382 DoubleRegister dbl_scratch) { |
450 if (op->IsDoubleRegister()) { | 383 if (op->IsDoubleRegister()) { |
451 return ToDoubleRegister(op->index()); | 384 return ToDoubleRegister(op->index()); |
452 } else if (op->IsConstantOperand()) { | 385 } else if (op->IsConstantOperand()) { |
453 LConstantOperand* const_op = LConstantOperand::cast(op); | 386 LConstantOperand* const_op = LConstantOperand::cast(op); |
454 HConstant* constant = chunk_->LookupConstant(const_op); | 387 HConstant* constant = chunk_->LookupConstant(const_op); |
455 Handle<Object> literal = constant->handle(); | 388 Handle<Object> literal = constant->handle(); |
456 Representation r = chunk_->LookupLiteralRepresentation(const_op); | 389 Representation r = chunk_->LookupLiteralRepresentation(const_op); |
457 if (r.IsInteger32()) { | 390 if (r.IsInteger32()) { |
458 ASSERT(literal->IsNumber()); | 391 ASSERT(literal->IsNumber()); |
459 __ mov(ip, Operand(static_cast<int32_t>(literal->Number()))); | 392 __ mov(ip, Operand(static_cast<int32_t>(literal->Number()))); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 // arguments index points to the first element of a sequence of tagged | 508 // arguments index points to the first element of a sequence of tagged |
576 // values on the stack that represent the arguments. This needs to be | 509 // values on the stack that represent the arguments. This needs to be |
577 // kept in sync with the LArgumentsElements implementation. | 510 // kept in sync with the LArgumentsElements implementation. |
578 *arguments_index = -environment->parameter_count(); | 511 *arguments_index = -environment->parameter_count(); |
579 *arguments_count = environment->parameter_count(); | 512 *arguments_count = environment->parameter_count(); |
580 | 513 |
581 WriteTranslation(environment->outer(), | 514 WriteTranslation(environment->outer(), |
582 translation, | 515 translation, |
583 arguments_index, | 516 arguments_index, |
584 arguments_count); | 517 arguments_count); |
585 bool has_closure_id = !info()->closure().is_null() && | 518 int closure_id = *info()->closure() != *environment->closure() |
586 *info()->closure() != *environment->closure(); | |
587 int closure_id = has_closure_id | |
588 ? DefineDeoptimizationLiteral(environment->closure()) | 519 ? DefineDeoptimizationLiteral(environment->closure()) |
589 : Translation::kSelfLiteralId; | 520 : Translation::kSelfLiteralId; |
590 | 521 |
591 switch (environment->frame_type()) { | 522 switch (environment->frame_type()) { |
592 case JS_FUNCTION: | 523 case JS_FUNCTION: |
593 translation->BeginJSFrame(environment->ast_id(), closure_id, height); | 524 translation->BeginJSFrame(environment->ast_id(), closure_id, height); |
594 break; | 525 break; |
595 case JS_CONSTRUCT: | 526 case JS_CONSTRUCT: |
596 translation->BeginConstructStubFrame(closure_id, translation_size); | 527 translation->BeginConstructStubFrame(closure_id, translation_size); |
597 break; | 528 break; |
598 case JS_GETTER: | 529 case JS_GETTER: |
599 ASSERT(translation_size == 1); | 530 ASSERT(translation_size == 1); |
600 ASSERT(height == 0); | 531 ASSERT(height == 0); |
601 translation->BeginGetterStubFrame(closure_id); | 532 translation->BeginGetterStubFrame(closure_id); |
602 break; | 533 break; |
603 case JS_SETTER: | 534 case JS_SETTER: |
604 ASSERT(translation_size == 2); | 535 ASSERT(translation_size == 2); |
605 ASSERT(height == 0); | 536 ASSERT(height == 0); |
606 translation->BeginSetterStubFrame(closure_id); | 537 translation->BeginSetterStubFrame(closure_id); |
607 break; | 538 break; |
608 case STUB: | |
609 translation->BeginCompiledStubFrame(); | |
610 break; | |
611 case ARGUMENTS_ADAPTOR: | 539 case ARGUMENTS_ADAPTOR: |
612 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); | 540 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); |
613 break; | 541 break; |
614 } | 542 } |
615 | 543 |
616 // Inlined frames which push their arguments cause the index to be | 544 // Inlined frames which push their arguments cause the index to be |
617 // bumped and a new stack area to be used for materialization. | 545 // bumped and a new stack area to be used for materialization. |
618 if (environment->entry() != NULL && | 546 if (environment->entry() != NULL && |
619 environment->entry()->arguments_pushed()) { | 547 environment->entry()->arguments_pushed()) { |
620 *arguments_index = *arguments_index < 0 | 548 *arguments_index = *arguments_index < 0 |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
796 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); | 724 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); |
797 deoptimizations_.Add(environment, zone()); | 725 deoptimizations_.Add(environment, zone()); |
798 } | 726 } |
799 } | 727 } |
800 | 728 |
801 | 729 |
802 void LCodeGen::DeoptimizeIf(Condition cc, LEnvironment* environment) { | 730 void LCodeGen::DeoptimizeIf(Condition cc, LEnvironment* environment) { |
803 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 731 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
804 ASSERT(environment->HasBeenRegistered()); | 732 ASSERT(environment->HasBeenRegistered()); |
805 int id = environment->deoptimization_index(); | 733 int id = environment->deoptimization_index(); |
806 | 734 Address entry = Deoptimizer::GetDeoptimizationEntry(id, Deoptimizer::EAGER); |
807 Deoptimizer::BailoutType bailout_type = info()->IsStub() | |
808 ? Deoptimizer::LAZY | |
809 : Deoptimizer::EAGER; | |
810 Address entry = Deoptimizer::GetDeoptimizationEntry(id, bailout_type); | |
811 if (entry == NULL) { | 735 if (entry == NULL) { |
812 Abort("bailout was not prepared"); | 736 Abort("bailout was not prepared"); |
813 return; | 737 return; |
814 } | 738 } |
815 | 739 |
816 ASSERT(FLAG_deopt_every_n_times < 2); // Other values not supported on ARM. | 740 ASSERT(FLAG_deopt_every_n_times < 2); // Other values not supported on ARM. |
817 | 741 |
818 if (FLAG_deopt_every_n_times == 1 && | 742 if (FLAG_deopt_every_n_times == 1 && |
819 info_->shared_info()->opt_count() == id) { | 743 info_->shared_info()->opt_count() == id) { |
820 __ Jump(entry, RelocInfo::RUNTIME_ENTRY); | 744 __ Jump(entry, RelocInfo::RUNTIME_ENTRY); |
821 return; | 745 return; |
822 } | 746 } |
823 | 747 |
824 if (FLAG_trap_on_deopt) __ stop("trap_on_deopt", cc); | 748 if (FLAG_trap_on_deopt) __ stop("trap_on_deopt", cc); |
825 | 749 |
826 bool needs_lazy_deopt = info()->IsStub(); | 750 if (cc == al) { |
827 ASSERT(info()->IsStub() || frame_is_built_); | |
828 if (cc == al && !needs_lazy_deopt) { | |
829 __ Jump(entry, RelocInfo::RUNTIME_ENTRY); | 751 __ Jump(entry, RelocInfo::RUNTIME_ENTRY); |
830 } else { | 752 } else { |
831 // We often have several deopts to the same entry, reuse the last | 753 // We often have several deopts to the same entry, reuse the last |
832 // jump entry if this is the case. | 754 // jump entry if this is the case. |
833 if (deopt_jump_table_.is_empty() || | 755 if (deopt_jump_table_.is_empty() || |
834 (deopt_jump_table_.last().address != entry) || | 756 (deopt_jump_table_.last().address != entry)) { |
835 (deopt_jump_table_.last().is_lazy_deopt != needs_lazy_deopt) || | 757 deopt_jump_table_.Add(JumpTableEntry(entry), zone()); |
836 (deopt_jump_table_.last().needs_frame != !frame_is_built_)) { | |
837 JumpTableEntry table_entry(entry, !frame_is_built_, needs_lazy_deopt); | |
838 deopt_jump_table_.Add(table_entry, zone()); | |
839 } | 758 } |
840 __ b(cc, &deopt_jump_table_.last().label); | 759 __ b(cc, &deopt_jump_table_.last().label); |
841 } | 760 } |
842 } | 761 } |
843 | 762 |
844 | 763 |
845 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 764 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
846 int length = deoptimizations_.length(); | 765 int length = deoptimizations_.length(); |
847 if (length == 0) return; | 766 if (length == 0) return; |
848 Handle<DeoptimizationInputData> data = | 767 Handle<DeoptimizationInputData> data = |
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1437 __ cmp(remainder, Operand(0)); | 1356 __ cmp(remainder, Operand(0)); |
1438 __ teq(remainder, Operand(divisor), ne); | 1357 __ teq(remainder, Operand(divisor), ne); |
1439 __ sub(result, result, Operand(1), LeaveCC, mi); | 1358 __ sub(result, result, Operand(1), LeaveCC, mi); |
1440 } | 1359 } |
1441 | 1360 |
1442 | 1361 |
1443 void LCodeGen::DoDeferredBinaryOpStub(LPointerMap* pointer_map, | 1362 void LCodeGen::DoDeferredBinaryOpStub(LPointerMap* pointer_map, |
1444 LOperand* left_argument, | 1363 LOperand* left_argument, |
1445 LOperand* right_argument, | 1364 LOperand* right_argument, |
1446 Token::Value op) { | 1365 Token::Value op) { |
1447 CpuFeatures::Scope vfp_scope(VFP2); | |
1448 Register left = ToRegister(left_argument); | 1366 Register left = ToRegister(left_argument); |
1449 Register right = ToRegister(right_argument); | 1367 Register right = ToRegister(right_argument); |
1450 | 1368 |
1451 PushSafepointRegistersScope scope(this, Safepoint::kWithRegistersAndDoubles); | 1369 PushSafepointRegistersScope scope(this, Safepoint::kWithRegistersAndDoubles); |
1452 // Move left to r1 and right to r0 for the stub call. | 1370 // Move left to r1 and right to r0 for the stub call. |
1453 if (left.is(r1)) { | 1371 if (left.is(r1)) { |
1454 __ Move(r0, right); | 1372 __ Move(r0, right); |
1455 } else if (left.is(r0) && right.is(r1)) { | 1373 } else if (left.is(r0) && right.is(r1)) { |
1456 __ Swap(r0, r1, r2); | 1374 __ Swap(r0, r1, r2); |
1457 } else if (left.is(r0)) { | 1375 } else if (left.is(r0)) { |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1723 | 1641 |
1724 void LCodeGen::DoConstantI(LConstantI* instr) { | 1642 void LCodeGen::DoConstantI(LConstantI* instr) { |
1725 ASSERT(instr->result()->IsRegister()); | 1643 ASSERT(instr->result()->IsRegister()); |
1726 __ mov(ToRegister(instr->result()), Operand(instr->value())); | 1644 __ mov(ToRegister(instr->result()), Operand(instr->value())); |
1727 } | 1645 } |
1728 | 1646 |
1729 | 1647 |
1730 void LCodeGen::DoConstantD(LConstantD* instr) { | 1648 void LCodeGen::DoConstantD(LConstantD* instr) { |
1731 ASSERT(instr->result()->IsDoubleRegister()); | 1649 ASSERT(instr->result()->IsDoubleRegister()); |
1732 DwVfpRegister result = ToDoubleRegister(instr->result()); | 1650 DwVfpRegister result = ToDoubleRegister(instr->result()); |
1733 CpuFeatures::Scope scope(VFP2); | |
1734 double v = instr->value(); | 1651 double v = instr->value(); |
1735 __ Vmov(result, v, scratch0()); | 1652 __ Vmov(result, v, scratch0()); |
1736 } | 1653 } |
1737 | 1654 |
1738 | 1655 |
1739 void LCodeGen::DoConstantT(LConstantT* instr) { | 1656 void LCodeGen::DoConstantT(LConstantT* instr) { |
1740 Handle<Object> value = instr->value(); | 1657 Handle<Object> value = instr->value(); |
1741 if (value->IsSmi()) { | 1658 if (value->IsSmi()) { |
1742 __ mov(ToRegister(instr->result()), Operand(value)); | 1659 __ mov(ToRegister(instr->result()), Operand(value)); |
1743 } else { | 1660 } else { |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1892 ? ToOperand(right) | 1809 ? ToOperand(right) |
1893 : Operand(EmitLoadRegister(right, ip)); | 1810 : Operand(EmitLoadRegister(right, ip)); |
1894 Register result_reg = ToRegister(instr->result()); | 1811 Register result_reg = ToRegister(instr->result()); |
1895 __ cmp(left_reg, right_op); | 1812 __ cmp(left_reg, right_op); |
1896 if (!result_reg.is(left_reg)) { | 1813 if (!result_reg.is(left_reg)) { |
1897 __ mov(result_reg, left_reg, LeaveCC, condition); | 1814 __ mov(result_reg, left_reg, LeaveCC, condition); |
1898 } | 1815 } |
1899 __ mov(result_reg, right_op, LeaveCC, NegateCondition(condition)); | 1816 __ mov(result_reg, right_op, LeaveCC, NegateCondition(condition)); |
1900 } else { | 1817 } else { |
1901 ASSERT(instr->hydrogen()->representation().IsDouble()); | 1818 ASSERT(instr->hydrogen()->representation().IsDouble()); |
1902 CpuFeatures::Scope scope(VFP2); | 1819 DoubleRegister left_reg = ToDoubleRegister(left); |
1903 DwVfpRegister left_reg = ToDoubleRegister(left); | 1820 DoubleRegister right_reg = ToDoubleRegister(right); |
1904 DwVfpRegister right_reg = ToDoubleRegister(right); | 1821 DoubleRegister result_reg = ToDoubleRegister(instr->result()); |
1905 DwVfpRegister result_reg = ToDoubleRegister(instr->result()); | |
1906 Label check_nan_left, check_zero, return_left, return_right, done; | 1822 Label check_nan_left, check_zero, return_left, return_right, done; |
1907 __ VFPCompareAndSetFlags(left_reg, right_reg); | 1823 __ VFPCompareAndSetFlags(left_reg, right_reg); |
1908 __ b(vs, &check_nan_left); | 1824 __ b(vs, &check_nan_left); |
1909 __ b(eq, &check_zero); | 1825 __ b(eq, &check_zero); |
1910 __ b(condition, &return_left); | 1826 __ b(condition, &return_left); |
1911 __ b(al, &return_right); | 1827 __ b(al, &return_right); |
1912 | 1828 |
1913 __ bind(&check_zero); | 1829 __ bind(&check_zero); |
1914 __ VFPCompareAndSetFlags(left_reg, 0.0); | 1830 __ VFPCompareAndSetFlags(left_reg, 0.0); |
1915 __ b(ne, &return_left); // left == right != 0. | 1831 __ b(ne, &return_left); // left == right != 0. |
(...skipping 22 matching lines...) Expand all Loading... |
1938 __ bind(&return_left); | 1854 __ bind(&return_left); |
1939 if (!left_reg.is(result_reg)) { | 1855 if (!left_reg.is(result_reg)) { |
1940 __ vmov(result_reg, left_reg); | 1856 __ vmov(result_reg, left_reg); |
1941 } | 1857 } |
1942 __ bind(&done); | 1858 __ bind(&done); |
1943 } | 1859 } |
1944 } | 1860 } |
1945 | 1861 |
1946 | 1862 |
1947 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 1863 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
1948 CpuFeatures::Scope scope(VFP2); | 1864 DoubleRegister left = ToDoubleRegister(instr->left()); |
1949 DwVfpRegister left = ToDoubleRegister(instr->left()); | 1865 DoubleRegister right = ToDoubleRegister(instr->right()); |
1950 DwVfpRegister right = ToDoubleRegister(instr->right()); | 1866 DoubleRegister result = ToDoubleRegister(instr->result()); |
1951 DwVfpRegister result = ToDoubleRegister(instr->result()); | |
1952 switch (instr->op()) { | 1867 switch (instr->op()) { |
1953 case Token::ADD: | 1868 case Token::ADD: |
1954 __ vadd(result, left, right); | 1869 __ vadd(result, left, right); |
1955 break; | 1870 break; |
1956 case Token::SUB: | 1871 case Token::SUB: |
1957 __ vsub(result, left, right); | 1872 __ vsub(result, left, right); |
1958 break; | 1873 break; |
1959 case Token::MUL: | 1874 case Token::MUL: |
1960 __ vmul(result, left, right); | 1875 __ vmul(result, left, right); |
1961 break; | 1876 break; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2029 void LCodeGen::DoBranch(LBranch* instr) { | 1944 void LCodeGen::DoBranch(LBranch* instr) { |
2030 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1945 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2031 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1946 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2032 | 1947 |
2033 Representation r = instr->hydrogen()->value()->representation(); | 1948 Representation r = instr->hydrogen()->value()->representation(); |
2034 if (r.IsInteger32()) { | 1949 if (r.IsInteger32()) { |
2035 Register reg = ToRegister(instr->value()); | 1950 Register reg = ToRegister(instr->value()); |
2036 __ cmp(reg, Operand(0)); | 1951 __ cmp(reg, Operand(0)); |
2037 EmitBranch(true_block, false_block, ne); | 1952 EmitBranch(true_block, false_block, ne); |
2038 } else if (r.IsDouble()) { | 1953 } else if (r.IsDouble()) { |
2039 CpuFeatures::Scope scope(VFP2); | 1954 DoubleRegister reg = ToDoubleRegister(instr->value()); |
2040 DwVfpRegister reg = ToDoubleRegister(instr->value()); | |
2041 Register scratch = scratch0(); | 1955 Register scratch = scratch0(); |
2042 | 1956 |
2043 // Test the double value. Zero and NaN are false. | 1957 // Test the double value. Zero and NaN are false. |
2044 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); | 1958 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); |
2045 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); | 1959 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); |
2046 EmitBranch(true_block, false_block, eq); | 1960 EmitBranch(true_block, false_block, eq); |
2047 } else { | 1961 } else { |
2048 ASSERT(r.IsTagged()); | 1962 ASSERT(r.IsTagged()); |
2049 Register reg = ToRegister(instr->value()); | 1963 Register reg = ToRegister(instr->value()); |
2050 HType type = instr->hydrogen()->value()->type(); | 1964 HType type = instr->hydrogen()->value()->type(); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2115 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); | 2029 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); |
2116 __ b(ge, ¬_string); | 2030 __ b(ge, ¬_string); |
2117 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset)); | 2031 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset)); |
2118 __ cmp(ip, Operand(0)); | 2032 __ cmp(ip, Operand(0)); |
2119 __ b(ne, true_label); | 2033 __ b(ne, true_label); |
2120 __ b(false_label); | 2034 __ b(false_label); |
2121 __ bind(¬_string); | 2035 __ bind(¬_string); |
2122 } | 2036 } |
2123 | 2037 |
2124 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | 2038 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { |
2125 CpuFeatures::Scope scope(VFP2); | |
2126 // heap number -> false iff +0, -0, or NaN. | 2039 // heap number -> false iff +0, -0, or NaN. |
2127 DwVfpRegister dbl_scratch = double_scratch0(); | 2040 DoubleRegister dbl_scratch = double_scratch0(); |
2128 Label not_heap_number; | 2041 Label not_heap_number; |
2129 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | 2042 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
2130 __ b(ne, ¬_heap_number); | 2043 __ b(ne, ¬_heap_number); |
2131 __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); | 2044 __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); |
2132 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); | 2045 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); |
2133 __ b(vs, false_label); // NaN -> false. | 2046 __ b(vs, false_label); // NaN -> false. |
2134 __ b(eq, false_label); // +0, -0 -> false. | 2047 __ b(eq, false_label); // +0, -0 -> false. |
2135 __ b(true_label); | 2048 __ b(true_label); |
2136 __ bind(¬_heap_number); | 2049 __ bind(¬_heap_number); |
2137 } | 2050 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2195 if (left->IsConstantOperand() && right->IsConstantOperand()) { | 2108 if (left->IsConstantOperand() && right->IsConstantOperand()) { |
2196 // We can statically evaluate the comparison. | 2109 // We can statically evaluate the comparison. |
2197 double left_val = ToDouble(LConstantOperand::cast(left)); | 2110 double left_val = ToDouble(LConstantOperand::cast(left)); |
2198 double right_val = ToDouble(LConstantOperand::cast(right)); | 2111 double right_val = ToDouble(LConstantOperand::cast(right)); |
2199 int next_block = | 2112 int next_block = |
2200 EvalComparison(instr->op(), left_val, right_val) ? true_block | 2113 EvalComparison(instr->op(), left_val, right_val) ? true_block |
2201 : false_block; | 2114 : false_block; |
2202 EmitGoto(next_block); | 2115 EmitGoto(next_block); |
2203 } else { | 2116 } else { |
2204 if (instr->is_double()) { | 2117 if (instr->is_double()) { |
2205 CpuFeatures::Scope scope(VFP2); | |
2206 // Compare left and right operands as doubles and load the | 2118 // Compare left and right operands as doubles and load the |
2207 // resulting flags into the normal status register. | 2119 // resulting flags into the normal status register. |
2208 __ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right)); | 2120 __ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right)); |
2209 // If a NaN is involved, i.e. the result is unordered (V set), | 2121 // If a NaN is involved, i.e. the result is unordered (V set), |
2210 // jump to false block label. | 2122 // jump to false block label. |
2211 __ b(vs, chunk_->GetAssemblyLabel(false_block)); | 2123 __ b(vs, chunk_->GetAssemblyLabel(false_block)); |
2212 } else { | 2124 } else { |
2213 if (right->IsConstantOperand()) { | 2125 if (right->IsConstantOperand()) { |
2214 __ cmp(ToRegister(left), | 2126 __ cmp(ToRegister(left), |
2215 Operand(ToInteger32(LConstantOperand::cast(right)))); | 2127 Operand(ToInteger32(LConstantOperand::cast(right)))); |
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2734 __ LoadRoot(ToRegister(instr->result()), | 2646 __ LoadRoot(ToRegister(instr->result()), |
2735 Heap::kTrueValueRootIndex, | 2647 Heap::kTrueValueRootIndex, |
2736 condition); | 2648 condition); |
2737 __ LoadRoot(ToRegister(instr->result()), | 2649 __ LoadRoot(ToRegister(instr->result()), |
2738 Heap::kFalseValueRootIndex, | 2650 Heap::kFalseValueRootIndex, |
2739 NegateCondition(condition)); | 2651 NegateCondition(condition)); |
2740 } | 2652 } |
2741 | 2653 |
2742 | 2654 |
2743 void LCodeGen::DoReturn(LReturn* instr) { | 2655 void LCodeGen::DoReturn(LReturn* instr) { |
2744 if (FLAG_trace && info()->IsOptimizing()) { | 2656 if (FLAG_trace) { |
2745 // Push the return value on the stack as the parameter. | 2657 // Push the return value on the stack as the parameter. |
2746 // Runtime::TraceExit returns its parameter in r0. | 2658 // Runtime::TraceExit returns its parameter in r0. |
2747 __ push(r0); | 2659 __ push(r0); |
2748 __ CallRuntime(Runtime::kTraceExit, 1); | 2660 __ CallRuntime(Runtime::kTraceExit, 1); |
2749 } | 2661 } |
2750 if (NeedsEagerFrame()) { | 2662 int32_t sp_delta = (GetParameterCount() + 1) * kPointerSize; |
2751 int32_t sp_delta = (GetParameterCount() + 1) * kPointerSize; | 2663 __ mov(sp, fp); |
2752 __ mov(sp, fp); | 2664 __ ldm(ia_w, sp, fp.bit() | lr.bit()); |
2753 __ ldm(ia_w, sp, fp.bit() | lr.bit()); | 2665 __ add(sp, sp, Operand(sp_delta)); |
2754 __ add(sp, sp, Operand(sp_delta)); | |
2755 } | |
2756 if (info()->IsStub()) { | |
2757 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
2758 } | |
2759 __ Jump(lr); | 2666 __ Jump(lr); |
2760 } | 2667 } |
2761 | 2668 |
2762 | 2669 |
2763 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { | 2670 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { |
2764 Register result = ToRegister(instr->result()); | 2671 Register result = ToRegister(instr->result()); |
2765 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell()))); | 2672 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell()))); |
2766 __ ldr(result, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); | 2673 __ ldr(result, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); |
2767 if (instr->hydrogen()->RequiresHoleCheck()) { | 2674 if (instr->hydrogen()->RequiresHoleCheck()) { |
2768 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 2675 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3098 } else { | 3005 } else { |
3099 key = ToRegister(instr->key()); | 3006 key = ToRegister(instr->key()); |
3100 } | 3007 } |
3101 int element_size_shift = ElementsKindToShiftSize(elements_kind); | 3008 int element_size_shift = ElementsKindToShiftSize(elements_kind); |
3102 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) | 3009 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) |
3103 ? (element_size_shift - kSmiTagSize) : element_size_shift; | 3010 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
3104 int additional_offset = instr->additional_index() << element_size_shift; | 3011 int additional_offset = instr->additional_index() << element_size_shift; |
3105 | 3012 |
3106 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 3013 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || |
3107 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | 3014 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
| 3015 CpuFeatures::Scope scope(VFP3); |
3108 DwVfpRegister result = ToDoubleRegister(instr->result()); | 3016 DwVfpRegister result = ToDoubleRegister(instr->result()); |
3109 Operand operand = key_is_constant | 3017 Operand operand = key_is_constant |
3110 ? Operand(constant_key << element_size_shift) | 3018 ? Operand(constant_key << element_size_shift) |
3111 : Operand(key, LSL, shift_size); | 3019 : Operand(key, LSL, shift_size); |
3112 __ add(scratch0(), external_pointer, operand); | 3020 __ add(scratch0(), external_pointer, operand); |
3113 if (CpuFeatures::IsSupported(VFP2)) { | 3021 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { |
3114 CpuFeatures::Scope scope(VFP2); | 3022 __ vldr(result.low(), scratch0(), additional_offset); |
3115 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | 3023 __ vcvt_f64_f32(result, result.low()); |
3116 __ vldr(result.low(), scratch0(), additional_offset); | 3024 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS |
3117 __ vcvt_f64_f32(result, result.low()); | 3025 __ vldr(result, scratch0(), additional_offset); |
3118 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS | |
3119 __ vldr(result, scratch0(), additional_offset); | |
3120 } | |
3121 } else { | |
3122 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | |
3123 Register value = external_pointer; | |
3124 __ ldr(value, MemOperand(scratch0(), additional_offset)); | |
3125 __ and_(sfpd_lo, value, Operand(kBinary32MantissaMask)); | |
3126 | |
3127 __ mov(scratch0(), Operand(value, LSR, kBinary32MantissaBits)); | |
3128 __ and_(scratch0(), scratch0(), | |
3129 Operand(kBinary32ExponentMask >> kBinary32MantissaBits)); | |
3130 | |
3131 Label exponent_rebiased; | |
3132 __ teq(scratch0(), Operand(0x00)); | |
3133 __ b(eq, &exponent_rebiased); | |
3134 | |
3135 __ teq(scratch0(), Operand(0xff)); | |
3136 __ mov(scratch0(), Operand(0x7ff), LeaveCC, eq); | |
3137 __ b(eq, &exponent_rebiased); | |
3138 | |
3139 // Rebias exponent. | |
3140 __ add(scratch0(), | |
3141 scratch0(), | |
3142 Operand(-kBinary32ExponentBias + HeapNumber::kExponentBias)); | |
3143 | |
3144 __ bind(&exponent_rebiased); | |
3145 __ and_(sfpd_hi, value, Operand(kBinary32SignMask)); | |
3146 __ orr(sfpd_hi, sfpd_hi, | |
3147 Operand(scratch0(), LSL, HeapNumber::kMantissaBitsInTopWord)); | |
3148 | |
3149 // Shift mantissa. | |
3150 static const int kMantissaShiftForHiWord = | |
3151 kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord; | |
3152 | |
3153 static const int kMantissaShiftForLoWord = | |
3154 kBitsPerInt - kMantissaShiftForHiWord; | |
3155 | |
3156 __ orr(sfpd_hi, sfpd_hi, | |
3157 Operand(sfpd_lo, LSR, kMantissaShiftForHiWord)); | |
3158 __ mov(sfpd_lo, Operand(sfpd_lo, LSL, kMantissaShiftForLoWord)); | |
3159 | |
3160 } else { | |
3161 __ ldr(sfpd_lo, MemOperand(scratch0(), additional_offset)); | |
3162 __ ldr(sfpd_hi, MemOperand(scratch0(), | |
3163 additional_offset + kPointerSize)); | |
3164 } | |
3165 } | 3026 } |
3166 } else { | 3027 } else { |
3167 Register result = ToRegister(instr->result()); | 3028 Register result = ToRegister(instr->result()); |
3168 MemOperand mem_operand = PrepareKeyedOperand( | 3029 MemOperand mem_operand = PrepareKeyedOperand( |
3169 key, external_pointer, key_is_constant, constant_key, | 3030 key, external_pointer, key_is_constant, constant_key, |
3170 element_size_shift, shift_size, | 3031 element_size_shift, shift_size, |
3171 instr->additional_index(), additional_offset); | 3032 instr->additional_index(), additional_offset); |
3172 switch (elements_kind) { | 3033 switch (elements_kind) { |
3173 case EXTERNAL_BYTE_ELEMENTS: | 3034 case EXTERNAL_BYTE_ELEMENTS: |
3174 __ ldrsb(result, mem_operand); | 3035 __ ldrsb(result, mem_operand); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3223 int constant_key = 0; | 3084 int constant_key = 0; |
3224 if (key_is_constant) { | 3085 if (key_is_constant) { |
3225 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 3086 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
3226 if (constant_key & 0xF0000000) { | 3087 if (constant_key & 0xF0000000) { |
3227 Abort("array index constant value too big."); | 3088 Abort("array index constant value too big."); |
3228 } | 3089 } |
3229 } else { | 3090 } else { |
3230 key = ToRegister(instr->key()); | 3091 key = ToRegister(instr->key()); |
3231 } | 3092 } |
3232 | 3093 |
3233 int base_offset = (FixedDoubleArray::kHeaderSize - kHeapObjectTag) + | 3094 Operand operand = key_is_constant |
3234 ((constant_key + instr->additional_index()) << element_size_shift); | 3095 ? Operand(((constant_key + instr->additional_index()) << |
| 3096 element_size_shift) + |
| 3097 FixedDoubleArray::kHeaderSize - kHeapObjectTag) |
| 3098 : Operand(key, LSL, shift_size); |
| 3099 __ add(elements, elements, operand); |
3235 if (!key_is_constant) { | 3100 if (!key_is_constant) { |
3236 __ add(elements, elements, Operand(key, LSL, shift_size)); | 3101 __ add(elements, elements, |
| 3102 Operand((FixedDoubleArray::kHeaderSize - kHeapObjectTag) + |
| 3103 (instr->additional_index() << element_size_shift))); |
3237 } | 3104 } |
3238 if (CpuFeatures::IsSupported(VFP2)) { | 3105 |
3239 CpuFeatures::Scope scope(VFP2); | 3106 __ vldr(result, elements, 0); |
3240 __ add(elements, elements, Operand(base_offset)); | 3107 if (instr->hydrogen()->RequiresHoleCheck()) { |
3241 __ vldr(result, elements, 0); | 3108 __ ldr(scratch, MemOperand(elements, sizeof(kHoleNanLower32))); |
3242 if (instr->hydrogen()->RequiresHoleCheck()) { | 3109 __ cmp(scratch, Operand(kHoleNanUpper32)); |
3243 __ ldr(scratch, MemOperand(elements, sizeof(kHoleNanLower32))); | 3110 DeoptimizeIf(eq, instr->environment()); |
3244 __ cmp(scratch, Operand(kHoleNanUpper32)); | |
3245 DeoptimizeIf(eq, instr->environment()); | |
3246 } | |
3247 } else { | |
3248 __ ldr(sfpd_hi, MemOperand(elements, base_offset + kPointerSize)); | |
3249 __ ldr(sfpd_lo, MemOperand(elements, base_offset)); | |
3250 if (instr->hydrogen()->RequiresHoleCheck()) { | |
3251 ASSERT(kPointerSize == sizeof(kHoleNanLower32)); | |
3252 __ cmp(sfpd_hi, Operand(kHoleNanUpper32)); | |
3253 DeoptimizeIf(eq, instr->environment()); | |
3254 } | |
3255 } | 3111 } |
3256 } | 3112 } |
3257 | 3113 |
3258 | 3114 |
3259 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { | 3115 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
3260 Register elements = ToRegister(instr->elements()); | 3116 Register elements = ToRegister(instr->elements()); |
3261 Register result = ToRegister(instr->result()); | 3117 Register result = ToRegister(instr->result()); |
3262 Register scratch = scratch0(); | 3118 Register scratch = scratch0(); |
3263 Register store_base = scratch; | 3119 Register store_base = scratch; |
3264 int offset = 0; | 3120 int offset = 0; |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3680 // We can make rsb conditional because the previous cmp instruction | 3536 // We can make rsb conditional because the previous cmp instruction |
3681 // will clear the V (overflow) flag and rsb won't set this flag | 3537 // will clear the V (overflow) flag and rsb won't set this flag |
3682 // if input is positive. | 3538 // if input is positive. |
3683 __ rsb(result, input, Operand(0), SetCC, mi); | 3539 __ rsb(result, input, Operand(0), SetCC, mi); |
3684 // Deoptimize on overflow. | 3540 // Deoptimize on overflow. |
3685 DeoptimizeIf(vs, instr->environment()); | 3541 DeoptimizeIf(vs, instr->environment()); |
3686 } | 3542 } |
3687 | 3543 |
3688 | 3544 |
3689 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 3545 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
3690 CpuFeatures::Scope scope(VFP2); | |
3691 // Class for deferred case. | 3546 // Class for deferred case. |
3692 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 3547 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
3693 public: | 3548 public: |
3694 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 3549 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
3695 LUnaryMathOperation* instr) | 3550 LUnaryMathOperation* instr) |
3696 : LDeferredCode(codegen), instr_(instr) { } | 3551 : LDeferredCode(codegen), instr_(instr) { } |
3697 virtual void Generate() { | 3552 virtual void Generate() { |
3698 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 3553 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
3699 } | 3554 } |
3700 virtual LInstruction* instr() { return instr_; } | 3555 virtual LInstruction* instr() { return instr_; } |
(...skipping 16 matching lines...) Expand all Loading... |
3717 // Smi check. | 3572 // Smi check. |
3718 __ JumpIfNotSmi(input, deferred->entry()); | 3573 __ JumpIfNotSmi(input, deferred->entry()); |
3719 // If smi, handle it directly. | 3574 // If smi, handle it directly. |
3720 EmitIntegerMathAbs(instr); | 3575 EmitIntegerMathAbs(instr); |
3721 __ bind(deferred->exit()); | 3576 __ bind(deferred->exit()); |
3722 } | 3577 } |
3723 } | 3578 } |
3724 | 3579 |
3725 | 3580 |
3726 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { | 3581 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
3727 CpuFeatures::Scope scope(VFP2); | 3582 DoubleRegister input = ToDoubleRegister(instr->value()); |
3728 DwVfpRegister input = ToDoubleRegister(instr->value()); | |
3729 Register result = ToRegister(instr->result()); | 3583 Register result = ToRegister(instr->result()); |
3730 Register scratch = scratch0(); | 3584 Register scratch = scratch0(); |
3731 | 3585 |
3732 __ EmitVFPTruncate(kRoundToMinusInf, | 3586 __ EmitVFPTruncate(kRoundToMinusInf, |
3733 result, | 3587 result, |
3734 input, | 3588 input, |
3735 scratch, | 3589 scratch, |
3736 double_scratch0()); | 3590 double_scratch0()); |
3737 DeoptimizeIf(ne, instr->environment()); | 3591 DeoptimizeIf(ne, instr->environment()); |
3738 | 3592 |
3739 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3593 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3740 // Test for -0. | 3594 // Test for -0. |
3741 Label done; | 3595 Label done; |
3742 __ cmp(result, Operand(0)); | 3596 __ cmp(result, Operand(0)); |
3743 __ b(ne, &done); | 3597 __ b(ne, &done); |
3744 __ vmov(scratch, input.high()); | 3598 __ vmov(scratch, input.high()); |
3745 __ tst(scratch, Operand(HeapNumber::kSignMask)); | 3599 __ tst(scratch, Operand(HeapNumber::kSignMask)); |
3746 DeoptimizeIf(ne, instr->environment()); | 3600 DeoptimizeIf(ne, instr->environment()); |
3747 __ bind(&done); | 3601 __ bind(&done); |
3748 } | 3602 } |
3749 } | 3603 } |
3750 | 3604 |
3751 | 3605 |
3752 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { | 3606 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
3753 CpuFeatures::Scope scope(VFP2); | 3607 DoubleRegister input = ToDoubleRegister(instr->value()); |
3754 DwVfpRegister input = ToDoubleRegister(instr->value()); | |
3755 Register result = ToRegister(instr->result()); | 3608 Register result = ToRegister(instr->result()); |
3756 DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp()); | 3609 DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp()); |
3757 Register scratch = scratch0(); | 3610 Register scratch = scratch0(); |
3758 Label done, check_sign_on_zero; | 3611 Label done, check_sign_on_zero; |
3759 | 3612 |
3760 // Extract exponent bits. | 3613 // Extract exponent bits. |
3761 __ vmov(result, input.high()); | 3614 __ vmov(result, input.high()); |
3762 __ ubfx(scratch, | 3615 __ ubfx(scratch, |
3763 result, | 3616 result, |
3764 HeapNumber::kExponentShift, | 3617 HeapNumber::kExponentShift, |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3809 __ bind(&check_sign_on_zero); | 3662 __ bind(&check_sign_on_zero); |
3810 __ vmov(scratch, input.high()); | 3663 __ vmov(scratch, input.high()); |
3811 __ tst(scratch, Operand(HeapNumber::kSignMask)); | 3664 __ tst(scratch, Operand(HeapNumber::kSignMask)); |
3812 DeoptimizeIf(ne, instr->environment()); | 3665 DeoptimizeIf(ne, instr->environment()); |
3813 } | 3666 } |
3814 __ bind(&done); | 3667 __ bind(&done); |
3815 } | 3668 } |
3816 | 3669 |
3817 | 3670 |
3818 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 3671 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
3819 CpuFeatures::Scope scope(VFP2); | 3672 DoubleRegister input = ToDoubleRegister(instr->value()); |
3820 DwVfpRegister input = ToDoubleRegister(instr->value()); | 3673 DoubleRegister result = ToDoubleRegister(instr->result()); |
3821 DwVfpRegister result = ToDoubleRegister(instr->result()); | |
3822 __ vsqrt(result, input); | 3674 __ vsqrt(result, input); |
3823 } | 3675 } |
3824 | 3676 |
3825 | 3677 |
3826 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { | 3678 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { |
3827 CpuFeatures::Scope scope(VFP2); | 3679 DoubleRegister input = ToDoubleRegister(instr->value()); |
3828 DwVfpRegister input = ToDoubleRegister(instr->value()); | 3680 DoubleRegister result = ToDoubleRegister(instr->result()); |
3829 DwVfpRegister result = ToDoubleRegister(instr->result()); | 3681 DoubleRegister temp = ToDoubleRegister(instr->temp()); |
3830 DwVfpRegister temp = ToDoubleRegister(instr->temp()); | |
3831 | 3682 |
3832 // Note that according to ECMA-262 15.8.2.13: | 3683 // Note that according to ECMA-262 15.8.2.13: |
3833 // Math.pow(-Infinity, 0.5) == Infinity | 3684 // Math.pow(-Infinity, 0.5) == Infinity |
3834 // Math.sqrt(-Infinity) == NaN | 3685 // Math.sqrt(-Infinity) == NaN |
3835 Label done; | 3686 Label done; |
3836 __ vmov(temp, -V8_INFINITY, scratch0()); | 3687 __ vmov(temp, -V8_INFINITY, scratch0()); |
3837 __ VFPCompareAndSetFlags(input, temp); | 3688 __ VFPCompareAndSetFlags(input, temp); |
3838 __ vneg(result, temp, eq); | 3689 __ vneg(result, temp, eq); |
3839 __ b(&done, eq); | 3690 __ b(&done, eq); |
3840 | 3691 |
3841 // Add +0 to convert -0 to +0. | 3692 // Add +0 to convert -0 to +0. |
3842 __ vadd(result, input, kDoubleRegZero); | 3693 __ vadd(result, input, kDoubleRegZero); |
3843 __ vsqrt(result, result); | 3694 __ vsqrt(result, result); |
3844 __ bind(&done); | 3695 __ bind(&done); |
3845 } | 3696 } |
3846 | 3697 |
3847 | 3698 |
3848 void LCodeGen::DoPower(LPower* instr) { | 3699 void LCodeGen::DoPower(LPower* instr) { |
3849 CpuFeatures::Scope scope(VFP2); | |
3850 Representation exponent_type = instr->hydrogen()->right()->representation(); | 3700 Representation exponent_type = instr->hydrogen()->right()->representation(); |
3851 // Having marked this as a call, we can use any registers. | 3701 // Having marked this as a call, we can use any registers. |
3852 // Just make sure that the input/output registers are the expected ones. | 3702 // Just make sure that the input/output registers are the expected ones. |
3853 ASSERT(!instr->right()->IsDoubleRegister() || | 3703 ASSERT(!instr->right()->IsDoubleRegister() || |
3854 ToDoubleRegister(instr->right()).is(d2)); | 3704 ToDoubleRegister(instr->right()).is(d2)); |
3855 ASSERT(!instr->right()->IsRegister() || | 3705 ASSERT(!instr->right()->IsRegister() || |
3856 ToRegister(instr->right()).is(r2)); | 3706 ToRegister(instr->right()).is(r2)); |
3857 ASSERT(ToDoubleRegister(instr->left()).is(d1)); | 3707 ASSERT(ToDoubleRegister(instr->left()).is(d1)); |
3858 ASSERT(ToDoubleRegister(instr->result()).is(d3)); | 3708 ASSERT(ToDoubleRegister(instr->result()).is(d3)); |
3859 | 3709 |
(...skipping 12 matching lines...) Expand all Loading... |
3872 __ CallStub(&stub); | 3722 __ CallStub(&stub); |
3873 } else { | 3723 } else { |
3874 ASSERT(exponent_type.IsDouble()); | 3724 ASSERT(exponent_type.IsDouble()); |
3875 MathPowStub stub(MathPowStub::DOUBLE); | 3725 MathPowStub stub(MathPowStub::DOUBLE); |
3876 __ CallStub(&stub); | 3726 __ CallStub(&stub); |
3877 } | 3727 } |
3878 } | 3728 } |
3879 | 3729 |
3880 | 3730 |
3881 void LCodeGen::DoRandom(LRandom* instr) { | 3731 void LCodeGen::DoRandom(LRandom* instr) { |
3882 CpuFeatures::Scope scope(VFP2); | |
3883 class DeferredDoRandom: public LDeferredCode { | 3732 class DeferredDoRandom: public LDeferredCode { |
3884 public: | 3733 public: |
3885 DeferredDoRandom(LCodeGen* codegen, LRandom* instr) | 3734 DeferredDoRandom(LCodeGen* codegen, LRandom* instr) |
3886 : LDeferredCode(codegen), instr_(instr) { } | 3735 : LDeferredCode(codegen), instr_(instr) { } |
3887 virtual void Generate() { codegen()->DoDeferredRandom(instr_); } | 3736 virtual void Generate() { codegen()->DoDeferredRandom(instr_); } |
3888 virtual LInstruction* instr() { return instr_; } | 3737 virtual LInstruction* instr() { return instr_; } |
3889 private: | 3738 private: |
3890 LRandom* instr_; | 3739 LRandom* instr_; |
3891 }; | 3740 }; |
3892 | 3741 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3951 | 3800 |
3952 | 3801 |
3953 void LCodeGen::DoDeferredRandom(LRandom* instr) { | 3802 void LCodeGen::DoDeferredRandom(LRandom* instr) { |
3954 __ PrepareCallCFunction(1, scratch0()); | 3803 __ PrepareCallCFunction(1, scratch0()); |
3955 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); | 3804 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); |
3956 // Return value is in r0. | 3805 // Return value is in r0. |
3957 } | 3806 } |
3958 | 3807 |
3959 | 3808 |
3960 void LCodeGen::DoMathExp(LMathExp* instr) { | 3809 void LCodeGen::DoMathExp(LMathExp* instr) { |
3961 CpuFeatures::Scope scope(VFP2); | 3810 DoubleRegister input = ToDoubleRegister(instr->value()); |
3962 DwVfpRegister input = ToDoubleRegister(instr->value()); | 3811 DoubleRegister result = ToDoubleRegister(instr->result()); |
3963 DwVfpRegister result = ToDoubleRegister(instr->result()); | 3812 DoubleRegister double_scratch1 = ToDoubleRegister(instr->double_temp()); |
3964 DwVfpRegister double_scratch1 = ToDoubleRegister(instr->double_temp()); | 3813 DoubleRegister double_scratch2 = double_scratch0(); |
3965 DwVfpRegister double_scratch2 = double_scratch0(); | |
3966 Register temp1 = ToRegister(instr->temp1()); | 3814 Register temp1 = ToRegister(instr->temp1()); |
3967 Register temp2 = ToRegister(instr->temp2()); | 3815 Register temp2 = ToRegister(instr->temp2()); |
3968 | 3816 |
3969 MathExpGenerator::EmitMathExp( | 3817 MathExpGenerator::EmitMathExp( |
3970 masm(), input, result, double_scratch1, double_scratch2, | 3818 masm(), input, result, double_scratch1, double_scratch2, |
3971 temp1, temp2, scratch0()); | 3819 temp1, temp2, scratch0()); |
3972 } | 3820 } |
3973 | 3821 |
3974 | 3822 |
3975 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { | 3823 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4241 } | 4089 } |
4242 __ cmp(ip, ToRegister(instr->length())); | 4090 __ cmp(ip, ToRegister(instr->length())); |
4243 } else { | 4091 } else { |
4244 __ cmp(ToRegister(instr->index()), ToRegister(instr->length())); | 4092 __ cmp(ToRegister(instr->index()), ToRegister(instr->length())); |
4245 } | 4093 } |
4246 DeoptimizeIf(hs, instr->environment()); | 4094 DeoptimizeIf(hs, instr->environment()); |
4247 } | 4095 } |
4248 | 4096 |
4249 | 4097 |
4250 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { | 4098 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
4251 CpuFeatures::Scope scope(VFP2); | |
4252 Register external_pointer = ToRegister(instr->elements()); | 4099 Register external_pointer = ToRegister(instr->elements()); |
4253 Register key = no_reg; | 4100 Register key = no_reg; |
4254 ElementsKind elements_kind = instr->elements_kind(); | 4101 ElementsKind elements_kind = instr->elements_kind(); |
4255 bool key_is_constant = instr->key()->IsConstantOperand(); | 4102 bool key_is_constant = instr->key()->IsConstantOperand(); |
4256 int constant_key = 0; | 4103 int constant_key = 0; |
4257 if (key_is_constant) { | 4104 if (key_is_constant) { |
4258 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 4105 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
4259 if (constant_key & 0xF0000000) { | 4106 if (constant_key & 0xF0000000) { |
4260 Abort("array index constant value too big."); | 4107 Abort("array index constant value too big."); |
4261 } | 4108 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4312 case DICTIONARY_ELEMENTS: | 4159 case DICTIONARY_ELEMENTS: |
4313 case NON_STRICT_ARGUMENTS_ELEMENTS: | 4160 case NON_STRICT_ARGUMENTS_ELEMENTS: |
4314 UNREACHABLE(); | 4161 UNREACHABLE(); |
4315 break; | 4162 break; |
4316 } | 4163 } |
4317 } | 4164 } |
4318 } | 4165 } |
4319 | 4166 |
4320 | 4167 |
4321 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { | 4168 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { |
4322 CpuFeatures::Scope scope(VFP2); | |
4323 DwVfpRegister value = ToDoubleRegister(instr->value()); | 4169 DwVfpRegister value = ToDoubleRegister(instr->value()); |
4324 Register elements = ToRegister(instr->elements()); | 4170 Register elements = ToRegister(instr->elements()); |
4325 Register key = no_reg; | 4171 Register key = no_reg; |
4326 Register scratch = scratch0(); | 4172 Register scratch = scratch0(); |
4327 bool key_is_constant = instr->key()->IsConstantOperand(); | 4173 bool key_is_constant = instr->key()->IsConstantOperand(); |
4328 int constant_key = 0; | 4174 int constant_key = 0; |
4329 | 4175 |
4330 // Calculate the effective address of the slot in the array to store the | 4176 // Calculate the effective address of the slot in the array to store the |
4331 // double value. | 4177 // double value. |
4332 if (key_is_constant) { | 4178 if (key_is_constant) { |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4589 | 4435 |
4590 | 4436 |
4591 void LCodeGen::DoStringLength(LStringLength* instr) { | 4437 void LCodeGen::DoStringLength(LStringLength* instr) { |
4592 Register string = ToRegister(instr->string()); | 4438 Register string = ToRegister(instr->string()); |
4593 Register result = ToRegister(instr->result()); | 4439 Register result = ToRegister(instr->result()); |
4594 __ ldr(result, FieldMemOperand(string, String::kLengthOffset)); | 4440 __ ldr(result, FieldMemOperand(string, String::kLengthOffset)); |
4595 } | 4441 } |
4596 | 4442 |
4597 | 4443 |
4598 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 4444 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
4599 CpuFeatures::Scope scope(VFP2); | |
4600 LOperand* input = instr->value(); | 4445 LOperand* input = instr->value(); |
4601 ASSERT(input->IsRegister() || input->IsStackSlot()); | 4446 ASSERT(input->IsRegister() || input->IsStackSlot()); |
4602 LOperand* output = instr->result(); | 4447 LOperand* output = instr->result(); |
4603 ASSERT(output->IsDoubleRegister()); | 4448 ASSERT(output->IsDoubleRegister()); |
4604 SwVfpRegister single_scratch = double_scratch0().low(); | 4449 SwVfpRegister single_scratch = double_scratch0().low(); |
4605 if (input->IsStackSlot()) { | 4450 if (input->IsStackSlot()) { |
4606 Register scratch = scratch0(); | 4451 Register scratch = scratch0(); |
4607 __ ldr(scratch, ToMemOperand(input)); | 4452 __ ldr(scratch, ToMemOperand(input)); |
4608 __ vmov(single_scratch, scratch); | 4453 __ vmov(single_scratch, scratch); |
4609 } else { | 4454 } else { |
4610 __ vmov(single_scratch, ToRegister(input)); | 4455 __ vmov(single_scratch, ToRegister(input)); |
4611 } | 4456 } |
4612 __ vcvt_f64_s32(ToDoubleRegister(output), single_scratch); | 4457 __ vcvt_f64_s32(ToDoubleRegister(output), single_scratch); |
4613 } | 4458 } |
4614 | 4459 |
4615 | 4460 |
4616 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { | 4461 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { |
4617 CpuFeatures::Scope scope(VFP2); | |
4618 LOperand* input = instr->value(); | 4462 LOperand* input = instr->value(); |
4619 LOperand* output = instr->result(); | 4463 LOperand* output = instr->result(); |
4620 | 4464 |
4621 SwVfpRegister flt_scratch = double_scratch0().low(); | 4465 SwVfpRegister flt_scratch = double_scratch0().low(); |
4622 __ vmov(flt_scratch, ToRegister(input)); | 4466 __ vmov(flt_scratch, ToRegister(input)); |
4623 __ vcvt_f64_u32(ToDoubleRegister(output), flt_scratch); | 4467 __ vcvt_f64_u32(ToDoubleRegister(output), flt_scratch); |
4624 } | 4468 } |
4625 | 4469 |
4626 | 4470 |
4627 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 4471 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4669 Register reg = ToRegister(input); | 4513 Register reg = ToRegister(input); |
4670 | 4514 |
4671 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); | 4515 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); |
4672 __ cmp(reg, Operand(Smi::kMaxValue)); | 4516 __ cmp(reg, Operand(Smi::kMaxValue)); |
4673 __ b(hi, deferred->entry()); | 4517 __ b(hi, deferred->entry()); |
4674 __ SmiTag(reg, reg); | 4518 __ SmiTag(reg, reg); |
4675 __ bind(deferred->exit()); | 4519 __ bind(deferred->exit()); |
4676 } | 4520 } |
4677 | 4521 |
4678 | 4522 |
4679 // Convert unsigned integer with specified number of leading zeroes in binary | |
4680 // representation to IEEE 754 double. | |
4681 // Integer to convert is passed in register hiword. | |
4682 // Resulting double is returned in registers hiword:loword. | |
4683 // This functions does not work correctly for 0. | |
4684 static void GenerateUInt2Double(MacroAssembler* masm, | |
4685 Register hiword, | |
4686 Register loword, | |
4687 Register scratch, | |
4688 int leading_zeroes) { | |
4689 const int meaningful_bits = kBitsPerInt - leading_zeroes - 1; | |
4690 const int biased_exponent = HeapNumber::kExponentBias + meaningful_bits; | |
4691 | |
4692 const int mantissa_shift_for_hi_word = | |
4693 meaningful_bits - HeapNumber::kMantissaBitsInTopWord; | |
4694 const int mantissa_shift_for_lo_word = | |
4695 kBitsPerInt - mantissa_shift_for_hi_word; | |
4696 masm->mov(scratch, Operand(biased_exponent << HeapNumber::kExponentShift)); | |
4697 if (mantissa_shift_for_hi_word > 0) { | |
4698 masm->mov(loword, Operand(hiword, LSL, mantissa_shift_for_lo_word)); | |
4699 masm->orr(hiword, scratch, | |
4700 Operand(hiword, LSR, mantissa_shift_for_hi_word)); | |
4701 } else { | |
4702 masm->mov(loword, Operand(0, RelocInfo::NONE)); | |
4703 masm->orr(hiword, scratch, | |
4704 Operand(hiword, LSL, -mantissa_shift_for_hi_word)); | |
4705 } | |
4706 | |
4707 // If least significant bit of biased exponent was not 1 it was corrupted | |
4708 // by most significant bit of mantissa so we should fix that. | |
4709 if (!(biased_exponent & 1)) { | |
4710 masm->bic(hiword, hiword, Operand(1 << HeapNumber::kExponentShift)); | |
4711 } | |
4712 } | |
4713 | |
4714 | |
4715 void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, | 4523 void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, |
4716 LOperand* value, | 4524 LOperand* value, |
4717 IntegerSignedness signedness) { | 4525 IntegerSignedness signedness) { |
4718 Label slow; | 4526 Label slow; |
4719 Register src = ToRegister(value); | 4527 Register src = ToRegister(value); |
4720 Register dst = ToRegister(instr->result()); | 4528 Register dst = ToRegister(instr->result()); |
4721 DwVfpRegister dbl_scratch = double_scratch0(); | 4529 DoubleRegister dbl_scratch = double_scratch0(); |
4722 SwVfpRegister flt_scratch = dbl_scratch.low(); | 4530 SwVfpRegister flt_scratch = dbl_scratch.low(); |
4723 | 4531 |
4724 // Preserve the value of all registers. | 4532 // Preserve the value of all registers. |
4725 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4533 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
4726 | 4534 |
4727 Label done; | 4535 Label done; |
4728 if (signedness == SIGNED_INT32) { | 4536 if (signedness == SIGNED_INT32) { |
4729 // There was overflow, so bits 30 and 31 of the original integer | 4537 // There was overflow, so bits 30 and 31 of the original integer |
4730 // disagree. Try to allocate a heap number in new space and store | 4538 // disagree. Try to allocate a heap number in new space and store |
4731 // the value in there. If that fails, call the runtime system. | 4539 // the value in there. If that fails, call the runtime system. |
4732 if (dst.is(src)) { | 4540 if (dst.is(src)) { |
4733 __ SmiUntag(src, dst); | 4541 __ SmiUntag(src, dst); |
4734 __ eor(src, src, Operand(0x80000000)); | 4542 __ eor(src, src, Operand(0x80000000)); |
4735 } | 4543 } |
4736 if (CpuFeatures::IsSupported(VFP2)) { | 4544 __ vmov(flt_scratch, src); |
4737 CpuFeatures::Scope scope(VFP2); | 4545 __ vcvt_f64_s32(dbl_scratch, flt_scratch); |
4738 __ vmov(flt_scratch, src); | |
4739 __ vcvt_f64_s32(dbl_scratch, flt_scratch); | |
4740 } else { | |
4741 FloatingPointHelper::Destination dest = | |
4742 FloatingPointHelper::kCoreRegisters; | |
4743 FloatingPointHelper::ConvertIntToDouble(masm(), src, dest, d0, | |
4744 sfpd_lo, sfpd_hi, | |
4745 scratch0(), s0); | |
4746 } | |
4747 } else { | 4546 } else { |
4748 if (CpuFeatures::IsSupported(VFP2)) { | 4547 __ vmov(flt_scratch, src); |
4749 CpuFeatures::Scope scope(VFP2); | 4548 __ vcvt_f64_u32(dbl_scratch, flt_scratch); |
4750 __ vmov(flt_scratch, src); | |
4751 __ vcvt_f64_u32(dbl_scratch, flt_scratch); | |
4752 } else { | |
4753 Label no_leading_zero, done; | |
4754 __ tst(src, Operand(0x80000000)); | |
4755 __ b(ne, &no_leading_zero); | |
4756 | |
4757 // Integer has one leading zeros. | |
4758 GenerateUInt2Double(masm(), sfpd_hi, sfpd_lo, r9, 1); | |
4759 __ b(&done); | |
4760 | |
4761 __ bind(&no_leading_zero); | |
4762 GenerateUInt2Double(masm(), sfpd_hi, sfpd_lo, r9, 0); | |
4763 __ b(&done); | |
4764 } | |
4765 } | 4549 } |
4766 | 4550 |
4767 if (FLAG_inline_new) { | 4551 if (FLAG_inline_new) { |
4768 __ LoadRoot(scratch0(), Heap::kHeapNumberMapRootIndex); | 4552 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); |
4769 __ AllocateHeapNumber(r5, r3, r4, scratch0(), &slow, DONT_TAG_RESULT); | 4553 __ AllocateHeapNumber(r5, r3, r4, r6, &slow, DONT_TAG_RESULT); |
4770 __ Move(dst, r5); | 4554 __ Move(dst, r5); |
4771 __ b(&done); | 4555 __ b(&done); |
4772 } | 4556 } |
4773 | 4557 |
4774 // Slow case: Call the runtime system to do the number allocation. | 4558 // Slow case: Call the runtime system to do the number allocation. |
4775 __ bind(&slow); | 4559 __ bind(&slow); |
4776 | 4560 |
4777 // TODO(3095996): Put a valid pointer value in the stack slot where the result | 4561 // TODO(3095996): Put a valid pointer value in the stack slot where the result |
4778 // register is stored, as this register is in the pointer map, but contains an | 4562 // register is stored, as this register is in the pointer map, but contains an |
4779 // integer value. | 4563 // integer value. |
4780 __ mov(ip, Operand(0)); | 4564 __ mov(ip, Operand(0)); |
4781 __ StoreToSafepointRegisterSlot(ip, dst); | 4565 __ StoreToSafepointRegisterSlot(ip, dst); |
4782 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 4566 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
4783 __ Move(dst, r0); | 4567 __ Move(dst, r0); |
4784 __ sub(dst, dst, Operand(kHeapObjectTag)); | 4568 __ sub(dst, dst, Operand(kHeapObjectTag)); |
4785 | 4569 |
4786 // Done. Put the value in dbl_scratch into the value of the allocated heap | 4570 // Done. Put the value in dbl_scratch into the value of the allocated heap |
4787 // number. | 4571 // number. |
4788 __ bind(&done); | 4572 __ bind(&done); |
4789 if (CpuFeatures::IsSupported(VFP2)) { | 4573 __ vstr(dbl_scratch, dst, HeapNumber::kValueOffset); |
4790 CpuFeatures::Scope scope(VFP2); | |
4791 __ vstr(dbl_scratch, dst, HeapNumber::kValueOffset); | |
4792 } else { | |
4793 __ str(sfpd_lo, MemOperand(dst, HeapNumber::kMantissaOffset)); | |
4794 __ str(sfpd_hi, MemOperand(dst, HeapNumber::kExponentOffset)); | |
4795 } | |
4796 __ add(dst, dst, Operand(kHeapObjectTag)); | 4574 __ add(dst, dst, Operand(kHeapObjectTag)); |
4797 __ StoreToSafepointRegisterSlot(dst, dst); | 4575 __ StoreToSafepointRegisterSlot(dst, dst); |
4798 } | 4576 } |
4799 | 4577 |
4800 | 4578 |
4801 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 4579 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
4802 class DeferredNumberTagD: public LDeferredCode { | 4580 class DeferredNumberTagD: public LDeferredCode { |
4803 public: | 4581 public: |
4804 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 4582 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
4805 : LDeferredCode(codegen), instr_(instr) { } | 4583 : LDeferredCode(codegen), instr_(instr) { } |
4806 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 4584 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } |
4807 virtual LInstruction* instr() { return instr_; } | 4585 virtual LInstruction* instr() { return instr_; } |
4808 private: | 4586 private: |
4809 LNumberTagD* instr_; | 4587 LNumberTagD* instr_; |
4810 }; | 4588 }; |
4811 | 4589 |
4812 DwVfpRegister input_reg = ToDoubleRegister(instr->value()); | 4590 DoubleRegister input_reg = ToDoubleRegister(instr->value()); |
4813 Register scratch = scratch0(); | 4591 Register scratch = scratch0(); |
4814 Register reg = ToRegister(instr->result()); | 4592 Register reg = ToRegister(instr->result()); |
4815 Register temp1 = ToRegister(instr->temp()); | 4593 Register temp1 = ToRegister(instr->temp()); |
4816 Register temp2 = ToRegister(instr->temp2()); | 4594 Register temp2 = ToRegister(instr->temp2()); |
4817 | 4595 |
4818 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); | 4596 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); |
4819 if (FLAG_inline_new) { | 4597 if (FLAG_inline_new) { |
4820 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); | 4598 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); |
4821 // We want the untagged address first for performance | 4599 // We want the untagged address first for performance |
4822 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry(), | 4600 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry(), |
4823 DONT_TAG_RESULT); | 4601 DONT_TAG_RESULT); |
4824 } else { | 4602 } else { |
4825 __ jmp(deferred->entry()); | 4603 __ jmp(deferred->entry()); |
4826 } | 4604 } |
4827 __ bind(deferred->exit()); | 4605 __ bind(deferred->exit()); |
4828 if (CpuFeatures::IsSupported(VFP2)) { | 4606 __ vstr(input_reg, reg, HeapNumber::kValueOffset); |
4829 CpuFeatures::Scope scope(VFP2); | |
4830 __ vstr(input_reg, reg, HeapNumber::kValueOffset); | |
4831 } else { | |
4832 __ str(sfpd_lo, MemOperand(reg, HeapNumber::kValueOffset)); | |
4833 __ str(sfpd_hi, MemOperand(reg, HeapNumber::kValueOffset + kPointerSize)); | |
4834 } | |
4835 // Now that we have finished with the object's real address tag it | 4607 // Now that we have finished with the object's real address tag it |
4836 __ add(reg, reg, Operand(kHeapObjectTag)); | 4608 __ add(reg, reg, Operand(kHeapObjectTag)); |
4837 } | 4609 } |
4838 | 4610 |
4839 | 4611 |
4840 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 4612 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
4841 // TODO(3095996): Get rid of this. For now, we need to make the | 4613 // TODO(3095996): Get rid of this. For now, we need to make the |
4842 // result register contain a valid pointer because it is already | 4614 // result register contain a valid pointer because it is already |
4843 // contained in the register pointer map. | 4615 // contained in the register pointer map. |
4844 Register reg = ToRegister(instr->result()); | 4616 Register reg = ToRegister(instr->result()); |
(...skipping 20 matching lines...) Expand all Loading... |
4865 // If the input is a HeapObject, SmiUntag will set the carry flag. | 4637 // If the input is a HeapObject, SmiUntag will set the carry flag. |
4866 __ SmiUntag(result, input, SetCC); | 4638 __ SmiUntag(result, input, SetCC); |
4867 DeoptimizeIf(cs, instr->environment()); | 4639 DeoptimizeIf(cs, instr->environment()); |
4868 } else { | 4640 } else { |
4869 __ SmiUntag(result, input); | 4641 __ SmiUntag(result, input); |
4870 } | 4642 } |
4871 } | 4643 } |
4872 | 4644 |
4873 | 4645 |
4874 void LCodeGen::EmitNumberUntagD(Register input_reg, | 4646 void LCodeGen::EmitNumberUntagD(Register input_reg, |
4875 DwVfpRegister result_reg, | 4647 DoubleRegister result_reg, |
4876 bool deoptimize_on_undefined, | 4648 bool deoptimize_on_undefined, |
4877 bool deoptimize_on_minus_zero, | 4649 bool deoptimize_on_minus_zero, |
4878 LEnvironment* env) { | 4650 LEnvironment* env) { |
4879 Register scratch = scratch0(); | 4651 Register scratch = scratch0(); |
4880 SwVfpRegister flt_scratch = double_scratch0().low(); | 4652 SwVfpRegister flt_scratch = double_scratch0().low(); |
4881 ASSERT(!result_reg.is(double_scratch0())); | 4653 ASSERT(!result_reg.is(double_scratch0())); |
4882 CpuFeatures::Scope scope(VFP2); | |
4883 | 4654 |
4884 Label load_smi, heap_number, done; | 4655 Label load_smi, heap_number, done; |
4885 | 4656 |
4886 // Smi check. | 4657 // Smi check. |
4887 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); | 4658 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); |
4888 | 4659 |
4889 // Heap number map check. | 4660 // Heap number map check. |
4890 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4661 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
4891 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 4662 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
4892 __ cmp(scratch, Operand(ip)); | 4663 __ cmp(scratch, Operand(ip)); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4947 // SmiUntag(heap_object, SetCC) | 4718 // SmiUntag(heap_object, SetCC) |
4948 STATIC_ASSERT(kHeapObjectTag == 1); | 4719 STATIC_ASSERT(kHeapObjectTag == 1); |
4949 __ adc(input_reg, input_reg, Operand(input_reg)); | 4720 __ adc(input_reg, input_reg, Operand(input_reg)); |
4950 | 4721 |
4951 // Heap number map check. | 4722 // Heap number map check. |
4952 __ ldr(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4723 __ ldr(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
4953 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 4724 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
4954 __ cmp(scratch1, Operand(ip)); | 4725 __ cmp(scratch1, Operand(ip)); |
4955 | 4726 |
4956 if (instr->truncating()) { | 4727 if (instr->truncating()) { |
4957 CpuFeatures::Scope scope(VFP2); | |
4958 Register scratch3 = ToRegister(instr->temp2()); | 4728 Register scratch3 = ToRegister(instr->temp2()); |
4959 SwVfpRegister single_scratch = double_scratch.low(); | 4729 SwVfpRegister single_scratch = double_scratch.low(); |
4960 ASSERT(!scratch3.is(input_reg) && | 4730 ASSERT(!scratch3.is(input_reg) && |
4961 !scratch3.is(scratch1) && | 4731 !scratch3.is(scratch1) && |
4962 !scratch3.is(scratch2)); | 4732 !scratch3.is(scratch2)); |
4963 // Performs a truncating conversion of a floating point number as used by | 4733 // Performs a truncating conversion of a floating point number as used by |
4964 // the JS bitwise operations. | 4734 // the JS bitwise operations. |
4965 Label heap_number; | 4735 Label heap_number; |
4966 __ b(eq, &heap_number); | 4736 __ b(eq, &heap_number); |
4967 // Check for undefined. Undefined is converted to zero for truncating | 4737 // Check for undefined. Undefined is converted to zero for truncating |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5039 } | 4809 } |
5040 | 4810 |
5041 | 4811 |
5042 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 4812 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
5043 LOperand* input = instr->value(); | 4813 LOperand* input = instr->value(); |
5044 ASSERT(input->IsRegister()); | 4814 ASSERT(input->IsRegister()); |
5045 LOperand* result = instr->result(); | 4815 LOperand* result = instr->result(); |
5046 ASSERT(result->IsDoubleRegister()); | 4816 ASSERT(result->IsDoubleRegister()); |
5047 | 4817 |
5048 Register input_reg = ToRegister(input); | 4818 Register input_reg = ToRegister(input); |
5049 DwVfpRegister result_reg = ToDoubleRegister(result); | 4819 DoubleRegister result_reg = ToDoubleRegister(result); |
5050 | 4820 |
5051 EmitNumberUntagD(input_reg, result_reg, | 4821 EmitNumberUntagD(input_reg, result_reg, |
5052 instr->hydrogen()->deoptimize_on_undefined(), | 4822 instr->hydrogen()->deoptimize_on_undefined(), |
5053 instr->hydrogen()->deoptimize_on_minus_zero(), | 4823 instr->hydrogen()->deoptimize_on_minus_zero(), |
5054 instr->environment()); | 4824 instr->environment()); |
5055 } | 4825 } |
5056 | 4826 |
5057 | 4827 |
5058 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 4828 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
5059 Register result_reg = ToRegister(instr->result()); | 4829 Register result_reg = ToRegister(instr->result()); |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5188 __ CompareMap(reg, scratch, map, &success, REQUIRE_EXACT_MAP); | 4958 __ CompareMap(reg, scratch, map, &success, REQUIRE_EXACT_MAP); |
5189 __ b(eq, &success); | 4959 __ b(eq, &success); |
5190 } | 4960 } |
5191 Handle<Map> map = map_set->last(); | 4961 Handle<Map> map = map_set->last(); |
5192 DoCheckMapCommon(reg, scratch, map, REQUIRE_EXACT_MAP, instr->environment()); | 4962 DoCheckMapCommon(reg, scratch, map, REQUIRE_EXACT_MAP, instr->environment()); |
5193 __ bind(&success); | 4963 __ bind(&success); |
5194 } | 4964 } |
5195 | 4965 |
5196 | 4966 |
5197 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 4967 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
5198 CpuFeatures::Scope vfp_scope(VFP2); | 4968 DoubleRegister value_reg = ToDoubleRegister(instr->unclamped()); |
5199 DwVfpRegister value_reg = ToDoubleRegister(instr->unclamped()); | |
5200 Register result_reg = ToRegister(instr->result()); | 4969 Register result_reg = ToRegister(instr->result()); |
5201 DwVfpRegister temp_reg = ToDoubleRegister(instr->temp()); | 4970 DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); |
5202 __ ClampDoubleToUint8(result_reg, value_reg, temp_reg); | 4971 __ ClampDoubleToUint8(result_reg, value_reg, temp_reg); |
5203 } | 4972 } |
5204 | 4973 |
5205 | 4974 |
5206 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { | 4975 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { |
5207 CpuFeatures::Scope scope(VFP2); | |
5208 Register unclamped_reg = ToRegister(instr->unclamped()); | 4976 Register unclamped_reg = ToRegister(instr->unclamped()); |
5209 Register result_reg = ToRegister(instr->result()); | 4977 Register result_reg = ToRegister(instr->result()); |
5210 __ ClampUint8(result_reg, unclamped_reg); | 4978 __ ClampUint8(result_reg, unclamped_reg); |
5211 } | 4979 } |
5212 | 4980 |
5213 | 4981 |
5214 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { | 4982 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { |
5215 CpuFeatures::Scope scope(VFP2); | |
5216 Register scratch = scratch0(); | 4983 Register scratch = scratch0(); |
5217 Register input_reg = ToRegister(instr->unclamped()); | 4984 Register input_reg = ToRegister(instr->unclamped()); |
5218 Register result_reg = ToRegister(instr->result()); | 4985 Register result_reg = ToRegister(instr->result()); |
5219 DwVfpRegister temp_reg = ToDoubleRegister(instr->temp()); | 4986 DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); |
5220 Label is_smi, done, heap_number; | 4987 Label is_smi, done, heap_number; |
5221 | 4988 |
5222 // Both smi and heap number cases are handled. | 4989 // Both smi and heap number cases are handled. |
5223 __ UntagAndJumpIfSmi(result_reg, input_reg, &is_smi); | 4990 __ UntagAndJumpIfSmi(result_reg, input_reg, &is_smi); |
5224 | 4991 |
5225 // Check for heap number | 4992 // Check for heap number |
5226 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4993 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
5227 __ cmp(scratch, Operand(factory()->heap_number_map())); | 4994 __ cmp(scratch, Operand(factory()->heap_number_map())); |
5228 __ b(eq, &heap_number); | 4995 __ b(eq, &heap_number); |
5229 | 4996 |
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5786 __ ldr(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset)); | 5553 __ ldr(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset)); |
5787 | 5554 |
5788 // Check the marker in the calling frame. | 5555 // Check the marker in the calling frame. |
5789 __ bind(&check_frame_marker); | 5556 __ bind(&check_frame_marker); |
5790 __ ldr(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset)); | 5557 __ ldr(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset)); |
5791 __ cmp(temp1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); | 5558 __ cmp(temp1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); |
5792 } | 5559 } |
5793 | 5560 |
5794 | 5561 |
5795 void LCodeGen::EnsureSpaceForLazyDeopt() { | 5562 void LCodeGen::EnsureSpaceForLazyDeopt() { |
5796 if (info()->IsStub()) return; | |
5797 // Ensure that we have enough space after the previous lazy-bailout | 5563 // Ensure that we have enough space after the previous lazy-bailout |
5798 // instruction for patching the code here. | 5564 // instruction for patching the code here. |
5799 int current_pc = masm()->pc_offset(); | 5565 int current_pc = masm()->pc_offset(); |
5800 int patch_size = Deoptimizer::patch_size(); | 5566 int patch_size = Deoptimizer::patch_size(); |
5801 if (current_pc < last_lazy_deopt_pc_ + patch_size) { | 5567 if (current_pc < last_lazy_deopt_pc_ + patch_size) { |
5802 // Block literal pool emission for duration of padding. | 5568 // Block literal pool emission for duration of padding. |
5803 Assembler::BlockConstPoolScope block_const_pool(masm()); | 5569 Assembler::BlockConstPoolScope block_const_pool(masm()); |
5804 int padding_size = last_lazy_deopt_pc_ + patch_size - current_pc; | 5570 int padding_size = last_lazy_deopt_pc_ + patch_size - current_pc; |
5805 ASSERT_EQ(0, padding_size % Assembler::kInstrSize); | 5571 ASSERT_EQ(0, padding_size % Assembler::kInstrSize); |
5806 while (padding_size > 0) { | 5572 while (padding_size > 0) { |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6018 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); | 5784 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); |
6019 __ ldr(result, FieldMemOperand(scratch, | 5785 __ ldr(result, FieldMemOperand(scratch, |
6020 FixedArray::kHeaderSize - kPointerSize)); | 5786 FixedArray::kHeaderSize - kPointerSize)); |
6021 __ bind(&done); | 5787 __ bind(&done); |
6022 } | 5788 } |
6023 | 5789 |
6024 | 5790 |
6025 #undef __ | 5791 #undef __ |
6026 | 5792 |
6027 } } // namespace v8::internal | 5793 } } // namespace v8::internal |
OLD | NEW |