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