| 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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 info()->CommitDependencies(code); | 91 info()->CommitDependencies(code); |
| 92 } | 92 } |
| 93 | 93 |
| 94 | 94 |
| 95 void LCodeGen::Abort(BailoutReason reason) { | 95 void LCodeGen::Abort(BailoutReason reason) { |
| 96 info()->set_bailout_reason(reason); | 96 info()->set_bailout_reason(reason); |
| 97 status_ = ABORTED; | 97 status_ = ABORTED; |
| 98 } | 98 } |
| 99 | 99 |
| 100 | 100 |
| 101 void LCodeGen::SaveCallerDoubles() { |
| 102 ASSERT(info()->saves_caller_doubles()); |
| 103 ASSERT(NeedsEagerFrame()); |
| 104 Comment(";;; Save clobbered callee double registers"); |
| 105 int count = 0; |
| 106 BitVector* doubles = chunk()->allocated_double_registers(); |
| 107 BitVector::Iterator save_iterator(doubles); |
| 108 while (!save_iterator.Done()) { |
| 109 __ vstr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), |
| 110 MemOperand(sp, count * kDoubleSize)); |
| 111 save_iterator.Advance(); |
| 112 count++; |
| 113 } |
| 114 } |
| 115 |
| 116 |
| 117 void LCodeGen::RestoreCallerDoubles() { |
| 118 ASSERT(info()->saves_caller_doubles()); |
| 119 ASSERT(NeedsEagerFrame()); |
| 120 Comment(";;; Restore clobbered callee double registers"); |
| 121 BitVector* doubles = chunk()->allocated_double_registers(); |
| 122 BitVector::Iterator save_iterator(doubles); |
| 123 int count = 0; |
| 124 while (!save_iterator.Done()) { |
| 125 __ vldr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), |
| 126 MemOperand(sp, count * kDoubleSize)); |
| 127 save_iterator.Advance(); |
| 128 count++; |
| 129 } |
| 130 } |
| 131 |
| 132 |
| 101 bool LCodeGen::GeneratePrologue() { | 133 bool LCodeGen::GeneratePrologue() { |
| 102 ASSERT(is_generating()); | 134 ASSERT(is_generating()); |
| 103 | 135 |
| 104 if (info()->IsOptimizing()) { | 136 if (info()->IsOptimizing()) { |
| 105 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 137 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
| 106 | 138 |
| 107 #ifdef DEBUG | 139 #ifdef DEBUG |
| 108 if (strlen(FLAG_stop_at) > 0 && | 140 if (strlen(FLAG_stop_at) > 0 && |
| 109 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 141 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
| 110 __ stop("stop_at"); | 142 __ stop("stop_at"); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 __ cmp(r0, sp); | 183 __ cmp(r0, sp); |
| 152 __ b(ne, &loop); | 184 __ b(ne, &loop); |
| 153 __ pop(r1); | 185 __ pop(r1); |
| 154 __ pop(r0); | 186 __ pop(r0); |
| 155 } else { | 187 } else { |
| 156 __ sub(sp, sp, Operand(slots * kPointerSize)); | 188 __ sub(sp, sp, Operand(slots * kPointerSize)); |
| 157 } | 189 } |
| 158 } | 190 } |
| 159 | 191 |
| 160 if (info()->saves_caller_doubles()) { | 192 if (info()->saves_caller_doubles()) { |
| 161 Comment(";;; Save clobbered callee double registers"); | 193 SaveCallerDoubles(); |
| 162 int count = 0; | |
| 163 BitVector* doubles = chunk()->allocated_double_registers(); | |
| 164 BitVector::Iterator save_iterator(doubles); | |
| 165 while (!save_iterator.Done()) { | |
| 166 __ vstr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), | |
| 167 MemOperand(sp, count * kDoubleSize)); | |
| 168 save_iterator.Advance(); | |
| 169 count++; | |
| 170 } | |
| 171 } | 194 } |
| 172 | 195 |
| 173 // Possibly allocate a local context. | 196 // Possibly allocate a local context. |
| 174 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 197 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 175 if (heap_slots > 0) { | 198 if (heap_slots > 0) { |
| 176 Comment(";;; Allocate local context"); | 199 Comment(";;; Allocate local context"); |
| 177 // Argument to NewContext is the function, which is in r1. | 200 // Argument to NewContext is the function, which is in r1. |
| 178 __ push(r1); | 201 __ push(r1); |
| 179 if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 202 if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
| 180 FastNewContextStub stub(heap_slots); | 203 FastNewContextStub stub(heap_slots); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 code->instr()->Mnemonic()); | 276 code->instr()->Mnemonic()); |
| 254 __ bind(code->entry()); | 277 __ bind(code->entry()); |
| 255 if (NeedsDeferredFrame()) { | 278 if (NeedsDeferredFrame()) { |
| 256 Comment(";;; Build frame"); | 279 Comment(";;; Build frame"); |
| 257 ASSERT(!frame_is_built_); | 280 ASSERT(!frame_is_built_); |
| 258 ASSERT(info()->IsStub()); | 281 ASSERT(info()->IsStub()); |
| 259 frame_is_built_ = true; | 282 frame_is_built_ = true; |
| 260 __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); | 283 __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); |
| 261 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); | 284 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); |
| 262 __ push(scratch0()); | 285 __ push(scratch0()); |
| 263 __ add(fp, sp, Operand(2 * kPointerSize)); | 286 __ add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); |
| 264 Comment(";;; Deferred code"); | 287 Comment(";;; Deferred code"); |
| 265 } | 288 } |
| 266 code->Generate(); | 289 code->Generate(); |
| 267 if (NeedsDeferredFrame()) { | 290 if (NeedsDeferredFrame()) { |
| 268 Comment(";;; Destroy frame"); | 291 Comment(";;; Destroy frame"); |
| 269 ASSERT(frame_is_built_); | 292 ASSERT(frame_is_built_); |
| 270 __ pop(ip); | 293 __ pop(ip); |
| 271 __ ldm(ia_w, sp, cp.bit() | fp.bit() | lr.bit()); | 294 __ ldm(ia_w, sp, cp.bit() | fp.bit() | lr.bit()); |
| 272 frame_is_built_ = false; | 295 frame_is_built_ = false; |
| 273 } | 296 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 306 __ bind(&deopt_jump_table_[i].label); | 329 __ bind(&deopt_jump_table_[i].label); |
| 307 Address entry = deopt_jump_table_[i].address; | 330 Address entry = deopt_jump_table_[i].address; |
| 308 Deoptimizer::BailoutType type = deopt_jump_table_[i].bailout_type; | 331 Deoptimizer::BailoutType type = deopt_jump_table_[i].bailout_type; |
| 309 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); | 332 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); |
| 310 if (id == Deoptimizer::kNotDeoptimizationEntry) { | 333 if (id == Deoptimizer::kNotDeoptimizationEntry) { |
| 311 Comment(";;; jump table entry %d.", i); | 334 Comment(";;; jump table entry %d.", i); |
| 312 } else { | 335 } else { |
| 313 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); | 336 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); |
| 314 } | 337 } |
| 315 if (deopt_jump_table_[i].needs_frame) { | 338 if (deopt_jump_table_[i].needs_frame) { |
| 339 ASSERT(!info()->saves_caller_doubles()); |
| 316 __ mov(ip, Operand(ExternalReference::ForDeoptEntry(entry))); | 340 __ mov(ip, Operand(ExternalReference::ForDeoptEntry(entry))); |
| 317 if (needs_frame.is_bound()) { | 341 if (needs_frame.is_bound()) { |
| 318 __ b(&needs_frame); | 342 __ b(&needs_frame); |
| 319 } else { | 343 } else { |
| 320 __ bind(&needs_frame); | 344 __ bind(&needs_frame); |
| 321 __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); | 345 __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); |
| 322 // This variant of deopt can only be used with stubs. Since we don't | 346 // This variant of deopt can only be used with stubs. Since we don't |
| 323 // have a function pointer to install in the stack frame that we're | 347 // have a function pointer to install in the stack frame that we're |
| 324 // building, install a special marker there instead. | 348 // building, install a special marker there instead. |
| 325 ASSERT(info()->IsStub()); | 349 ASSERT(info()->IsStub()); |
| 326 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); | 350 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); |
| 327 __ push(scratch0()); | 351 __ push(scratch0()); |
| 328 __ add(fp, sp, Operand(2 * kPointerSize)); | 352 __ add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); |
| 329 __ mov(lr, Operand(pc), LeaveCC, al); | 353 __ mov(lr, Operand(pc), LeaveCC, al); |
| 330 __ mov(pc, ip); | 354 __ mov(pc, ip); |
| 331 } | 355 } |
| 332 } else { | 356 } else { |
| 357 if (info()->saves_caller_doubles()) { |
| 358 ASSERT(info()->IsStub()); |
| 359 RestoreCallerDoubles(); |
| 360 } |
| 333 __ mov(lr, Operand(pc), LeaveCC, al); | 361 __ mov(lr, Operand(pc), LeaveCC, al); |
| 334 __ mov(pc, Operand(ExternalReference::ForDeoptEntry(entry))); | 362 __ mov(pc, Operand(ExternalReference::ForDeoptEntry(entry))); |
| 335 } | 363 } |
| 336 masm()->CheckConstPool(false, false); | 364 masm()->CheckConstPool(false, false); |
| 337 } | 365 } |
| 338 | 366 |
| 339 // Force constant pool emission at the end of the deopt jump table to make | 367 // Force constant pool emission at the end of the deopt jump table to make |
| 340 // sure that no constant pools are emitted after. | 368 // sure that no constant pools are emitted after. |
| 341 masm()->CheckConstPool(true, false); | 369 masm()->CheckConstPool(true, false); |
| 342 | 370 |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 } else if (op->IsDoubleRegister()) { | 530 } else if (op->IsDoubleRegister()) { |
| 503 Abort(kToOperandIsDoubleRegisterUnimplemented); | 531 Abort(kToOperandIsDoubleRegisterUnimplemented); |
| 504 return Operand::Zero(); | 532 return Operand::Zero(); |
| 505 } | 533 } |
| 506 // Stack slots not implemented, use ToMemOperand instead. | 534 // Stack slots not implemented, use ToMemOperand instead. |
| 507 UNREACHABLE(); | 535 UNREACHABLE(); |
| 508 return Operand::Zero(); | 536 return Operand::Zero(); |
| 509 } | 537 } |
| 510 | 538 |
| 511 | 539 |
| 540 static int ArgumentsOffsetWithoutFrame(int index) { |
| 541 ASSERT(index < 0); |
| 542 return -(index + 1) * kPointerSize; |
| 543 } |
| 544 |
| 545 |
| 512 MemOperand LCodeGen::ToMemOperand(LOperand* op) const { | 546 MemOperand LCodeGen::ToMemOperand(LOperand* op) const { |
| 513 ASSERT(!op->IsRegister()); | 547 ASSERT(!op->IsRegister()); |
| 514 ASSERT(!op->IsDoubleRegister()); | 548 ASSERT(!op->IsDoubleRegister()); |
| 515 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); | 549 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); |
| 516 return MemOperand(fp, StackSlotOffset(op->index())); | 550 if (NeedsEagerFrame()) { |
| 551 return MemOperand(fp, StackSlotOffset(op->index())); |
| 552 } else { |
| 553 // Retrieve parameter without eager stack-frame relative to the |
| 554 // stack-pointer. |
| 555 return MemOperand(sp, ArgumentsOffsetWithoutFrame(op->index())); |
| 556 } |
| 517 } | 557 } |
| 518 | 558 |
| 519 | 559 |
| 520 MemOperand LCodeGen::ToHighMemOperand(LOperand* op) const { | 560 MemOperand LCodeGen::ToHighMemOperand(LOperand* op) const { |
| 521 ASSERT(op->IsDoubleStackSlot()); | 561 ASSERT(op->IsDoubleStackSlot()); |
| 522 return MemOperand(fp, StackSlotOffset(op->index()) + kPointerSize); | 562 if (NeedsEagerFrame()) { |
| 563 return MemOperand(fp, StackSlotOffset(op->index()) + kPointerSize); |
| 564 } else { |
| 565 // Retrieve parameter without eager stack-frame relative to the |
| 566 // stack-pointer. |
| 567 return MemOperand( |
| 568 sp, ArgumentsOffsetWithoutFrame(op->index()) + kPointerSize); |
| 569 } |
| 523 } | 570 } |
| 524 | 571 |
| 525 | 572 |
| 526 void LCodeGen::WriteTranslation(LEnvironment* environment, | 573 void LCodeGen::WriteTranslation(LEnvironment* environment, |
| 527 Translation* translation) { | 574 Translation* translation) { |
| 528 if (environment == NULL) return; | 575 if (environment == NULL) return; |
| 529 | 576 |
| 530 // The translation includes one command per value in the environment. | 577 // The translation includes one command per value in the environment. |
| 531 int translation_size = environment->translation_size(); | 578 int translation_size = environment->translation_size(); |
| 532 // The output frame height does not include the parameters. | 579 // The output frame height does not include the parameters. |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 802 condition = ne; | 849 condition = ne; |
| 803 __ cmp(scratch, Operand::Zero()); | 850 __ cmp(scratch, Operand::Zero()); |
| 804 } | 851 } |
| 805 } | 852 } |
| 806 | 853 |
| 807 if (info()->ShouldTrapOnDeopt()) { | 854 if (info()->ShouldTrapOnDeopt()) { |
| 808 __ stop("trap_on_deopt", condition); | 855 __ stop("trap_on_deopt", condition); |
| 809 } | 856 } |
| 810 | 857 |
| 811 ASSERT(info()->IsStub() || frame_is_built_); | 858 ASSERT(info()->IsStub() || frame_is_built_); |
| 812 if (condition == al && frame_is_built_) { | 859 // Go through jump table if we need to handle condition, build frame, or |
| 860 // restore caller doubles. |
| 861 if (condition == al && frame_is_built_ && |
| 862 !info()->saves_caller_doubles()) { |
| 813 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | 863 __ Call(entry, RelocInfo::RUNTIME_ENTRY); |
| 814 } else { | 864 } else { |
| 815 // We often have several deopts to the same entry, reuse the last | 865 // We often have several deopts to the same entry, reuse the last |
| 816 // jump entry if this is the case. | 866 // jump entry if this is the case. |
| 817 if (deopt_jump_table_.is_empty() || | 867 if (deopt_jump_table_.is_empty() || |
| 818 (deopt_jump_table_.last().address != entry) || | 868 (deopt_jump_table_.last().address != entry) || |
| 819 (deopt_jump_table_.last().bailout_type != bailout_type) || | 869 (deopt_jump_table_.last().bailout_type != bailout_type) || |
| 820 (deopt_jump_table_.last().needs_frame != !frame_is_built_)) { | 870 (deopt_jump_table_.last().needs_frame != !frame_is_built_)) { |
| 821 Deoptimizer::JumpTableEntry table_entry(entry, | 871 Deoptimizer::JumpTableEntry table_entry(entry, |
| 822 bailout_type, | 872 bailout_type, |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1107 __ rsb(result_reg, result_reg, Operand::Zero(), SetCC); | 1157 __ rsb(result_reg, result_reg, Operand::Zero(), SetCC); |
| 1108 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1158 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1109 DeoptimizeIf(eq, instr->environment()); | 1159 DeoptimizeIf(eq, instr->environment()); |
| 1110 } | 1160 } |
| 1111 __ b(&done); | 1161 __ b(&done); |
| 1112 } | 1162 } |
| 1113 | 1163 |
| 1114 __ bind(&left_is_not_negative); | 1164 __ bind(&left_is_not_negative); |
| 1115 __ and_(result_reg, left_reg, Operand(divisor - 1)); | 1165 __ and_(result_reg, left_reg, Operand(divisor - 1)); |
| 1116 __ bind(&done); | 1166 __ bind(&done); |
| 1117 | |
| 1118 } else if (hmod->fixed_right_arg().has_value) { | |
| 1119 Register left_reg = ToRegister(instr->left()); | |
| 1120 Register right_reg = ToRegister(instr->right()); | |
| 1121 Register result_reg = ToRegister(instr->result()); | |
| 1122 | |
| 1123 int32_t divisor = hmod->fixed_right_arg().value; | |
| 1124 ASSERT(IsPowerOf2(divisor)); | |
| 1125 | |
| 1126 // Check if our assumption of a fixed right operand still holds. | |
| 1127 __ cmp(right_reg, Operand(divisor)); | |
| 1128 DeoptimizeIf(ne, instr->environment()); | |
| 1129 | |
| 1130 Label left_is_not_negative, done; | |
| 1131 if (left->CanBeNegative()) { | |
| 1132 __ cmp(left_reg, Operand::Zero()); | |
| 1133 __ b(pl, &left_is_not_negative); | |
| 1134 __ rsb(result_reg, left_reg, Operand::Zero()); | |
| 1135 __ and_(result_reg, result_reg, Operand(divisor - 1)); | |
| 1136 __ rsb(result_reg, result_reg, Operand::Zero(), SetCC); | |
| 1137 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | |
| 1138 DeoptimizeIf(eq, instr->environment()); | |
| 1139 } | |
| 1140 __ b(&done); | |
| 1141 } | |
| 1142 | |
| 1143 __ bind(&left_is_not_negative); | |
| 1144 __ and_(result_reg, left_reg, Operand(divisor - 1)); | |
| 1145 __ bind(&done); | |
| 1146 | |
| 1147 } else if (CpuFeatures::IsSupported(SUDIV)) { | 1167 } else if (CpuFeatures::IsSupported(SUDIV)) { |
| 1148 CpuFeatureScope scope(masm(), SUDIV); | 1168 CpuFeatureScope scope(masm(), SUDIV); |
| 1149 | 1169 |
| 1150 Register left_reg = ToRegister(instr->left()); | 1170 Register left_reg = ToRegister(instr->left()); |
| 1151 Register right_reg = ToRegister(instr->right()); | 1171 Register right_reg = ToRegister(instr->right()); |
| 1152 Register result_reg = ToRegister(instr->result()); | 1172 Register result_reg = ToRegister(instr->result()); |
| 1153 | 1173 |
| 1154 Label done; | 1174 Label done; |
| 1155 // Check for x % 0, sdiv might signal an exception. We have to deopt in this | 1175 // Check for x % 0, sdiv might signal an exception. We have to deopt in this |
| 1156 // case because we can't return a NaN. | 1176 // case because we can't return a NaN. |
| (...skipping 844 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2001 } | 2021 } |
| 2002 } | 2022 } |
| 2003 | 2023 |
| 2004 | 2024 |
| 2005 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { | 2025 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { |
| 2006 String::Encoding encoding = instr->hydrogen()->encoding(); | 2026 String::Encoding encoding = instr->hydrogen()->encoding(); |
| 2007 Register string = ToRegister(instr->string()); | 2027 Register string = ToRegister(instr->string()); |
| 2008 Register value = ToRegister(instr->value()); | 2028 Register value = ToRegister(instr->value()); |
| 2009 | 2029 |
| 2010 if (FLAG_debug_code) { | 2030 if (FLAG_debug_code) { |
| 2011 Register scratch = scratch0(); | 2031 Register index = ToRegister(instr->index()); |
| 2012 __ ldr(scratch, FieldMemOperand(string, HeapObject::kMapOffset)); | |
| 2013 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | |
| 2014 | |
| 2015 __ and_(scratch, scratch, | |
| 2016 Operand(kStringRepresentationMask | kStringEncodingMask)); | |
| 2017 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; | 2032 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; |
| 2018 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; | 2033 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; |
| 2019 __ cmp(scratch, Operand(encoding == String::ONE_BYTE_ENCODING | 2034 int encoding_mask = |
| 2020 ? one_byte_seq_type : two_byte_seq_type)); | 2035 instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING |
| 2021 __ Check(eq, kUnexpectedStringType); | 2036 ? one_byte_seq_type : two_byte_seq_type; |
| 2037 __ EmitSeqStringSetCharCheck(string, index, value, encoding_mask); |
| 2022 } | 2038 } |
| 2023 | 2039 |
| 2024 MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding); | 2040 MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding); |
| 2025 if (encoding == String::ONE_BYTE_ENCODING) { | 2041 if (encoding == String::ONE_BYTE_ENCODING) { |
| 2026 __ strb(value, operand); | 2042 __ strb(value, operand); |
| 2027 } else { | 2043 } else { |
| 2028 __ strh(value, operand); | 2044 __ strh(value, operand); |
| 2029 } | 2045 } |
| 2030 } | 2046 } |
| 2031 | 2047 |
| (...skipping 905 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2937 if (FLAG_trace && info()->IsOptimizing()) { | 2953 if (FLAG_trace && info()->IsOptimizing()) { |
| 2938 // Push the return value on the stack as the parameter. | 2954 // Push the return value on the stack as the parameter. |
| 2939 // Runtime::TraceExit returns its parameter in r0. We're leaving the code | 2955 // Runtime::TraceExit returns its parameter in r0. We're leaving the code |
| 2940 // managed by the register allocator and tearing down the frame, it's | 2956 // managed by the register allocator and tearing down the frame, it's |
| 2941 // safe to write to the context register. | 2957 // safe to write to the context register. |
| 2942 __ push(r0); | 2958 __ push(r0); |
| 2943 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2959 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2944 __ CallRuntime(Runtime::kTraceExit, 1); | 2960 __ CallRuntime(Runtime::kTraceExit, 1); |
| 2945 } | 2961 } |
| 2946 if (info()->saves_caller_doubles()) { | 2962 if (info()->saves_caller_doubles()) { |
| 2947 ASSERT(NeedsEagerFrame()); | 2963 RestoreCallerDoubles(); |
| 2948 BitVector* doubles = chunk()->allocated_double_registers(); | |
| 2949 BitVector::Iterator save_iterator(doubles); | |
| 2950 int count = 0; | |
| 2951 while (!save_iterator.Done()) { | |
| 2952 __ vldr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), | |
| 2953 MemOperand(sp, count * kDoubleSize)); | |
| 2954 save_iterator.Advance(); | |
| 2955 count++; | |
| 2956 } | |
| 2957 } | 2964 } |
| 2958 int no_frame_start = -1; | 2965 int no_frame_start = -1; |
| 2959 if (NeedsEagerFrame()) { | 2966 if (NeedsEagerFrame()) { |
| 2960 __ mov(sp, fp); | 2967 __ mov(sp, fp); |
| 2961 no_frame_start = masm_->pc_offset(); | 2968 no_frame_start = masm_->pc_offset(); |
| 2962 __ ldm(ia_w, sp, fp.bit() | lr.bit()); | 2969 __ ldm(ia_w, sp, fp.bit() | lr.bit()); |
| 2963 } | 2970 } |
| 2964 if (instr->has_constant_parameter_count()) { | 2971 if (instr->has_constant_parameter_count()) { |
| 2965 int parameter_count = ToInteger32(instr->constant_parameter_count()); | 2972 int parameter_count = ToInteger32(instr->constant_parameter_count()); |
| 2966 int32_t sp_delta = (parameter_count + 1) * kPointerSize; | 2973 int32_t sp_delta = (parameter_count + 1) * kPointerSize; |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3194 Register to_reg = ToRegister(instr->result()); | 3201 Register to_reg = ToRegister(instr->result()); |
| 3195 Register from_reg = ToRegister(instr->object()); | 3202 Register from_reg = ToRegister(instr->object()); |
| 3196 __ ldr(to_reg, FieldMemOperand(from_reg, | 3203 __ ldr(to_reg, FieldMemOperand(from_reg, |
| 3197 ExternalArray::kExternalPointerOffset)); | 3204 ExternalArray::kExternalPointerOffset)); |
| 3198 } | 3205 } |
| 3199 | 3206 |
| 3200 | 3207 |
| 3201 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 3208 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
| 3202 Register arguments = ToRegister(instr->arguments()); | 3209 Register arguments = ToRegister(instr->arguments()); |
| 3203 Register result = ToRegister(instr->result()); | 3210 Register result = ToRegister(instr->result()); |
| 3204 if (instr->length()->IsConstantOperand() && | 3211 // There are two words between the frame pointer and the last argument. |
| 3205 instr->index()->IsConstantOperand()) { | 3212 // Subtracting from length accounts for one of them add one more. |
| 3206 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 3213 if (instr->length()->IsConstantOperand()) { |
| 3207 int const_length = ToInteger32(LConstantOperand::cast(instr->length())); | 3214 int const_length = ToInteger32(LConstantOperand::cast(instr->length())); |
| 3208 int index = (const_length - const_index) + 1; | 3215 if (instr->index()->IsConstantOperand()) { |
| 3209 __ ldr(result, MemOperand(arguments, index * kPointerSize)); | 3216 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
| 3210 } else { | 3217 int index = (const_length - const_index) + 1; |
| 3218 __ ldr(result, MemOperand(arguments, index * kPointerSize)); |
| 3219 } else { |
| 3220 Register index = ToRegister(instr->index()); |
| 3221 __ rsb(result, index, Operand(const_length + 1)); |
| 3222 __ ldr(result, MemOperand(arguments, result, LSL, kPointerSizeLog2)); |
| 3223 } |
| 3224 } else if (instr->index()->IsConstantOperand()) { |
| 3225 Register length = ToRegister(instr->length()); |
| 3226 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
| 3227 int loc = const_index - 1; |
| 3228 if (loc != 0) { |
| 3229 __ sub(result, length, Operand(loc)); |
| 3230 __ ldr(result, MemOperand(arguments, result, LSL, kPointerSizeLog2)); |
| 3231 } else { |
| 3232 __ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2)); |
| 3233 } |
| 3234 } else { |
| 3211 Register length = ToRegister(instr->length()); | 3235 Register length = ToRegister(instr->length()); |
| 3212 Register index = ToRegister(instr->index()); | 3236 Register index = ToRegister(instr->index()); |
| 3213 // There are two words between the frame pointer and the last argument. | 3237 __ sub(result, length, index); |
| 3214 // Subtracting from length accounts for one of them add one more. | 3238 __ add(result, result, Operand(1)); |
| 3215 __ sub(length, length, index); | 3239 __ ldr(result, MemOperand(arguments, result, LSL, kPointerSizeLog2)); |
| 3216 __ add(length, length, Operand(1)); | |
| 3217 __ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2)); | |
| 3218 } | 3240 } |
| 3219 } | 3241 } |
| 3220 | 3242 |
| 3221 | 3243 |
| 3222 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { | 3244 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { |
| 3223 Register external_pointer = ToRegister(instr->elements()); | 3245 Register external_pointer = ToRegister(instr->elements()); |
| 3224 Register key = no_reg; | 3246 Register key = no_reg; |
| 3225 ElementsKind elements_kind = instr->elements_kind(); | 3247 ElementsKind elements_kind = instr->elements_kind(); |
| 3226 bool key_is_constant = instr->key()->IsConstantOperand(); | 3248 bool key_is_constant = instr->key()->IsConstantOperand(); |
| 3227 int constant_key = 0; | 3249 int constant_key = 0; |
| (...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3927 MathPowStub stub(MathPowStub::INTEGER); | 3949 MathPowStub stub(MathPowStub::INTEGER); |
| 3928 __ CallStub(&stub); | 3950 __ CallStub(&stub); |
| 3929 } else { | 3951 } else { |
| 3930 ASSERT(exponent_type.IsDouble()); | 3952 ASSERT(exponent_type.IsDouble()); |
| 3931 MathPowStub stub(MathPowStub::DOUBLE); | 3953 MathPowStub stub(MathPowStub::DOUBLE); |
| 3932 __ CallStub(&stub); | 3954 __ CallStub(&stub); |
| 3933 } | 3955 } |
| 3934 } | 3956 } |
| 3935 | 3957 |
| 3936 | 3958 |
| 3937 void LCodeGen::DoRandom(LRandom* instr) { | |
| 3938 // Assert that the register size is indeed the size of each seed. | |
| 3939 static const int kSeedSize = sizeof(uint32_t); | |
| 3940 STATIC_ASSERT(kPointerSize == kSeedSize); | |
| 3941 | |
| 3942 // Load native context | |
| 3943 Register global_object = ToRegister(instr->global_object()); | |
| 3944 Register native_context = global_object; | |
| 3945 __ ldr(native_context, FieldMemOperand( | |
| 3946 global_object, GlobalObject::kNativeContextOffset)); | |
| 3947 | |
| 3948 // Load state (FixedArray of the native context's random seeds) | |
| 3949 static const int kRandomSeedOffset = | |
| 3950 FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; | |
| 3951 Register state = native_context; | |
| 3952 __ ldr(state, FieldMemOperand(native_context, kRandomSeedOffset)); | |
| 3953 | |
| 3954 // Load state[0]. | |
| 3955 Register state0 = ToRegister(instr->scratch()); | |
| 3956 __ ldr(state0, FieldMemOperand(state, ByteArray::kHeaderSize)); | |
| 3957 // Load state[1]. | |
| 3958 Register state1 = ToRegister(instr->scratch2()); | |
| 3959 __ ldr(state1, FieldMemOperand(state, ByteArray::kHeaderSize + kSeedSize)); | |
| 3960 | |
| 3961 // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16) | |
| 3962 Register scratch3 = ToRegister(instr->scratch3()); | |
| 3963 Register scratch4 = scratch0(); | |
| 3964 __ and_(scratch3, state0, Operand(0xFFFF)); | |
| 3965 __ mov(scratch4, Operand(18273)); | |
| 3966 __ mul(scratch3, scratch3, scratch4); | |
| 3967 __ add(state0, scratch3, Operand(state0, LSR, 16)); | |
| 3968 // Save state[0]. | |
| 3969 __ str(state0, FieldMemOperand(state, ByteArray::kHeaderSize)); | |
| 3970 | |
| 3971 // state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16) | |
| 3972 __ and_(scratch3, state1, Operand(0xFFFF)); | |
| 3973 __ mov(scratch4, Operand(36969)); | |
| 3974 __ mul(scratch3, scratch3, scratch4); | |
| 3975 __ add(state1, scratch3, Operand(state1, LSR, 16)); | |
| 3976 // Save state[1]. | |
| 3977 __ str(state1, FieldMemOperand(state, ByteArray::kHeaderSize + kSeedSize)); | |
| 3978 | |
| 3979 // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF) | |
| 3980 Register random = scratch4; | |
| 3981 __ and_(random, state1, Operand(0x3FFFF)); | |
| 3982 __ add(random, random, Operand(state0, LSL, 14)); | |
| 3983 | |
| 3984 // 0x41300000 is the top half of 1.0 x 2^20 as a double. | |
| 3985 // Create this constant using mov/orr to avoid PC relative load. | |
| 3986 __ mov(scratch3, Operand(0x41000000)); | |
| 3987 __ orr(scratch3, scratch3, Operand(0x300000)); | |
| 3988 // Move 0x41300000xxxxxxxx (x = random bits) to VFP. | |
| 3989 DwVfpRegister result = ToDoubleRegister(instr->result()); | |
| 3990 __ vmov(result, random, scratch3); | |
| 3991 // Move 0x4130000000000000 to VFP. | |
| 3992 __ mov(scratch4, Operand::Zero()); | |
| 3993 DwVfpRegister scratch5 = double_scratch0(); | |
| 3994 __ vmov(scratch5, scratch4, scratch3); | |
| 3995 __ vsub(result, result, scratch5); | |
| 3996 } | |
| 3997 | |
| 3998 | |
| 3999 void LCodeGen::DoMathExp(LMathExp* instr) { | 3959 void LCodeGen::DoMathExp(LMathExp* instr) { |
| 4000 DwVfpRegister input = ToDoubleRegister(instr->value()); | 3960 DwVfpRegister input = ToDoubleRegister(instr->value()); |
| 4001 DwVfpRegister result = ToDoubleRegister(instr->result()); | 3961 DwVfpRegister result = ToDoubleRegister(instr->result()); |
| 4002 DwVfpRegister double_scratch1 = ToDoubleRegister(instr->double_temp()); | 3962 DwVfpRegister double_scratch1 = ToDoubleRegister(instr->double_temp()); |
| 4003 DwVfpRegister double_scratch2 = double_scratch0(); | 3963 DwVfpRegister double_scratch2 = double_scratch0(); |
| 4004 Register temp1 = ToRegister(instr->temp1()); | 3964 Register temp1 = ToRegister(instr->temp1()); |
| 4005 Register temp2 = ToRegister(instr->temp2()); | 3965 Register temp2 = ToRegister(instr->temp2()); |
| 4006 | 3966 |
| 4007 MathExpGenerator::EmitMathExp( | 3967 MathExpGenerator::EmitMathExp( |
| 4008 masm(), input, result, double_scratch1, double_scratch2, | 3968 masm(), input, result, double_scratch1, double_scratch2, |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4100 } | 4060 } |
| 4101 | 4061 |
| 4102 | 4062 |
| 4103 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 4063 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
| 4104 ASSERT(ToRegister(instr->context()).is(cp)); | 4064 ASSERT(ToRegister(instr->context()).is(cp)); |
| 4105 ASSERT(ToRegister(instr->function()).is(r1)); | 4065 ASSERT(ToRegister(instr->function()).is(r1)); |
| 4106 ASSERT(ToRegister(instr->result()).is(r0)); | 4066 ASSERT(ToRegister(instr->result()).is(r0)); |
| 4107 | 4067 |
| 4108 int arity = instr->arity(); | 4068 int arity = instr->arity(); |
| 4109 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); | 4069 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); |
| 4110 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4070 if (instr->hydrogen()->IsTailCall()) { |
| 4071 if (NeedsEagerFrame()) __ mov(sp, fp); |
| 4072 __ Jump(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); |
| 4073 } else { |
| 4074 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 4075 } |
| 4111 } | 4076 } |
| 4112 | 4077 |
| 4113 | 4078 |
| 4114 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | 4079 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { |
| 4115 ASSERT(ToRegister(instr->context()).is(cp)); | 4080 ASSERT(ToRegister(instr->context()).is(cp)); |
| 4116 ASSERT(ToRegister(instr->result()).is(r0)); | 4081 ASSERT(ToRegister(instr->result()).is(r0)); |
| 4117 | 4082 |
| 4118 int arity = instr->arity(); | 4083 int arity = instr->arity(); |
| 4119 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; | 4084 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; |
| 4120 Handle<Code> ic = | 4085 Handle<Code> ic = |
| (...skipping 1345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5466 if (instr->size()->IsRegister()) { | 5431 if (instr->size()->IsRegister()) { |
| 5467 Register size = ToRegister(instr->size()); | 5432 Register size = ToRegister(instr->size()); |
| 5468 ASSERT(!size.is(result)); | 5433 ASSERT(!size.is(result)); |
| 5469 __ SmiTag(size); | 5434 __ SmiTag(size); |
| 5470 __ push(size); | 5435 __ push(size); |
| 5471 } else { | 5436 } else { |
| 5472 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 5437 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
| 5473 __ Push(Smi::FromInt(size)); | 5438 __ Push(Smi::FromInt(size)); |
| 5474 } | 5439 } |
| 5475 | 5440 |
| 5441 int flags = AllocateDoubleAlignFlag::encode( |
| 5442 instr->hydrogen()->MustAllocateDoubleAligned()); |
| 5476 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { | 5443 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { |
| 5477 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); | 5444 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); |
| 5478 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5445 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
| 5479 CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr, | 5446 flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE); |
| 5480 instr->context()); | |
| 5481 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { | 5447 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { |
| 5482 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5448 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
| 5483 CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr, | 5449 flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE); |
| 5484 instr->context()); | |
| 5485 } else { | 5450 } else { |
| 5486 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr, | 5451 flags = AllocateTargetSpace::update(flags, NEW_SPACE); |
| 5487 instr->context()); | |
| 5488 } | 5452 } |
| 5453 __ Push(Smi::FromInt(flags)); |
| 5454 |
| 5455 CallRuntimeFromDeferred( |
| 5456 Runtime::kAllocateInTargetSpace, 2, instr, instr->context()); |
| 5489 __ StoreToSafepointRegisterSlot(r0, result); | 5457 __ StoreToSafepointRegisterSlot(r0, result); |
| 5490 } | 5458 } |
| 5491 | 5459 |
| 5492 | 5460 |
| 5493 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 5461 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
| 5494 ASSERT(ToRegister(instr->value()).is(r0)); | 5462 ASSERT(ToRegister(instr->value()).is(r0)); |
| 5495 __ push(r0); | 5463 __ push(r0); |
| 5496 CallRuntime(Runtime::kToFastProperties, 1, instr); | 5464 CallRuntime(Runtime::kToFastProperties, 1, instr); |
| 5497 } | 5465 } |
| 5498 | 5466 |
| (...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5910 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5878 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
| 5911 __ ldr(result, FieldMemOperand(scratch, | 5879 __ ldr(result, FieldMemOperand(scratch, |
| 5912 FixedArray::kHeaderSize - kPointerSize)); | 5880 FixedArray::kHeaderSize - kPointerSize)); |
| 5913 __ bind(&done); | 5881 __ bind(&done); |
| 5914 } | 5882 } |
| 5915 | 5883 |
| 5916 | 5884 |
| 5917 #undef __ | 5885 #undef __ |
| 5918 | 5886 |
| 5919 } } // namespace v8::internal | 5887 } } // namespace v8::internal |
| OLD | NEW |