Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(249)

Side by Side Diff: src/arm/lithium-codegen-arm.cc

Issue 110573004: Merge bleeding_edge 17696:18016. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698