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

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

Issue 143633007: A64: Synchronize with r18764. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months 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
« no previous file with comments | « src/x64/ic-x64.cc ('k') | src/x64/lithium-gap-resolver-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 void LChunkBuilder::Abort(BailoutReason reason) { 96 void LChunkBuilder::Abort(BailoutReason reason) {
97 info()->set_bailout_reason(reason); 97 info()->set_bailout_reason(reason);
98 status_ = ABORTED; 98 status_ = ABORTED;
99 } 99 }
100 100
101 101
102 #ifdef _MSC_VER 102 #ifdef _MSC_VER
103 void LCodeGen::MakeSureStackPagesMapped(int offset) { 103 void LCodeGen::MakeSureStackPagesMapped(int offset) {
104 const int kPageSize = 4 * KB; 104 const int kPageSize = 4 * KB;
105 for (offset -= kPageSize; offset > 0; offset -= kPageSize) { 105 for (offset -= kPageSize; offset > 0; offset -= kPageSize) {
106 __ movq(Operand(rsp, offset), rax); 106 __ movp(Operand(rsp, offset), rax);
107 } 107 }
108 } 108 }
109 #endif 109 #endif
110 110
111 111
112 void LCodeGen::SaveCallerDoubles() { 112 void LCodeGen::SaveCallerDoubles() {
113 ASSERT(info()->saves_caller_doubles()); 113 ASSERT(info()->saves_caller_doubles());
114 ASSERT(NeedsEagerFrame()); 114 ASSERT(NeedsEagerFrame());
115 Comment(";;; Save clobbered callee double registers"); 115 Comment(";;; Save clobbered callee double registers");
116 int count = 0; 116 int count = 0;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 } 154 }
155 #endif 155 #endif
156 156
157 // Classic mode functions need to replace the receiver with the global proxy 157 // Classic mode functions need to replace the receiver with the global proxy
158 // when called as functions (without an explicit receiver object). 158 // when called as functions (without an explicit receiver object).
159 if (info_->this_has_uses() && 159 if (info_->this_has_uses() &&
160 info_->is_classic_mode() && 160 info_->is_classic_mode() &&
161 !info_->is_native()) { 161 !info_->is_native()) {
162 Label ok; 162 Label ok;
163 StackArgumentsAccessor args(rsp, scope()->num_parameters()); 163 StackArgumentsAccessor args(rsp, scope()->num_parameters());
164 __ movq(rcx, args.GetReceiverOperand()); 164 __ movp(rcx, args.GetReceiverOperand());
165 165
166 __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex); 166 __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex);
167 __ j(not_equal, &ok, Label::kNear); 167 __ j(not_equal, &ok, Label::kNear);
168 168
169 __ movq(rcx, GlobalObjectOperand()); 169 __ movp(rcx, GlobalObjectOperand());
170 __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); 170 __ movp(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
171 171
172 __ movq(args.GetReceiverOperand(), rcx); 172 __ movp(args.GetReceiverOperand(), rcx);
173 173
174 __ bind(&ok); 174 __ bind(&ok);
175 } 175 }
176 } 176 }
177 177
178 info()->set_prologue_offset(masm_->pc_offset()); 178 info()->set_prologue_offset(masm_->pc_offset());
179 if (NeedsEagerFrame()) { 179 if (NeedsEagerFrame()) {
180 ASSERT(!frame_is_built_); 180 ASSERT(!frame_is_built_);
181 frame_is_built_ = true; 181 frame_is_built_ = true;
182 __ Prologue(info()->IsStub() ? BUILD_STUB_FRAME : BUILD_FUNCTION_FRAME); 182 __ Prologue(info()->IsStub() ? BUILD_STUB_FRAME : BUILD_FUNCTION_FRAME);
183 info()->AddNoFrameRange(0, masm_->pc_offset()); 183 info()->AddNoFrameRange(0, masm_->pc_offset());
184 } 184 }
185 185
186 // Reserve space for the stack slots needed by the code. 186 // Reserve space for the stack slots needed by the code.
187 int slots = GetStackSlotCount(); 187 int slots = GetStackSlotCount();
188 if (slots > 0) { 188 if (slots > 0) {
189 if (FLAG_debug_code) { 189 if (FLAG_debug_code) {
190 __ subq(rsp, Immediate(slots * kPointerSize)); 190 __ subq(rsp, Immediate(slots * kPointerSize));
191 #ifdef _MSC_VER 191 #ifdef _MSC_VER
192 MakeSureStackPagesMapped(slots * kPointerSize); 192 MakeSureStackPagesMapped(slots * kPointerSize);
193 #endif 193 #endif
194 __ push(rax); 194 __ push(rax);
195 __ Set(rax, slots); 195 __ Set(rax, slots);
196 __ movq(kScratchRegister, kSlotsZapValue); 196 __ movq(kScratchRegister, kSlotsZapValue);
197 Label loop; 197 Label loop;
198 __ bind(&loop); 198 __ bind(&loop);
199 __ movq(MemOperand(rsp, rax, times_pointer_size, 0), 199 __ movp(MemOperand(rsp, rax, times_pointer_size, 0),
200 kScratchRegister); 200 kScratchRegister);
201 __ decl(rax); 201 __ decl(rax);
202 __ j(not_zero, &loop); 202 __ j(not_zero, &loop);
203 __ pop(rax); 203 __ pop(rax);
204 } else { 204 } else {
205 __ subq(rsp, Immediate(slots * kPointerSize)); 205 __ subq(rsp, Immediate(slots * kPointerSize));
206 #ifdef _MSC_VER 206 #ifdef _MSC_VER
207 MakeSureStackPagesMapped(slots * kPointerSize); 207 MakeSureStackPagesMapped(slots * kPointerSize);
208 #endif 208 #endif
209 } 209 }
210 210
211 if (info()->saves_caller_doubles()) { 211 if (info()->saves_caller_doubles()) {
212 SaveCallerDoubles(); 212 SaveCallerDoubles();
213 } 213 }
214 } 214 }
215 215
216 // Possibly allocate a local context. 216 // Possibly allocate a local context.
217 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 217 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
218 if (heap_slots > 0) { 218 if (heap_slots > 0) {
219 Comment(";;; Allocate local context"); 219 Comment(";;; Allocate local context");
220 // Argument to NewContext is the function, which is still in rdi. 220 // Argument to NewContext is the function, which is still in rdi.
221 __ push(rdi);
222 if (heap_slots <= FastNewContextStub::kMaximumSlots) { 221 if (heap_slots <= FastNewContextStub::kMaximumSlots) {
223 FastNewContextStub stub(heap_slots); 222 FastNewContextStub stub(heap_slots);
224 __ CallStub(&stub); 223 __ CallStub(&stub);
225 } else { 224 } else {
225 __ push(rdi);
226 __ CallRuntime(Runtime::kNewFunctionContext, 1); 226 __ CallRuntime(Runtime::kNewFunctionContext, 1);
227 } 227 }
228 RecordSafepoint(Safepoint::kNoLazyDeopt); 228 RecordSafepoint(Safepoint::kNoLazyDeopt);
229 // Context is returned in both rax and rsi. It replaces the context 229 // Context is returned in rax. It replaces the context passed to us.
230 // passed to us. It's saved in the stack and kept live in rsi. 230 // It's saved in the stack and kept live in rsi.
231 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 231 __ movp(rsi, rax);
232 __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax);
232 233
233 // Copy any necessary parameters into the context. 234 // Copy any necessary parameters into the context.
234 int num_parameters = scope()->num_parameters(); 235 int num_parameters = scope()->num_parameters();
235 for (int i = 0; i < num_parameters; i++) { 236 for (int i = 0; i < num_parameters; i++) {
236 Variable* var = scope()->parameter(i); 237 Variable* var = scope()->parameter(i);
237 if (var->IsContextSlot()) { 238 if (var->IsContextSlot()) {
238 int parameter_offset = StandardFrameConstants::kCallerSPOffset + 239 int parameter_offset = StandardFrameConstants::kCallerSPOffset +
239 (num_parameters - 1 - i) * kPointerSize; 240 (num_parameters - 1 - i) * kPointerSize;
240 // Load parameter from stack. 241 // Load parameter from stack.
241 __ movq(rax, Operand(rbp, parameter_offset)); 242 __ movp(rax, Operand(rbp, parameter_offset));
242 // Store it in the context. 243 // Store it in the context.
243 int context_offset = Context::SlotOffset(var->index()); 244 int context_offset = Context::SlotOffset(var->index());
244 __ movq(Operand(rsi, context_offset), rax); 245 __ movp(Operand(rsi, context_offset), rax);
245 // Update the write barrier. This clobbers rax and rbx. 246 // Update the write barrier. This clobbers rax and rbx.
246 __ RecordWriteContextSlot(rsi, context_offset, rax, rbx, kSaveFPRegs); 247 __ RecordWriteContextSlot(rsi, context_offset, rax, rbx, kSaveFPRegs);
247 } 248 }
248 } 249 }
249 Comment(";;; End allocate local context"); 250 Comment(";;; End allocate local context");
250 } 251 }
251 252
252 // Trace the call. 253 // Trace the call.
253 if (FLAG_trace && info()->IsOptimizing()) { 254 if (FLAG_trace && info()->IsOptimizing()) {
254 __ CallRuntime(Runtime::kTraceEnter, 0); 255 __ CallRuntime(Runtime::kTraceEnter, 0);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 } else { 288 } else {
288 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); 289 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id);
289 } 290 }
290 if (jump_table_[i].needs_frame) { 291 if (jump_table_[i].needs_frame) {
291 ASSERT(!info()->saves_caller_doubles()); 292 ASSERT(!info()->saves_caller_doubles());
292 __ Move(kScratchRegister, ExternalReference::ForDeoptEntry(entry)); 293 __ Move(kScratchRegister, ExternalReference::ForDeoptEntry(entry));
293 if (needs_frame.is_bound()) { 294 if (needs_frame.is_bound()) {
294 __ jmp(&needs_frame); 295 __ jmp(&needs_frame);
295 } else { 296 } else {
296 __ bind(&needs_frame); 297 __ bind(&needs_frame);
297 __ movq(rsi, MemOperand(rbp, StandardFrameConstants::kContextOffset)); 298 __ movp(rsi, MemOperand(rbp, StandardFrameConstants::kContextOffset));
298 __ push(rbp); 299 __ push(rbp);
299 __ movq(rbp, rsp); 300 __ movp(rbp, rsp);
300 __ push(rsi); 301 __ push(rsi);
301 // This variant of deopt can only be used with stubs. Since we don't 302 // This variant of deopt can only be used with stubs. Since we don't
302 // have a function pointer to install in the stack frame that we're 303 // have a function pointer to install in the stack frame that we're
303 // building, install a special marker there instead. 304 // building, install a special marker there instead.
304 ASSERT(info()->IsStub()); 305 ASSERT(info()->IsStub());
305 __ Move(rsi, Smi::FromInt(StackFrame::STUB)); 306 __ Move(rsi, Smi::FromInt(StackFrame::STUB));
306 __ push(rsi); 307 __ push(rsi);
307 __ movq(rsi, MemOperand(rsp, kPointerSize)); 308 __ movp(rsi, MemOperand(rsp, kPointerSize));
308 __ call(kScratchRegister); 309 __ call(kScratchRegister);
309 } 310 }
310 } else { 311 } else {
311 if (info()->saves_caller_doubles()) { 312 if (info()->saves_caller_doubles()) {
312 ASSERT(info()->IsStub()); 313 ASSERT(info()->IsStub());
313 RestoreCallerDoubles(); 314 RestoreCallerDoubles();
314 } 315 }
315 __ call(entry, RelocInfo::RUNTIME_ENTRY); 316 __ call(entry, RelocInfo::RUNTIME_ENTRY);
316 } 317 }
317 } 318 }
(...skipping 28 matching lines...) Expand all
346 __ Push(Smi::FromInt(StackFrame::STUB)); 347 __ Push(Smi::FromInt(StackFrame::STUB));
347 __ lea(rbp, Operand(rsp, 2 * kPointerSize)); 348 __ lea(rbp, Operand(rsp, 2 * kPointerSize));
348 Comment(";;; Deferred code"); 349 Comment(";;; Deferred code");
349 } 350 }
350 code->Generate(); 351 code->Generate();
351 if (NeedsDeferredFrame()) { 352 if (NeedsDeferredFrame()) {
352 __ bind(code->done()); 353 __ bind(code->done());
353 Comment(";;; Destroy frame"); 354 Comment(";;; Destroy frame");
354 ASSERT(frame_is_built_); 355 ASSERT(frame_is_built_);
355 frame_is_built_ = false; 356 frame_is_built_ = false;
356 __ movq(rsp, rbp); 357 __ movp(rsp, rbp);
357 __ pop(rbp); 358 __ pop(rbp);
358 } 359 }
359 __ jmp(code->exit()); 360 __ jmp(code->exit());
360 } 361 }
361 } 362 }
362 363
363 // Deferred code is the last part of the instruction sequence. Mark 364 // Deferred code is the last part of the instruction sequence. Mark
364 // the generated code as done unless we bailed out. 365 // the generated code as done unless we bailed out.
365 if (!is_aborted()) status_ = DONE; 366 if (!is_aborted()) status_ = DONE;
366 return !is_aborted(); 367 return !is_aborted();
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 630
630 __ CallRuntime(function, num_arguments, save_doubles); 631 __ CallRuntime(function, num_arguments, save_doubles);
631 632
632 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); 633 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0);
633 } 634 }
634 635
635 636
636 void LCodeGen::LoadContextFromDeferred(LOperand* context) { 637 void LCodeGen::LoadContextFromDeferred(LOperand* context) {
637 if (context->IsRegister()) { 638 if (context->IsRegister()) {
638 if (!ToRegister(context).is(rsi)) { 639 if (!ToRegister(context).is(rsi)) {
639 __ movq(rsi, ToRegister(context)); 640 __ movp(rsi, ToRegister(context));
640 } 641 }
641 } else if (context->IsStackSlot()) { 642 } else if (context->IsStackSlot()) {
642 __ movq(rsi, ToOperand(context)); 643 __ movp(rsi, ToOperand(context));
643 } else if (context->IsConstantOperand()) { 644 } else if (context->IsConstantOperand()) {
644 HConstant* constant = 645 HConstant* constant =
645 chunk_->LookupConstant(LConstantOperand::cast(context)); 646 chunk_->LookupConstant(LConstantOperand::cast(context));
646 __ Move(rsi, Handle<Object>::cast(constant->handle(isolate()))); 647 __ Move(rsi, Handle<Object>::cast(constant->handle(isolate())));
647 } else { 648 } else {
648 UNREACHABLE(); 649 UNREACHABLE();
649 } 650 }
650 } 651 }
651 652
652 653
(...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after
1261 } 1262 }
1262 } 1263 }
1263 1264
1264 1265
1265 void LCodeGen::DoMulI(LMulI* instr) { 1266 void LCodeGen::DoMulI(LMulI* instr) {
1266 Register left = ToRegister(instr->left()); 1267 Register left = ToRegister(instr->left());
1267 LOperand* right = instr->right(); 1268 LOperand* right = instr->right();
1268 1269
1269 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1270 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1270 if (instr->hydrogen_value()->representation().IsSmi()) { 1271 if (instr->hydrogen_value()->representation().IsSmi()) {
1271 __ movq(kScratchRegister, left); 1272 __ movp(kScratchRegister, left);
1272 } else { 1273 } else {
1273 __ movl(kScratchRegister, left); 1274 __ movl(kScratchRegister, left);
1274 } 1275 }
1275 } 1276 }
1276 1277
1277 bool can_overflow = 1278 bool can_overflow =
1278 instr->hydrogen()->CheckFlag(HValue::kCanOverflow); 1279 instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1279 if (right->IsConstantOperand()) { 1280 if (right->IsConstantOperand()) {
1280 int32_t right_value = ToInteger32(LConstantOperand::cast(right)); 1281 int32_t right_value = ToInteger32(LConstantOperand::cast(right));
1281 if (right_value == -1) { 1282 if (right_value == -1) {
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
1576 Register map = ToRegister(instr->value()); 1577 Register map = ToRegister(instr->value());
1577 __ EnumLength(result, map); 1578 __ EnumLength(result, map);
1578 } 1579 }
1579 1580
1580 1581
1581 void LCodeGen::DoElementsKind(LElementsKind* instr) { 1582 void LCodeGen::DoElementsKind(LElementsKind* instr) {
1582 Register result = ToRegister(instr->result()); 1583 Register result = ToRegister(instr->result());
1583 Register input = ToRegister(instr->value()); 1584 Register input = ToRegister(instr->value());
1584 1585
1585 // Load map into |result|. 1586 // Load map into |result|.
1586 __ movq(result, FieldOperand(input, HeapObject::kMapOffset)); 1587 __ movp(result, FieldOperand(input, HeapObject::kMapOffset));
1587 // Load the map's "bit field 2" into |result|. We only need the first byte. 1588 // Load the map's "bit field 2" into |result|. We only need the first byte.
1588 __ movzxbq(result, FieldOperand(result, Map::kBitField2Offset)); 1589 __ movzxbq(result, FieldOperand(result, Map::kBitField2Offset));
1589 // Retrieve elements_kind from bit field 2. 1590 // Retrieve elements_kind from bit field 2.
1590 __ and_(result, Immediate(Map::kElementsKindMask)); 1591 __ and_(result, Immediate(Map::kElementsKindMask));
1591 __ shr(result, Immediate(Map::kElementsKindShift)); 1592 __ shr(result, Immediate(Map::kElementsKindShift));
1592 } 1593 }
1593 1594
1594 1595
1595 void LCodeGen::DoValueOf(LValueOf* instr) { 1596 void LCodeGen::DoValueOf(LValueOf* instr) {
1596 Register input = ToRegister(instr->value()); 1597 Register input = ToRegister(instr->value());
1597 Register result = ToRegister(instr->result()); 1598 Register result = ToRegister(instr->result());
1598 ASSERT(input.is(result)); 1599 ASSERT(input.is(result));
1599 Label done; 1600 Label done;
1600 1601
1601 if (!instr->hydrogen()->value()->IsHeapObject()) { 1602 if (!instr->hydrogen()->value()->IsHeapObject()) {
1602 // If the object is a smi return the object. 1603 // If the object is a smi return the object.
1603 __ JumpIfSmi(input, &done, Label::kNear); 1604 __ JumpIfSmi(input, &done, Label::kNear);
1604 } 1605 }
1605 1606
1606 // If the object is not a value type, return the object. 1607 // If the object is not a value type, return the object.
1607 __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister); 1608 __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister);
1608 __ j(not_equal, &done, Label::kNear); 1609 __ j(not_equal, &done, Label::kNear);
1609 __ movq(result, FieldOperand(input, JSValue::kValueOffset)); 1610 __ movp(result, FieldOperand(input, JSValue::kValueOffset));
1610 1611
1611 __ bind(&done); 1612 __ bind(&done);
1612 } 1613 }
1613 1614
1614 1615
1615 void LCodeGen::DoDateField(LDateField* instr) { 1616 void LCodeGen::DoDateField(LDateField* instr) {
1616 Register object = ToRegister(instr->date()); 1617 Register object = ToRegister(instr->date());
1617 Register result = ToRegister(instr->result()); 1618 Register result = ToRegister(instr->result());
1618 Smi* index = instr->index(); 1619 Smi* index = instr->index();
1619 Label runtime, done, not_date_object; 1620 Label runtime, done, not_date_object;
1620 ASSERT(object.is(result)); 1621 ASSERT(object.is(result));
1621 ASSERT(object.is(rax)); 1622 ASSERT(object.is(rax));
1622 1623
1623 Condition cc = masm()->CheckSmi(object); 1624 Condition cc = masm()->CheckSmi(object);
1624 DeoptimizeIf(cc, instr->environment()); 1625 DeoptimizeIf(cc, instr->environment());
1625 __ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister); 1626 __ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister);
1626 DeoptimizeIf(not_equal, instr->environment()); 1627 DeoptimizeIf(not_equal, instr->environment());
1627 1628
1628 if (index->value() == 0) { 1629 if (index->value() == 0) {
1629 __ movq(result, FieldOperand(object, JSDate::kValueOffset)); 1630 __ movp(result, FieldOperand(object, JSDate::kValueOffset));
1630 } else { 1631 } else {
1631 if (index->value() < JSDate::kFirstUncachedField) { 1632 if (index->value() < JSDate::kFirstUncachedField) {
1632 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 1633 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
1633 Operand stamp_operand = __ ExternalOperand(stamp); 1634 Operand stamp_operand = __ ExternalOperand(stamp);
1634 __ movq(kScratchRegister, stamp_operand); 1635 __ movp(kScratchRegister, stamp_operand);
1635 __ cmpq(kScratchRegister, FieldOperand(object, 1636 __ cmpq(kScratchRegister, FieldOperand(object,
1636 JSDate::kCacheStampOffset)); 1637 JSDate::kCacheStampOffset));
1637 __ j(not_equal, &runtime, Label::kNear); 1638 __ j(not_equal, &runtime, Label::kNear);
1638 __ movq(result, FieldOperand(object, JSDate::kValueOffset + 1639 __ movp(result, FieldOperand(object, JSDate::kValueOffset +
1639 kPointerSize * index->value())); 1640 kPointerSize * index->value()));
1640 __ jmp(&done, Label::kNear); 1641 __ jmp(&done, Label::kNear);
1641 } 1642 }
1642 __ bind(&runtime); 1643 __ bind(&runtime);
1643 __ PrepareCallCFunction(2); 1644 __ PrepareCallCFunction(2);
1644 __ movq(arg_reg_1, object); 1645 __ movp(arg_reg_1, object);
1645 __ Move(arg_reg_2, index, RelocInfo::NONE64); 1646 __ Move(arg_reg_2, index, RelocInfo::NONE64);
1646 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); 1647 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
1647 __ bind(&done); 1648 __ bind(&done);
1648 } 1649 }
1649 } 1650 }
1650 1651
1651 1652
1652 Operand LCodeGen::BuildSeqStringOperand(Register string, 1653 Operand LCodeGen::BuildSeqStringOperand(Register string,
1653 LOperand* index, 1654 LOperand* index,
1654 String::Encoding encoding) { 1655 String::Encoding encoding) {
(...skipping 12 matching lines...) Expand all
1667 } 1668 }
1668 1669
1669 1670
1670 void LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) { 1671 void LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) {
1671 String::Encoding encoding = instr->hydrogen()->encoding(); 1672 String::Encoding encoding = instr->hydrogen()->encoding();
1672 Register result = ToRegister(instr->result()); 1673 Register result = ToRegister(instr->result());
1673 Register string = ToRegister(instr->string()); 1674 Register string = ToRegister(instr->string());
1674 1675
1675 if (FLAG_debug_code) { 1676 if (FLAG_debug_code) {
1676 __ push(string); 1677 __ push(string);
1677 __ movq(string, FieldOperand(string, HeapObject::kMapOffset)); 1678 __ movp(string, FieldOperand(string, HeapObject::kMapOffset));
1678 __ movzxbq(string, FieldOperand(string, Map::kInstanceTypeOffset)); 1679 __ movzxbq(string, FieldOperand(string, Map::kInstanceTypeOffset));
1679 1680
1680 __ andb(string, Immediate(kStringRepresentationMask | kStringEncodingMask)); 1681 __ andb(string, Immediate(kStringRepresentationMask | kStringEncodingMask));
1681 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; 1682 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
1682 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; 1683 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
1683 __ cmpq(string, Immediate(encoding == String::ONE_BYTE_ENCODING 1684 __ cmpq(string, Immediate(encoding == String::ONE_BYTE_ENCODING
1684 ? one_byte_seq_type : two_byte_seq_type)); 1685 ? one_byte_seq_type : two_byte_seq_type));
1685 __ Check(equal, kUnexpectedStringType); 1686 __ Check(equal, kUnexpectedStringType);
1686 __ pop(string); 1687 __ pop(string);
1687 } 1688 }
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1808 Condition condition = (operation == HMathMinMax::kMathMin) 1809 Condition condition = (operation == HMathMinMax::kMathMin)
1809 ? less_equal 1810 ? less_equal
1810 : greater_equal; 1811 : greater_equal;
1811 Register left_reg = ToRegister(left); 1812 Register left_reg = ToRegister(left);
1812 if (right->IsConstantOperand()) { 1813 if (right->IsConstantOperand()) {
1813 Immediate right_imm = 1814 Immediate right_imm =
1814 Immediate(ToInteger32(LConstantOperand::cast(right))); 1815 Immediate(ToInteger32(LConstantOperand::cast(right)));
1815 ASSERT(!instr->hydrogen_value()->representation().IsSmi()); 1816 ASSERT(!instr->hydrogen_value()->representation().IsSmi());
1816 __ cmpl(left_reg, right_imm); 1817 __ cmpl(left_reg, right_imm);
1817 __ j(condition, &return_left, Label::kNear); 1818 __ j(condition, &return_left, Label::kNear);
1818 __ movq(left_reg, right_imm); 1819 __ movp(left_reg, right_imm);
1819 } else if (right->IsRegister()) { 1820 } else if (right->IsRegister()) {
1820 Register right_reg = ToRegister(right); 1821 Register right_reg = ToRegister(right);
1821 if (instr->hydrogen_value()->representation().IsSmi()) { 1822 if (instr->hydrogen_value()->representation().IsSmi()) {
1822 __ cmpq(left_reg, right_reg); 1823 __ cmpq(left_reg, right_reg);
1823 } else { 1824 } else {
1824 __ cmpl(left_reg, right_reg); 1825 __ cmpl(left_reg, right_reg);
1825 } 1826 }
1826 __ j(condition, &return_left, Label::kNear); 1827 __ j(condition, &return_left, Label::kNear);
1827 __ movq(left_reg, right_reg); 1828 __ movp(left_reg, right_reg);
1828 } else { 1829 } else {
1829 Operand right_op = ToOperand(right); 1830 Operand right_op = ToOperand(right);
1830 if (instr->hydrogen_value()->representation().IsSmi()) { 1831 if (instr->hydrogen_value()->representation().IsSmi()) {
1831 __ cmpq(left_reg, right_op); 1832 __ cmpq(left_reg, right_op);
1832 } else { 1833 } else {
1833 __ cmpl(left_reg, right_op); 1834 __ cmpl(left_reg, right_op);
1834 } 1835 }
1835 __ j(condition, &return_left, Label::kNear); 1836 __ j(condition, &return_left, Label::kNear);
1836 __ movq(left_reg, right_op); 1837 __ movp(left_reg, right_op);
1837 } 1838 }
1838 __ bind(&return_left); 1839 __ bind(&return_left);
1839 } else { 1840 } else {
1840 ASSERT(instr->hydrogen()->representation().IsDouble()); 1841 ASSERT(instr->hydrogen()->representation().IsDouble());
1841 Label check_nan_left, check_zero, return_left, return_right; 1842 Label check_nan_left, check_zero, return_left, return_right;
1842 Condition condition = (operation == HMathMinMax::kMathMin) ? below : above; 1843 Condition condition = (operation == HMathMinMax::kMathMin) ? below : above;
1843 XMMRegister left_reg = ToDoubleRegister(left); 1844 XMMRegister left_reg = ToDoubleRegister(left);
1844 XMMRegister right_reg = ToDoubleRegister(right); 1845 XMMRegister right_reg = ToDoubleRegister(right);
1845 __ ucomisd(left_reg, right_reg); 1846 __ ucomisd(left_reg, right_reg);
1846 __ j(parity_even, &check_nan_left, Label::kNear); // At least one NaN. 1847 __ j(parity_even, &check_nan_left, Label::kNear); // At least one NaN.
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
2032 __ j(equal, instr->FalseLabel(chunk_)); 2033 __ j(equal, instr->FalseLabel(chunk_));
2033 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); 2034 __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
2034 } else if (expected.NeedsMap()) { 2035 } else if (expected.NeedsMap()) {
2035 // If we need a map later and have a Smi -> deopt. 2036 // If we need a map later and have a Smi -> deopt.
2036 __ testb(reg, Immediate(kSmiTagMask)); 2037 __ testb(reg, Immediate(kSmiTagMask));
2037 DeoptimizeIf(zero, instr->environment()); 2038 DeoptimizeIf(zero, instr->environment());
2038 } 2039 }
2039 2040
2040 const Register map = kScratchRegister; 2041 const Register map = kScratchRegister;
2041 if (expected.NeedsMap()) { 2042 if (expected.NeedsMap()) {
2042 __ movq(map, FieldOperand(reg, HeapObject::kMapOffset)); 2043 __ movp(map, FieldOperand(reg, HeapObject::kMapOffset));
2043 2044
2044 if (expected.CanBeUndetectable()) { 2045 if (expected.CanBeUndetectable()) {
2045 // Undetectable -> false. 2046 // Undetectable -> false.
2046 __ testb(FieldOperand(map, Map::kBitFieldOffset), 2047 __ testb(FieldOperand(map, Map::kBitFieldOffset),
2047 Immediate(1 << Map::kIsUndetectable)); 2048 Immediate(1 << Map::kIsUndetectable));
2048 __ j(not_zero, instr->FalseLabel(chunk_)); 2049 __ j(not_zero, instr->FalseLabel(chunk_));
2049 } 2050 }
2050 } 2051 }
2051 2052
2052 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { 2053 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) {
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
2266 Condition LCodeGen::EmitIsObject(Register input, 2267 Condition LCodeGen::EmitIsObject(Register input,
2267 Label* is_not_object, 2268 Label* is_not_object,
2268 Label* is_object) { 2269 Label* is_object) {
2269 ASSERT(!input.is(kScratchRegister)); 2270 ASSERT(!input.is(kScratchRegister));
2270 2271
2271 __ JumpIfSmi(input, is_not_object); 2272 __ JumpIfSmi(input, is_not_object);
2272 2273
2273 __ CompareRoot(input, Heap::kNullValueRootIndex); 2274 __ CompareRoot(input, Heap::kNullValueRootIndex);
2274 __ j(equal, is_object); 2275 __ j(equal, is_object);
2275 2276
2276 __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); 2277 __ movp(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset));
2277 // Undetectable objects behave like undefined. 2278 // Undetectable objects behave like undefined.
2278 __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset), 2279 __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset),
2279 Immediate(1 << Map::kIsUndetectable)); 2280 Immediate(1 << Map::kIsUndetectable));
2280 __ j(not_zero, is_not_object); 2281 __ j(not_zero, is_not_object);
2281 2282
2282 __ movzxbl(kScratchRegister, 2283 __ movzxbl(kScratchRegister,
2283 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); 2284 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset));
2284 __ cmpb(kScratchRegister, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2285 __ cmpb(kScratchRegister, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2285 __ j(below, is_not_object); 2286 __ j(below, is_not_object);
2286 __ cmpb(kScratchRegister, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2287 __ cmpb(kScratchRegister, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2340 } 2341 }
2341 2342
2342 2343
2343 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { 2344 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
2344 Register input = ToRegister(instr->value()); 2345 Register input = ToRegister(instr->value());
2345 Register temp = ToRegister(instr->temp()); 2346 Register temp = ToRegister(instr->temp());
2346 2347
2347 if (!instr->hydrogen()->value()->IsHeapObject()) { 2348 if (!instr->hydrogen()->value()->IsHeapObject()) {
2348 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); 2349 __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2349 } 2350 }
2350 __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); 2351 __ movp(temp, FieldOperand(input, HeapObject::kMapOffset));
2351 __ testb(FieldOperand(temp, Map::kBitFieldOffset), 2352 __ testb(FieldOperand(temp, Map::kBitFieldOffset),
2352 Immediate(1 << Map::kIsUndetectable)); 2353 Immediate(1 << Map::kIsUndetectable));
2353 EmitBranch(instr, not_zero); 2354 EmitBranch(instr, not_zero);
2354 } 2355 }
2355 2356
2356 2357
2357 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { 2358 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) {
2358 ASSERT(ToRegister(instr->context()).is(rsi)); 2359 ASSERT(ToRegister(instr->context()).is(rsi));
2359 Token::Value op = instr->op(); 2360 Token::Value op = instr->op();
2360 2361
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
2446 LAST_SPEC_OBJECT_TYPE - 1); 2447 LAST_SPEC_OBJECT_TYPE - 1);
2447 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 2448 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
2448 __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp); 2449 __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp);
2449 __ j(below, is_false); 2450 __ j(below, is_false);
2450 __ j(equal, is_true); 2451 __ j(equal, is_true);
2451 __ CmpInstanceType(temp, LAST_SPEC_OBJECT_TYPE); 2452 __ CmpInstanceType(temp, LAST_SPEC_OBJECT_TYPE);
2452 __ j(equal, is_true); 2453 __ j(equal, is_true);
2453 } else { 2454 } else {
2454 // Faster code path to avoid two compares: subtract lower bound from the 2455 // Faster code path to avoid two compares: subtract lower bound from the
2455 // actual type and do a signed compare with the width of the type range. 2456 // actual type and do a signed compare with the width of the type range.
2456 __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); 2457 __ movp(temp, FieldOperand(input, HeapObject::kMapOffset));
2457 __ movzxbl(temp2, FieldOperand(temp, Map::kInstanceTypeOffset)); 2458 __ movzxbl(temp2, FieldOperand(temp, Map::kInstanceTypeOffset));
2458 __ subq(temp2, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2459 __ subq(temp2, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2459 __ cmpq(temp2, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - 2460 __ cmpq(temp2, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
2460 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2461 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2461 __ j(above, is_false); 2462 __ j(above, is_false);
2462 } 2463 }
2463 2464
2464 // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range. 2465 // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.
2465 // Check if the constructor in the map is a function. 2466 // Check if the constructor in the map is a function.
2466 __ movq(temp, FieldOperand(temp, Map::kConstructorOffset)); 2467 __ movp(temp, FieldOperand(temp, Map::kConstructorOffset));
2467 2468
2468 // Objects with a non-function constructor have class 'Object'. 2469 // Objects with a non-function constructor have class 'Object'.
2469 __ CmpObjectType(temp, JS_FUNCTION_TYPE, kScratchRegister); 2470 __ CmpObjectType(temp, JS_FUNCTION_TYPE, kScratchRegister);
2470 if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Object"))) { 2471 if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Object"))) {
2471 __ j(not_equal, is_true); 2472 __ j(not_equal, is_true);
2472 } else { 2473 } else {
2473 __ j(not_equal, is_false); 2474 __ j(not_equal, is_false);
2474 } 2475 }
2475 2476
2476 // temp now contains the constructor function. Grab the 2477 // temp now contains the constructor function. Grab the
2477 // instance class name from there. 2478 // instance class name from there.
2478 __ movq(temp, FieldOperand(temp, JSFunction::kSharedFunctionInfoOffset)); 2479 __ movp(temp, FieldOperand(temp, JSFunction::kSharedFunctionInfoOffset));
2479 __ movq(temp, FieldOperand(temp, 2480 __ movp(temp, FieldOperand(temp,
2480 SharedFunctionInfo::kInstanceClassNameOffset)); 2481 SharedFunctionInfo::kInstanceClassNameOffset));
2481 // The class name we are testing against is internalized since it's a literal. 2482 // The class name we are testing against is internalized since it's a literal.
2482 // The name in the constructor is internalized because of the way the context 2483 // The name in the constructor is internalized because of the way the context
2483 // is booted. This routine isn't expected to work for random API-created 2484 // is booted. This routine isn't expected to work for random API-created
2484 // classes and it doesn't have to because you can't access it with natives 2485 // classes and it doesn't have to because you can't access it with natives
2485 // syntax. Since both sides are internalized it is sufficient to use an 2486 // syntax. Since both sides are internalized it is sufficient to use an
2486 // identity comparison. 2487 // identity comparison.
2487 ASSERT(class_name->IsInternalizedString()); 2488 ASSERT(class_name->IsInternalizedString());
2488 __ Cmp(temp, class_name); 2489 __ Cmp(temp, class_name);
2489 // End with the answer in the z flag. 2490 // End with the answer in the z flag.
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
2553 2554
2554 // A Smi is not an instance of anything. 2555 // A Smi is not an instance of anything.
2555 __ JumpIfSmi(object, &false_result, Label::kNear); 2556 __ JumpIfSmi(object, &false_result, Label::kNear);
2556 2557
2557 // This is the inlined call site instanceof cache. The two occurences of the 2558 // This is the inlined call site instanceof cache. The two occurences of the
2558 // hole value will be patched to the last map/result pair generated by the 2559 // hole value will be patched to the last map/result pair generated by the
2559 // instanceof stub. 2560 // instanceof stub.
2560 Label cache_miss; 2561 Label cache_miss;
2561 // Use a temp register to avoid memory operands with variable lengths. 2562 // Use a temp register to avoid memory operands with variable lengths.
2562 Register map = ToRegister(instr->temp()); 2563 Register map = ToRegister(instr->temp());
2563 __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); 2564 __ movp(map, FieldOperand(object, HeapObject::kMapOffset));
2564 __ bind(deferred->map_check()); // Label for calculating code patching. 2565 __ bind(deferred->map_check()); // Label for calculating code patching.
2565 Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value()); 2566 Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value());
2566 __ Move(kScratchRegister, cache_cell, RelocInfo::CELL); 2567 __ Move(kScratchRegister, cache_cell, RelocInfo::CELL);
2567 __ cmpq(map, Operand(kScratchRegister, 0)); 2568 __ cmpq(map, Operand(kScratchRegister, 0));
2568 __ j(not_equal, &cache_miss, Label::kNear); 2569 __ j(not_equal, &cache_miss, Label::kNear);
2569 // Patched to load either true or false. 2570 // Patched to load either true or false.
2570 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); 2571 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex);
2571 #ifdef DEBUG 2572 #ifdef DEBUG
2572 // Check that the code size between patch label and patch sites is invariant. 2573 // Check that the code size between patch label and patch sites is invariant.
2573 Label end_of_patched_code; 2574 Label end_of_patched_code;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2617 CallCodeGeneric(stub.GetCode(isolate()), 2618 CallCodeGeneric(stub.GetCode(isolate()),
2618 RelocInfo::CODE_TARGET, 2619 RelocInfo::CODE_TARGET,
2619 instr, 2620 instr,
2620 RECORD_SAFEPOINT_WITH_REGISTERS, 2621 RECORD_SAFEPOINT_WITH_REGISTERS,
2621 2); 2622 2);
2622 ASSERT(delta == masm_->SizeOfCodeGeneratedSince(map_check)); 2623 ASSERT(delta == masm_->SizeOfCodeGeneratedSince(map_check));
2623 LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment(); 2624 LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment();
2624 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); 2625 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
2625 // Move result to a register that survives the end of the 2626 // Move result to a register that survives the end of the
2626 // PushSafepointRegisterScope. 2627 // PushSafepointRegisterScope.
2627 __ movq(kScratchRegister, rax); 2628 __ movp(kScratchRegister, rax);
2628 } 2629 }
2629 __ testq(kScratchRegister, kScratchRegister); 2630 __ testq(kScratchRegister, kScratchRegister);
2630 Label load_false; 2631 Label load_false;
2631 Label done; 2632 Label done;
2632 __ j(not_zero, &load_false, Label::kNear); 2633 __ j(not_zero, &load_false, Label::kNear);
2633 __ LoadRoot(rax, Heap::kTrueValueRootIndex); 2634 __ LoadRoot(rax, Heap::kTrueValueRootIndex);
2634 __ jmp(&done, Label::kNear); 2635 __ jmp(&done, Label::kNear);
2635 __ bind(&load_false); 2636 __ bind(&load_false);
2636 __ LoadRoot(rax, Heap::kFalseValueRootIndex); 2637 __ LoadRoot(rax, Heap::kFalseValueRootIndex);
2637 __ bind(&done); 2638 __ bind(&done);
(...skipping 19 matching lines...) Expand all
2657 } 2658 }
2658 2659
2659 2660
2660 void LCodeGen::DoReturn(LReturn* instr) { 2661 void LCodeGen::DoReturn(LReturn* instr) {
2661 if (FLAG_trace && info()->IsOptimizing()) { 2662 if (FLAG_trace && info()->IsOptimizing()) {
2662 // Preserve the return value on the stack and rely on the runtime call 2663 // Preserve the return value on the stack and rely on the runtime call
2663 // to return the value in the same register. We're leaving the code 2664 // to return the value in the same register. We're leaving the code
2664 // managed by the register allocator and tearing down the frame, it's 2665 // managed by the register allocator and tearing down the frame, it's
2665 // safe to write to the context register. 2666 // safe to write to the context register.
2666 __ push(rax); 2667 __ push(rax);
2667 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2668 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2668 __ CallRuntime(Runtime::kTraceExit, 1); 2669 __ CallRuntime(Runtime::kTraceExit, 1);
2669 } 2670 }
2670 if (info()->saves_caller_doubles()) { 2671 if (info()->saves_caller_doubles()) {
2671 RestoreCallerDoubles(); 2672 RestoreCallerDoubles();
2672 } 2673 }
2673 int no_frame_start = -1; 2674 int no_frame_start = -1;
2674 if (NeedsEagerFrame()) { 2675 if (NeedsEagerFrame()) {
2675 __ movq(rsp, rbp); 2676 __ movp(rsp, rbp);
2676 __ pop(rbp); 2677 __ pop(rbp);
2677 no_frame_start = masm_->pc_offset(); 2678 no_frame_start = masm_->pc_offset();
2678 } 2679 }
2679 if (instr->has_constant_parameter_count()) { 2680 if (instr->has_constant_parameter_count()) {
2680 __ Ret((ToInteger32(instr->constant_parameter_count()) + 1) * kPointerSize, 2681 __ Ret((ToInteger32(instr->constant_parameter_count()) + 1) * kPointerSize,
2681 rcx); 2682 rcx);
2682 } else { 2683 } else {
2683 Register reg = ToRegister(instr->parameter_count()); 2684 Register reg = ToRegister(instr->parameter_count());
2684 // The argument count parameter is a smi 2685 // The argument count parameter is a smi
2685 __ SmiToInteger32(reg, reg); 2686 __ SmiToInteger32(reg, reg);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2726 // to update the property details in the property dictionary to mark 2727 // to update the property details in the property dictionary to mark
2727 // it as no longer deleted. We deoptimize in that case. 2728 // it as no longer deleted. We deoptimize in that case.
2728 if (instr->hydrogen()->RequiresHoleCheck()) { 2729 if (instr->hydrogen()->RequiresHoleCheck()) {
2729 // We have a temp because CompareRoot might clobber kScratchRegister. 2730 // We have a temp because CompareRoot might clobber kScratchRegister.
2730 Register cell = ToRegister(instr->temp()); 2731 Register cell = ToRegister(instr->temp());
2731 ASSERT(!value.is(cell)); 2732 ASSERT(!value.is(cell));
2732 __ Move(cell, cell_handle, RelocInfo::CELL); 2733 __ Move(cell, cell_handle, RelocInfo::CELL);
2733 __ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex); 2734 __ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex);
2734 DeoptimizeIf(equal, instr->environment()); 2735 DeoptimizeIf(equal, instr->environment());
2735 // Store the value. 2736 // Store the value.
2736 __ movq(Operand(cell, 0), value); 2737 __ movp(Operand(cell, 0), value);
2737 } else { 2738 } else {
2738 // Store the value. 2739 // Store the value.
2739 __ Move(kScratchRegister, cell_handle, RelocInfo::CELL); 2740 __ Move(kScratchRegister, cell_handle, RelocInfo::CELL);
2740 __ movq(Operand(kScratchRegister, 0), value); 2741 __ movp(Operand(kScratchRegister, 0), value);
2741 } 2742 }
2742 // Cells are always rescanned, so no write barrier here. 2743 // Cells are always rescanned, so no write barrier here.
2743 } 2744 }
2744 2745
2745 2746
2746 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
2747 ASSERT(ToRegister(instr->context()).is(rsi));
2748 ASSERT(ToRegister(instr->global_object()).is(rdx));
2749 ASSERT(ToRegister(instr->value()).is(rax));
2750
2751 __ Move(rcx, instr->name());
2752 Handle<Code> ic = StoreIC::initialize_stub(isolate(),
2753 instr->strict_mode_flag(),
2754 CONTEXTUAL);
2755 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2756 }
2757
2758
2759 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 2747 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
2760 Register context = ToRegister(instr->context()); 2748 Register context = ToRegister(instr->context());
2761 Register result = ToRegister(instr->result()); 2749 Register result = ToRegister(instr->result());
2762 __ movq(result, ContextOperand(context, instr->slot_index())); 2750 __ movp(result, ContextOperand(context, instr->slot_index()));
2763 if (instr->hydrogen()->RequiresHoleCheck()) { 2751 if (instr->hydrogen()->RequiresHoleCheck()) {
2764 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 2752 __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
2765 if (instr->hydrogen()->DeoptimizesOnHole()) { 2753 if (instr->hydrogen()->DeoptimizesOnHole()) {
2766 DeoptimizeIf(equal, instr->environment()); 2754 DeoptimizeIf(equal, instr->environment());
2767 } else { 2755 } else {
2768 Label is_not_hole; 2756 Label is_not_hole;
2769 __ j(not_equal, &is_not_hole, Label::kNear); 2757 __ j(not_equal, &is_not_hole, Label::kNear);
2770 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 2758 __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
2771 __ bind(&is_not_hole); 2759 __ bind(&is_not_hole);
2772 } 2760 }
2773 } 2761 }
2774 } 2762 }
2775 2763
2776 2764
2777 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { 2765 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
2778 Register context = ToRegister(instr->context()); 2766 Register context = ToRegister(instr->context());
2779 Register value = ToRegister(instr->value()); 2767 Register value = ToRegister(instr->value());
2780 2768
2781 Operand target = ContextOperand(context, instr->slot_index()); 2769 Operand target = ContextOperand(context, instr->slot_index());
2782 2770
2783 Label skip_assignment; 2771 Label skip_assignment;
2784 if (instr->hydrogen()->RequiresHoleCheck()) { 2772 if (instr->hydrogen()->RequiresHoleCheck()) {
2785 __ CompareRoot(target, Heap::kTheHoleValueRootIndex); 2773 __ CompareRoot(target, Heap::kTheHoleValueRootIndex);
2786 if (instr->hydrogen()->DeoptimizesOnHole()) { 2774 if (instr->hydrogen()->DeoptimizesOnHole()) {
2787 DeoptimizeIf(equal, instr->environment()); 2775 DeoptimizeIf(equal, instr->environment());
2788 } else { 2776 } else {
2789 __ j(not_equal, &skip_assignment); 2777 __ j(not_equal, &skip_assignment);
2790 } 2778 }
2791 } 2779 }
2792 __ movq(target, value); 2780 __ movp(target, value);
2793 2781
2794 if (instr->hydrogen()->NeedsWriteBarrier()) { 2782 if (instr->hydrogen()->NeedsWriteBarrier()) {
2795 SmiCheck check_needed = 2783 SmiCheck check_needed =
2796 instr->hydrogen()->value()->IsHeapObject() 2784 instr->hydrogen()->value()->IsHeapObject()
2797 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 2785 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
2798 int offset = Context::SlotOffset(instr->slot_index()); 2786 int offset = Context::SlotOffset(instr->slot_index());
2799 Register scratch = ToRegister(instr->temp()); 2787 Register scratch = ToRegister(instr->temp());
2800 __ RecordWriteContextSlot(context, 2788 __ RecordWriteContextSlot(context,
2801 offset, 2789 offset,
2802 value, 2790 value,
(...skipping 26 matching lines...) Expand all
2829 Register object = ToRegister(instr->object()); 2817 Register object = ToRegister(instr->object());
2830 if (FLAG_track_double_fields && 2818 if (FLAG_track_double_fields &&
2831 instr->hydrogen()->representation().IsDouble()) { 2819 instr->hydrogen()->representation().IsDouble()) {
2832 XMMRegister result = ToDoubleRegister(instr->result()); 2820 XMMRegister result = ToDoubleRegister(instr->result());
2833 __ movsd(result, FieldOperand(object, offset)); 2821 __ movsd(result, FieldOperand(object, offset));
2834 return; 2822 return;
2835 } 2823 }
2836 2824
2837 Register result = ToRegister(instr->result()); 2825 Register result = ToRegister(instr->result());
2838 if (!access.IsInobject()) { 2826 if (!access.IsInobject()) {
2839 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); 2827 __ movp(result, FieldOperand(object, JSObject::kPropertiesOffset));
2840 object = result; 2828 object = result;
2841 } 2829 }
2842 2830
2843 Representation representation = access.representation(); 2831 Representation representation = access.representation();
2844 if (representation.IsSmi() && 2832 if (representation.IsSmi() &&
2845 instr->hydrogen()->representation().IsInteger32()) { 2833 instr->hydrogen()->representation().IsInteger32()) {
2846 // Read int value directly from upper half of the smi. 2834 // Read int value directly from upper half of the smi.
2847 STATIC_ASSERT(kSmiTag == 0); 2835 STATIC_ASSERT(kSmiTag == 0);
2848 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); 2836 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32);
2849 offset += kPointerSize / 2; 2837 offset += kPointerSize / 2;
(...skipping 22 matching lines...) Expand all
2872 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); 2860 __ CmpObjectType(function, JS_FUNCTION_TYPE, result);
2873 DeoptimizeIf(not_equal, instr->environment()); 2861 DeoptimizeIf(not_equal, instr->environment());
2874 2862
2875 // Check whether the function has an instance prototype. 2863 // Check whether the function has an instance prototype.
2876 Label non_instance; 2864 Label non_instance;
2877 __ testb(FieldOperand(result, Map::kBitFieldOffset), 2865 __ testb(FieldOperand(result, Map::kBitFieldOffset),
2878 Immediate(1 << Map::kHasNonInstancePrototype)); 2866 Immediate(1 << Map::kHasNonInstancePrototype));
2879 __ j(not_zero, &non_instance, Label::kNear); 2867 __ j(not_zero, &non_instance, Label::kNear);
2880 2868
2881 // Get the prototype or initial map from the function. 2869 // Get the prototype or initial map from the function.
2882 __ movq(result, 2870 __ movp(result,
2883 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 2871 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
2884 2872
2885 // Check that the function has a prototype or an initial map. 2873 // Check that the function has a prototype or an initial map.
2886 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 2874 __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
2887 DeoptimizeIf(equal, instr->environment()); 2875 DeoptimizeIf(equal, instr->environment());
2888 2876
2889 // If the function does not have an initial map, we're done. 2877 // If the function does not have an initial map, we're done.
2890 Label done; 2878 Label done;
2891 __ CmpObjectType(result, MAP_TYPE, kScratchRegister); 2879 __ CmpObjectType(result, MAP_TYPE, kScratchRegister);
2892 __ j(not_equal, &done, Label::kNear); 2880 __ j(not_equal, &done, Label::kNear);
2893 2881
2894 // Get the prototype from the initial map. 2882 // Get the prototype from the initial map.
2895 __ movq(result, FieldOperand(result, Map::kPrototypeOffset)); 2883 __ movp(result, FieldOperand(result, Map::kPrototypeOffset));
2896 __ jmp(&done, Label::kNear); 2884 __ jmp(&done, Label::kNear);
2897 2885
2898 // Non-instance prototype: Fetch prototype from constructor field 2886 // Non-instance prototype: Fetch prototype from constructor field
2899 // in the function's map. 2887 // in the function's map.
2900 __ bind(&non_instance); 2888 __ bind(&non_instance);
2901 __ movq(result, FieldOperand(result, Map::kConstructorOffset)); 2889 __ movp(result, FieldOperand(result, Map::kConstructorOffset));
2902 2890
2903 // All done. 2891 // All done.
2904 __ bind(&done); 2892 __ bind(&done);
2905 } 2893 }
2906 2894
2907 2895
2908 void LCodeGen::DoLoadRoot(LLoadRoot* instr) { 2896 void LCodeGen::DoLoadRoot(LLoadRoot* instr) {
2909 Register result = ToRegister(instr->result()); 2897 Register result = ToRegister(instr->result());
2910 __ LoadRoot(result, instr->index()); 2898 __ LoadRoot(result, instr->index());
2911 } 2899 }
2912 2900
2913 2901
2914 void LCodeGen::DoLoadExternalArrayPointer( 2902 void LCodeGen::DoLoadExternalArrayPointer(
2915 LLoadExternalArrayPointer* instr) { 2903 LLoadExternalArrayPointer* instr) {
2916 Register result = ToRegister(instr->result()); 2904 Register result = ToRegister(instr->result());
2917 Register input = ToRegister(instr->object()); 2905 Register input = ToRegister(instr->object());
2918 __ movq(result, FieldOperand(input, 2906 __ movp(result, FieldOperand(input,
2919 ExternalPixelArray::kExternalPointerOffset)); 2907 ExternalPixelArray::kExternalPointerOffset));
2920 } 2908 }
2921 2909
2922 2910
2923 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { 2911 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
2924 Register arguments = ToRegister(instr->arguments()); 2912 Register arguments = ToRegister(instr->arguments());
2925 Register result = ToRegister(instr->result()); 2913 Register result = ToRegister(instr->result());
2926 2914
2927 if (instr->length()->IsConstantOperand() && 2915 if (instr->length()->IsConstantOperand() &&
2928 instr->index()->IsConstantOperand()) { 2916 instr->index()->IsConstantOperand()) {
2929 int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index())); 2917 int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index()));
2930 int32_t const_length = ToInteger32(LConstantOperand::cast(instr->length())); 2918 int32_t const_length = ToInteger32(LConstantOperand::cast(instr->length()));
2931 StackArgumentsAccessor args(arguments, const_length, 2919 StackArgumentsAccessor args(arguments, const_length,
2932 ARGUMENTS_DONT_CONTAIN_RECEIVER); 2920 ARGUMENTS_DONT_CONTAIN_RECEIVER);
2933 __ movq(result, args.GetArgumentOperand(const_index)); 2921 __ movp(result, args.GetArgumentOperand(const_index));
2934 } else { 2922 } else {
2935 Register length = ToRegister(instr->length()); 2923 Register length = ToRegister(instr->length());
2936 // There are two words between the frame pointer and the last argument. 2924 // There are two words between the frame pointer and the last argument.
2937 // Subtracting from length accounts for one of them add one more. 2925 // Subtracting from length accounts for one of them add one more.
2938 if (instr->index()->IsRegister()) { 2926 if (instr->index()->IsRegister()) {
2939 __ subl(length, ToRegister(instr->index())); 2927 __ subl(length, ToRegister(instr->index()));
2940 } else { 2928 } else {
2941 __ subl(length, ToOperand(instr->index())); 2929 __ subl(length, ToOperand(instr->index()));
2942 } 2930 }
2943 StackArgumentsAccessor args(arguments, length, 2931 StackArgumentsAccessor args(arguments, length,
2944 ARGUMENTS_DONT_CONTAIN_RECEIVER); 2932 ARGUMENTS_DONT_CONTAIN_RECEIVER);
2945 __ movq(result, args.GetArgumentOperand(0)); 2933 __ movp(result, args.GetArgumentOperand(0));
2946 } 2934 }
2947 } 2935 }
2948 2936
2949 2937
2950 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { 2938 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
2951 ElementsKind elements_kind = instr->elements_kind(); 2939 ElementsKind elements_kind = instr->elements_kind();
2952 LOperand* key = instr->key(); 2940 LOperand* key = instr->key();
2953 if (!key->IsConstantOperand()) { 2941 if (!key->IsConstantOperand()) {
2954 Register key_reg = ToRegister(key); 2942 Register key_reg = ToRegister(key);
2955 // Even though the HLoad/StoreKeyed (in this case) instructions force 2943 // Even though the HLoad/StoreKeyed (in this case) instructions force
2956 // the input representation for the key to be an integer, the input 2944 // the input representation for the key to be an integer, the input
2957 // gets replaced during bound check elimination with the index argument 2945 // gets replaced during bound check elimination with the index argument
2958 // to the bounds check, which can be tagged, so that case must be 2946 // to the bounds check, which can be tagged, so that case must be
2959 // handled here, too. 2947 // handled here, too.
2960 if (instr->hydrogen()->IsDehoisted()) { 2948 if (instr->hydrogen()->IsDehoisted()) {
2961 // Sign extend key because it could be a 32 bit negative value 2949 // Sign extend key because it could be a 32 bit negative value
2962 // and the dehoisted address computation happens in 64 bits 2950 // and the dehoisted address computation happens in 64 bits
2963 __ movsxlq(key_reg, key_reg); 2951 __ movsxlq(key_reg, key_reg);
2964 } 2952 }
2965 } 2953 }
2954 int base_offset = instr->is_fixed_typed_array()
2955 ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
2956 : 0;
2966 Operand operand(BuildFastArrayOperand( 2957 Operand operand(BuildFastArrayOperand(
2967 instr->elements(), 2958 instr->elements(),
2968 key, 2959 key,
2969 elements_kind, 2960 elements_kind,
2970 0, 2961 base_offset,
2971 instr->additional_index())); 2962 instr->additional_index()));
2972 2963
2973 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 2964 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
2965 elements_kind == FLOAT32_ELEMENTS) {
2974 XMMRegister result(ToDoubleRegister(instr->result())); 2966 XMMRegister result(ToDoubleRegister(instr->result()));
2975 __ movss(result, operand); 2967 __ movss(result, operand);
2976 __ cvtss2sd(result, result); 2968 __ cvtss2sd(result, result);
2977 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 2969 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS ||
2970 elements_kind == FLOAT64_ELEMENTS) {
2978 __ movsd(ToDoubleRegister(instr->result()), operand); 2971 __ movsd(ToDoubleRegister(instr->result()), operand);
2979 } else { 2972 } else {
2980 Register result(ToRegister(instr->result())); 2973 Register result(ToRegister(instr->result()));
2981 switch (elements_kind) { 2974 switch (elements_kind) {
2982 case EXTERNAL_BYTE_ELEMENTS: 2975 case EXTERNAL_BYTE_ELEMENTS:
2976 case INT8_ELEMENTS:
2983 __ movsxbq(result, operand); 2977 __ movsxbq(result, operand);
2984 break; 2978 break;
2985 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 2979 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
2986 case EXTERNAL_PIXEL_ELEMENTS: 2980 case EXTERNAL_PIXEL_ELEMENTS:
2981 case UINT8_ELEMENTS:
2982 case UINT8_CLAMPED_ELEMENTS:
2987 __ movzxbq(result, operand); 2983 __ movzxbq(result, operand);
2988 break; 2984 break;
2989 case EXTERNAL_SHORT_ELEMENTS: 2985 case EXTERNAL_SHORT_ELEMENTS:
2986 case INT16_ELEMENTS:
2990 __ movsxwq(result, operand); 2987 __ movsxwq(result, operand);
2991 break; 2988 break;
2992 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 2989 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
2990 case UINT16_ELEMENTS:
2993 __ movzxwq(result, operand); 2991 __ movzxwq(result, operand);
2994 break; 2992 break;
2995 case EXTERNAL_INT_ELEMENTS: 2993 case EXTERNAL_INT_ELEMENTS:
2994 case INT32_ELEMENTS:
2996 __ movsxlq(result, operand); 2995 __ movsxlq(result, operand);
2997 break; 2996 break;
2998 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 2997 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
2998 case UINT32_ELEMENTS:
2999 __ movl(result, operand); 2999 __ movl(result, operand);
3000 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { 3000 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
3001 __ testl(result, result); 3001 __ testl(result, result);
3002 DeoptimizeIf(negative, instr->environment()); 3002 DeoptimizeIf(negative, instr->environment());
3003 } 3003 }
3004 break; 3004 break;
3005 case EXTERNAL_FLOAT_ELEMENTS: 3005 case EXTERNAL_FLOAT_ELEMENTS:
3006 case EXTERNAL_DOUBLE_ELEMENTS: 3006 case EXTERNAL_DOUBLE_ELEMENTS:
3007 case FLOAT32_ELEMENTS:
3008 case FLOAT64_ELEMENTS:
3007 case FAST_ELEMENTS: 3009 case FAST_ELEMENTS:
3008 case FAST_SMI_ELEMENTS: 3010 case FAST_SMI_ELEMENTS:
3009 case FAST_DOUBLE_ELEMENTS: 3011 case FAST_DOUBLE_ELEMENTS:
3010 case FAST_HOLEY_ELEMENTS: 3012 case FAST_HOLEY_ELEMENTS:
3011 case FAST_HOLEY_SMI_ELEMENTS: 3013 case FAST_HOLEY_SMI_ELEMENTS:
3012 case FAST_HOLEY_DOUBLE_ELEMENTS: 3014 case FAST_HOLEY_DOUBLE_ELEMENTS:
3013 case DICTIONARY_ELEMENTS: 3015 case DICTIONARY_ELEMENTS:
3014 case NON_STRICT_ARGUMENTS_ELEMENTS: 3016 case NON_STRICT_ARGUMENTS_ELEMENTS:
3015 UNREACHABLE(); 3017 UNREACHABLE();
3016 break; 3018 break;
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
3104 DeoptimizeIf(NegateCondition(smi), instr->environment()); 3106 DeoptimizeIf(NegateCondition(smi), instr->environment());
3105 } else { 3107 } else {
3106 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 3108 __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
3107 DeoptimizeIf(equal, instr->environment()); 3109 DeoptimizeIf(equal, instr->environment());
3108 } 3110 }
3109 } 3111 }
3110 } 3112 }
3111 3113
3112 3114
3113 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { 3115 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
3114 if (instr->is_external()) { 3116 if (instr->is_typed_elements()) {
3115 DoLoadKeyedExternalArray(instr); 3117 DoLoadKeyedExternalArray(instr);
3116 } else if (instr->hydrogen()->representation().IsDouble()) { 3118 } else if (instr->hydrogen()->representation().IsDouble()) {
3117 DoLoadKeyedFixedDoubleArray(instr); 3119 DoLoadKeyedFixedDoubleArray(instr);
3118 } else { 3120 } else {
3119 DoLoadKeyedFixedArray(instr); 3121 DoLoadKeyedFixedArray(instr);
3120 } 3122 }
3121 } 3123 }
3122 3124
3123 3125
3124 Operand LCodeGen::BuildFastArrayOperand( 3126 Operand LCodeGen::BuildFastArrayOperand(
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3158 3160
3159 3161
3160 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { 3162 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
3161 Register result = ToRegister(instr->result()); 3163 Register result = ToRegister(instr->result());
3162 3164
3163 if (instr->hydrogen()->from_inlined()) { 3165 if (instr->hydrogen()->from_inlined()) {
3164 __ lea(result, Operand(rsp, -kFPOnStackSize + -kPCOnStackSize)); 3166 __ lea(result, Operand(rsp, -kFPOnStackSize + -kPCOnStackSize));
3165 } else { 3167 } else {
3166 // Check for arguments adapter frame. 3168 // Check for arguments adapter frame.
3167 Label done, adapted; 3169 Label done, adapted;
3168 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 3170 __ movp(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
3169 __ Cmp(Operand(result, StandardFrameConstants::kContextOffset), 3171 __ Cmp(Operand(result, StandardFrameConstants::kContextOffset),
3170 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 3172 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
3171 __ j(equal, &adapted, Label::kNear); 3173 __ j(equal, &adapted, Label::kNear);
3172 3174
3173 // No arguments adaptor frame. 3175 // No arguments adaptor frame.
3174 __ movq(result, rbp); 3176 __ movp(result, rbp);
3175 __ jmp(&done, Label::kNear); 3177 __ jmp(&done, Label::kNear);
3176 3178
3177 // Arguments adaptor frame present. 3179 // Arguments adaptor frame present.
3178 __ bind(&adapted); 3180 __ bind(&adapted);
3179 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 3181 __ movp(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
3180 3182
3181 // Result is the frame pointer for the frame if not adapted and for the real 3183 // Result is the frame pointer for the frame if not adapted and for the real
3182 // frame below the adaptor frame if adapted. 3184 // frame below the adaptor frame if adapted.
3183 __ bind(&done); 3185 __ bind(&done);
3184 } 3186 }
3185 } 3187 }
3186 3188
3187 3189
3188 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { 3190 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
3189 Register result = ToRegister(instr->result()); 3191 Register result = ToRegister(instr->result());
3190 3192
3191 Label done; 3193 Label done;
3192 3194
3193 // If no arguments adaptor frame the number of arguments is fixed. 3195 // If no arguments adaptor frame the number of arguments is fixed.
3194 if (instr->elements()->IsRegister()) { 3196 if (instr->elements()->IsRegister()) {
3195 __ cmpq(rbp, ToRegister(instr->elements())); 3197 __ cmpq(rbp, ToRegister(instr->elements()));
3196 } else { 3198 } else {
3197 __ cmpq(rbp, ToOperand(instr->elements())); 3199 __ cmpq(rbp, ToOperand(instr->elements()));
3198 } 3200 }
3199 __ movl(result, Immediate(scope()->num_parameters())); 3201 __ movl(result, Immediate(scope()->num_parameters()));
3200 __ j(equal, &done, Label::kNear); 3202 __ j(equal, &done, Label::kNear);
3201 3203
3202 // Arguments adaptor frame present. Get argument length from there. 3204 // Arguments adaptor frame present. Get argument length from there.
3203 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 3205 __ movp(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
3204 __ SmiToInteger32(result, 3206 __ SmiToInteger32(result,
3205 Operand(result, 3207 Operand(result,
3206 ArgumentsAdaptorFrameConstants::kLengthOffset)); 3208 ArgumentsAdaptorFrameConstants::kLengthOffset));
3207 3209
3208 // Argument length is in result register. 3210 // Argument length is in result register.
3209 __ bind(&done); 3211 __ bind(&done);
3210 } 3212 }
3211 3213
3212 3214
3213 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { 3215 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
3214 Register receiver = ToRegister(instr->receiver()); 3216 Register receiver = ToRegister(instr->receiver());
3215 Register function = ToRegister(instr->function()); 3217 Register function = ToRegister(instr->function());
3216 3218
3217 // If the receiver is null or undefined, we have to pass the global 3219 // If the receiver is null or undefined, we have to pass the global
3218 // object as a receiver to normal functions. Values have to be 3220 // object as a receiver to normal functions. Values have to be
3219 // passed unchanged to builtins and strict-mode functions. 3221 // passed unchanged to builtins and strict-mode functions.
3220 Label global_object, receiver_ok; 3222 Label global_object, receiver_ok;
3221 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; 3223 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
3222 3224
3223 // Do not transform the receiver to object for strict mode 3225 // Do not transform the receiver to object for strict mode
3224 // functions. 3226 // functions.
3225 __ movq(kScratchRegister, 3227 __ movp(kScratchRegister,
3226 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); 3228 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
3227 __ testb(FieldOperand(kScratchRegister, 3229 __ testb(FieldOperand(kScratchRegister,
3228 SharedFunctionInfo::kStrictModeByteOffset), 3230 SharedFunctionInfo::kStrictModeByteOffset),
3229 Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte)); 3231 Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
3230 __ j(not_equal, &receiver_ok, dist); 3232 __ j(not_equal, &receiver_ok, dist);
3231 3233
3232 // Do not transform the receiver to object for builtins. 3234 // Do not transform the receiver to object for builtins.
3233 __ testb(FieldOperand(kScratchRegister, 3235 __ testb(FieldOperand(kScratchRegister,
3234 SharedFunctionInfo::kNativeByteOffset), 3236 SharedFunctionInfo::kNativeByteOffset),
3235 Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte)); 3237 Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
3236 __ j(not_equal, &receiver_ok, dist); 3238 __ j(not_equal, &receiver_ok, dist);
3237 3239
3238 // Normal function. Replace undefined or null with global receiver. 3240 // Normal function. Replace undefined or null with global receiver.
3239 __ CompareRoot(receiver, Heap::kNullValueRootIndex); 3241 __ CompareRoot(receiver, Heap::kNullValueRootIndex);
3240 __ j(equal, &global_object, Label::kNear); 3242 __ j(equal, &global_object, Label::kNear);
3241 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); 3243 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex);
3242 __ j(equal, &global_object, Label::kNear); 3244 __ j(equal, &global_object, Label::kNear);
3243 3245
3244 // The receiver should be a JS object. 3246 // The receiver should be a JS object.
3245 Condition is_smi = __ CheckSmi(receiver); 3247 Condition is_smi = __ CheckSmi(receiver);
3246 DeoptimizeIf(is_smi, instr->environment()); 3248 DeoptimizeIf(is_smi, instr->environment());
3247 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); 3249 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister);
3248 DeoptimizeIf(below, instr->environment()); 3250 DeoptimizeIf(below, instr->environment());
3249 __ jmp(&receiver_ok, Label::kNear); 3251 __ jmp(&receiver_ok, Label::kNear);
3250 3252
3251 __ bind(&global_object); 3253 __ bind(&global_object);
3252 __ movq(receiver, FieldOperand(function, JSFunction::kContextOffset)); 3254 __ movp(receiver, FieldOperand(function, JSFunction::kContextOffset));
3253 __ movq(receiver, 3255 __ movp(receiver,
3254 Operand(receiver, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 3256 Operand(receiver, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
3255 __ movq(receiver, 3257 __ movp(receiver,
3256 FieldOperand(receiver, GlobalObject::kGlobalReceiverOffset)); 3258 FieldOperand(receiver, GlobalObject::kGlobalReceiverOffset));
3257 __ bind(&receiver_ok); 3259 __ bind(&receiver_ok);
3258 } 3260 }
3259 3261
3260 3262
3261 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { 3263 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
3262 Register receiver = ToRegister(instr->receiver()); 3264 Register receiver = ToRegister(instr->receiver());
3263 Register function = ToRegister(instr->function()); 3265 Register function = ToRegister(instr->function());
3264 Register length = ToRegister(instr->length()); 3266 Register length = ToRegister(instr->length());
3265 Register elements = ToRegister(instr->elements()); 3267 Register elements = ToRegister(instr->elements());
3266 ASSERT(receiver.is(rax)); // Used for parameter count. 3268 ASSERT(receiver.is(rax)); // Used for parameter count.
3267 ASSERT(function.is(rdi)); // Required by InvokeFunction. 3269 ASSERT(function.is(rdi)); // Required by InvokeFunction.
3268 ASSERT(ToRegister(instr->result()).is(rax)); 3270 ASSERT(ToRegister(instr->result()).is(rax));
3269 3271
3270 // Copy the arguments to this function possibly from the 3272 // Copy the arguments to this function possibly from the
3271 // adaptor frame below it. 3273 // adaptor frame below it.
3272 const uint32_t kArgumentsLimit = 1 * KB; 3274 const uint32_t kArgumentsLimit = 1 * KB;
3273 __ cmpq(length, Immediate(kArgumentsLimit)); 3275 __ cmpq(length, Immediate(kArgumentsLimit));
3274 DeoptimizeIf(above, instr->environment()); 3276 DeoptimizeIf(above, instr->environment());
3275 3277
3276 __ push(receiver); 3278 __ push(receiver);
3277 __ movq(receiver, length); 3279 __ movp(receiver, length);
3278 3280
3279 // Loop through the arguments pushing them onto the execution 3281 // Loop through the arguments pushing them onto the execution
3280 // stack. 3282 // stack.
3281 Label invoke, loop; 3283 Label invoke, loop;
3282 // length is a small non-negative integer, due to the test above. 3284 // length is a small non-negative integer, due to the test above.
3283 __ testl(length, length); 3285 __ testl(length, length);
3284 __ j(zero, &invoke, Label::kNear); 3286 __ j(zero, &invoke, Label::kNear);
3285 __ bind(&loop); 3287 __ bind(&loop);
3286 StackArgumentsAccessor args(elements, length, 3288 StackArgumentsAccessor args(elements, length,
3287 ARGUMENTS_DONT_CONTAIN_RECEIVER); 3289 ARGUMENTS_DONT_CONTAIN_RECEIVER);
(...skipping 18 matching lines...) Expand all
3306 } 3308 }
3307 3309
3308 3310
3309 void LCodeGen::DoDrop(LDrop* instr) { 3311 void LCodeGen::DoDrop(LDrop* instr) {
3310 __ Drop(instr->count()); 3312 __ Drop(instr->count());
3311 } 3313 }
3312 3314
3313 3315
3314 void LCodeGen::DoThisFunction(LThisFunction* instr) { 3316 void LCodeGen::DoThisFunction(LThisFunction* instr) {
3315 Register result = ToRegister(instr->result()); 3317 Register result = ToRegister(instr->result());
3316 __ movq(result, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 3318 __ movp(result, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
3317 } 3319 }
3318 3320
3319 3321
3320 void LCodeGen::DoContext(LContext* instr) { 3322 void LCodeGen::DoContext(LContext* instr) {
3321 Register result = ToRegister(instr->result()); 3323 Register result = ToRegister(instr->result());
3322 if (info()->IsOptimizing()) { 3324 if (info()->IsOptimizing()) {
3323 __ movq(result, Operand(rbp, StandardFrameConstants::kContextOffset)); 3325 __ movp(result, Operand(rbp, StandardFrameConstants::kContextOffset));
3324 } else { 3326 } else {
3325 // If there is no frame, the context must be in rsi. 3327 // If there is no frame, the context must be in rsi.
3326 ASSERT(result.is(rsi)); 3328 ASSERT(result.is(rsi));
3327 } 3329 }
3328 } 3330 }
3329 3331
3330 3332
3331 void LCodeGen::DoOuterContext(LOuterContext* instr) { 3333 void LCodeGen::DoOuterContext(LOuterContext* instr) {
3332 Register context = ToRegister(instr->context()); 3334 Register context = ToRegister(instr->context());
3333 Register result = ToRegister(instr->result()); 3335 Register result = ToRegister(instr->result());
3334 __ movq(result, 3336 __ movp(result,
3335 Operand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); 3337 Operand(context, Context::SlotOffset(Context::PREVIOUS_INDEX)));
3336 } 3338 }
3337 3339
3338 3340
3339 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { 3341 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
3340 ASSERT(ToRegister(instr->context()).is(rsi)); 3342 ASSERT(ToRegister(instr->context()).is(rsi));
3341 __ push(rsi); // The context is the first argument. 3343 __ push(rsi); // The context is the first argument.
3342 __ Push(instr->hydrogen()->pairs()); 3344 __ Push(instr->hydrogen()->pairs());
3343 __ Push(Smi::FromInt(instr->hydrogen()->flags())); 3345 __ Push(Smi::FromInt(instr->hydrogen()->flags()));
3344 CallRuntime(Runtime::kDeclareGlobals, 3, instr); 3346 CallRuntime(Runtime::kDeclareGlobals, 3, instr);
3345 } 3347 }
3346 3348
3347 3349
3348 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { 3350 void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
3349 Register context = ToRegister(instr->context()); 3351 Register context = ToRegister(instr->context());
3350 Register result = ToRegister(instr->result()); 3352 Register result = ToRegister(instr->result());
3351 __ movq(result, 3353 __ movp(result,
3352 Operand(context, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 3354 Operand(context, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
3353 } 3355 }
3354 3356
3355 3357
3356 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { 3358 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) {
3357 Register global = ToRegister(instr->global()); 3359 Register global = ToRegister(instr->global());
3358 Register result = ToRegister(instr->result()); 3360 Register result = ToRegister(instr->result());
3359 __ movq(result, FieldOperand(global, GlobalObject::kGlobalReceiverOffset)); 3361 __ movp(result, FieldOperand(global, GlobalObject::kGlobalReceiverOffset));
3360 } 3362 }
3361 3363
3362 3364
3363 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, 3365 void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
3364 int formal_parameter_count, 3366 int formal_parameter_count,
3365 int arity, 3367 int arity,
3366 LInstruction* instr, 3368 LInstruction* instr,
3367 RDIState rdi_state) { 3369 RDIState rdi_state) {
3368 bool dont_adapt_arguments = 3370 bool dont_adapt_arguments =
3369 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; 3371 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3370 bool can_invoke_directly = 3372 bool can_invoke_directly =
3371 dont_adapt_arguments || formal_parameter_count == arity; 3373 dont_adapt_arguments || formal_parameter_count == arity;
3372 3374
3373 LPointerMap* pointers = instr->pointer_map(); 3375 LPointerMap* pointers = instr->pointer_map();
3374 3376
3375 if (can_invoke_directly) { 3377 if (can_invoke_directly) {
3376 if (rdi_state == RDI_UNINITIALIZED) { 3378 if (rdi_state == RDI_UNINITIALIZED) {
3377 __ Move(rdi, function); 3379 __ Move(rdi, function);
3378 } 3380 }
3379 3381
3380 // Change context. 3382 // Change context.
3381 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 3383 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
3382 3384
3383 // Set rax to arguments count if adaption is not needed. Assumes that rax 3385 // Set rax to arguments count if adaption is not needed. Assumes that rax
3384 // is available to write to at this point. 3386 // is available to write to at this point.
3385 if (dont_adapt_arguments) { 3387 if (dont_adapt_arguments) {
3386 __ Set(rax, arity); 3388 __ Set(rax, arity);
3387 } 3389 }
3388 3390
3389 // Invoke function. 3391 // Invoke function.
3390 if (function.is_identical_to(info()->closure())) { 3392 if (function.is_identical_to(info()->closure())) {
3391 __ CallSelf(); 3393 __ CallSelf();
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
3430 3432
3431 void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) { 3433 void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) {
3432 ASSERT(ToRegister(instr->function()).is(rdi)); 3434 ASSERT(ToRegister(instr->function()).is(rdi));
3433 ASSERT(ToRegister(instr->result()).is(rax)); 3435 ASSERT(ToRegister(instr->result()).is(rax));
3434 3436
3435 if (instr->hydrogen()->pass_argument_count()) { 3437 if (instr->hydrogen()->pass_argument_count()) {
3436 __ Set(rax, instr->arity()); 3438 __ Set(rax, instr->arity());
3437 } 3439 }
3438 3440
3439 // Change context. 3441 // Change context.
3440 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 3442 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
3441 3443
3442 LPointerMap* pointers = instr->pointer_map(); 3444 LPointerMap* pointers = instr->pointer_map();
3443 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); 3445 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
3444 3446
3445 bool is_self_call = false; 3447 bool is_self_call = false;
3446 if (instr->hydrogen()->function()->IsConstant()) { 3448 if (instr->hydrogen()->function()->IsConstant()) {
3447 Handle<JSFunction> jsfun = Handle<JSFunction>::null(); 3449 Handle<JSFunction> jsfun = Handle<JSFunction>::null();
3448 HConstant* fun_const = HConstant::cast(instr->hydrogen()->function()); 3450 HConstant* fun_const = HConstant::cast(instr->hydrogen()->function());
3449 jsfun = Handle<JSFunction>::cast(fun_const->handle(isolate())); 3451 jsfun = Handle<JSFunction>::cast(fun_const->handle(isolate()));
3450 is_self_call = jsfun.is_identical_to(info()->closure()); 3452 is_self_call = jsfun.is_identical_to(info()->closure());
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3483 __ j(zero, &done); 3485 __ j(zero, &done);
3484 3486
3485 __ AllocateHeapNumber(tmp, tmp2, &slow); 3487 __ AllocateHeapNumber(tmp, tmp2, &slow);
3486 __ jmp(&allocated, Label::kNear); 3488 __ jmp(&allocated, Label::kNear);
3487 3489
3488 // Slow case: Call the runtime system to do the number allocation. 3490 // Slow case: Call the runtime system to do the number allocation.
3489 __ bind(&slow); 3491 __ bind(&slow);
3490 CallRuntimeFromDeferred( 3492 CallRuntimeFromDeferred(
3491 Runtime::kAllocateHeapNumber, 0, instr, instr->context()); 3493 Runtime::kAllocateHeapNumber, 0, instr, instr->context());
3492 // Set the pointer to the new heap number in tmp. 3494 // Set the pointer to the new heap number in tmp.
3493 if (!tmp.is(rax)) __ movq(tmp, rax); 3495 if (!tmp.is(rax)) __ movp(tmp, rax);
3494 // Restore input_reg after call to runtime. 3496 // Restore input_reg after call to runtime.
3495 __ LoadFromSafepointRegisterSlot(input_reg, input_reg); 3497 __ LoadFromSafepointRegisterSlot(input_reg, input_reg);
3496 3498
3497 __ bind(&allocated); 3499 __ bind(&allocated);
3498 __ MoveDouble(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset)); 3500 __ MoveDouble(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset));
3499 __ shl(tmp2, Immediate(1)); 3501 __ shl(tmp2, Immediate(1));
3500 __ shr(tmp2, Immediate(1)); 3502 __ shr(tmp2, Immediate(1));
3501 __ MoveDouble(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); 3503 __ MoveDouble(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2);
3502 __ StoreToSafepointRegisterSlot(input_reg, tmp); 3504 __ StoreToSafepointRegisterSlot(input_reg, tmp);
3503 3505
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
3855 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 3857 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
3856 } 3858 }
3857 3859
3858 3860
3859 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { 3861 void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
3860 ASSERT(ToRegister(instr->context()).is(rsi)); 3862 ASSERT(ToRegister(instr->context()).is(rsi));
3861 ASSERT(ToRegister(instr->constructor()).is(rdi)); 3863 ASSERT(ToRegister(instr->constructor()).is(rdi));
3862 ASSERT(ToRegister(instr->result()).is(rax)); 3864 ASSERT(ToRegister(instr->result()).is(rax));
3863 3865
3864 __ Set(rax, instr->arity()); 3866 __ Set(rax, instr->arity());
3865 __ Move(rbx, instr->hydrogen()->property_cell()); 3867 __ Move(rbx, factory()->undefined_value());
3866 ElementsKind kind = instr->hydrogen()->elements_kind(); 3868 ElementsKind kind = instr->hydrogen()->elements_kind();
3867 AllocationSiteOverrideMode override_mode = 3869 AllocationSiteOverrideMode override_mode =
3868 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) 3870 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE)
3869 ? DISABLE_ALLOCATION_SITES 3871 ? DISABLE_ALLOCATION_SITES
3870 : DONT_OVERRIDE; 3872 : DONT_OVERRIDE;
3871 3873
3872 if (instr->arity() == 0) { 3874 if (instr->arity() == 0) {
3873 ArrayNoArgumentConstructorStub stub(kind, override_mode); 3875 ArrayNoArgumentConstructorStub stub(kind, override_mode);
3874 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 3876 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
3875 } else if (instr->arity() == 1) { 3877 } else if (instr->arity() == 1) {
3876 Label done; 3878 Label done;
3877 if (IsFastPackedElementsKind(kind)) { 3879 if (IsFastPackedElementsKind(kind)) {
3878 Label packed_case; 3880 Label packed_case;
3879 // We might need a change here 3881 // We might need a change here
3880 // look at the first argument 3882 // look at the first argument
3881 __ movq(rcx, Operand(rsp, 0)); 3883 __ movp(rcx, Operand(rsp, 0));
3882 __ testq(rcx, rcx); 3884 __ testq(rcx, rcx);
3883 __ j(zero, &packed_case, Label::kNear); 3885 __ j(zero, &packed_case, Label::kNear);
3884 3886
3885 ElementsKind holey_kind = GetHoleyElementsKind(kind); 3887 ElementsKind holey_kind = GetHoleyElementsKind(kind);
3886 ArraySingleArgumentConstructorStub stub(holey_kind, override_mode); 3888 ArraySingleArgumentConstructorStub stub(holey_kind, override_mode);
3887 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 3889 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
3888 __ jmp(&done, Label::kNear); 3890 __ jmp(&done, Label::kNear);
3889 __ bind(&packed_case); 3891 __ bind(&packed_case);
3890 } 3892 }
3891 3893
(...skipping 10 matching lines...) Expand all
3902 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { 3904 void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
3903 ASSERT(ToRegister(instr->context()).is(rsi)); 3905 ASSERT(ToRegister(instr->context()).is(rsi));
3904 CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles()); 3906 CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles());
3905 } 3907 }
3906 3908
3907 3909
3908 void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) { 3910 void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) {
3909 Register function = ToRegister(instr->function()); 3911 Register function = ToRegister(instr->function());
3910 Register code_object = ToRegister(instr->code_object()); 3912 Register code_object = ToRegister(instr->code_object());
3911 __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize)); 3913 __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize));
3912 __ movq(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object); 3914 __ movp(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object);
3913 } 3915 }
3914 3916
3915 3917
3916 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { 3918 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
3917 Register result = ToRegister(instr->result()); 3919 Register result = ToRegister(instr->result());
3918 Register base = ToRegister(instr->base_object()); 3920 Register base = ToRegister(instr->base_object());
3919 if (instr->offset()->IsConstantOperand()) { 3921 if (instr->offset()->IsConstantOperand()) {
3920 LConstantOperand* offset = LConstantOperand::cast(instr->offset()); 3922 LConstantOperand* offset = LConstantOperand::cast(instr->offset());
3921 __ lea(result, Operand(base, ToInteger32(offset))); 3923 __ lea(result, Operand(base, ToInteger32(offset)));
3922 } else { 3924 } else {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
3980 __ movsd(FieldOperand(object, offset), value); 3982 __ movsd(FieldOperand(object, offset), value);
3981 return; 3983 return;
3982 } 3984 }
3983 3985
3984 if (!transition.is_null()) { 3986 if (!transition.is_null()) {
3985 if (!hinstr->NeedsWriteBarrierForMap()) { 3987 if (!hinstr->NeedsWriteBarrierForMap()) {
3986 __ Move(FieldOperand(object, HeapObject::kMapOffset), transition); 3988 __ Move(FieldOperand(object, HeapObject::kMapOffset), transition);
3987 } else { 3989 } else {
3988 Register temp = ToRegister(instr->temp()); 3990 Register temp = ToRegister(instr->temp());
3989 __ Move(kScratchRegister, transition); 3991 __ Move(kScratchRegister, transition);
3990 __ movq(FieldOperand(object, HeapObject::kMapOffset), kScratchRegister); 3992 __ movp(FieldOperand(object, HeapObject::kMapOffset), kScratchRegister);
3991 // Update the write barrier for the map field. 3993 // Update the write barrier for the map field.
3992 __ RecordWriteField(object, 3994 __ RecordWriteField(object,
3993 HeapObject::kMapOffset, 3995 HeapObject::kMapOffset,
3994 kScratchRegister, 3996 kScratchRegister,
3995 temp, 3997 temp,
3996 kSaveFPRegs, 3998 kSaveFPRegs,
3997 OMIT_REMEMBERED_SET, 3999 OMIT_REMEMBERED_SET,
3998 OMIT_SMI_CHECK); 4000 OMIT_SMI_CHECK);
3999 } 4001 }
4000 } 4002 }
4001 4003
4002 // Do the store. 4004 // Do the store.
4003 SmiCheck check_needed = hinstr->value()->IsHeapObject() 4005 SmiCheck check_needed = hinstr->value()->IsHeapObject()
4004 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 4006 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
4005 4007
4006 Register write_register = object; 4008 Register write_register = object;
4007 if (!access.IsInobject()) { 4009 if (!access.IsInobject()) {
4008 write_register = ToRegister(instr->temp()); 4010 write_register = ToRegister(instr->temp());
4009 __ movq(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); 4011 __ movp(write_register, FieldOperand(object, JSObject::kPropertiesOffset));
4010 } 4012 }
4011 4013
4012 if (representation.IsSmi() && 4014 if (representation.IsSmi() &&
4013 hinstr->value()->representation().IsInteger32()) { 4015 hinstr->value()->representation().IsInteger32()) {
4014 ASSERT(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY); 4016 ASSERT(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY);
4015 // Store int value directly to upper half of the smi. 4017 // Store int value directly to upper half of the smi.
4016 STATIC_ASSERT(kSmiTag == 0); 4018 STATIC_ASSERT(kSmiTag == 0);
4017 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); 4019 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32);
4018 offset += kPointerSize / 2; 4020 offset += kPointerSize / 2;
4019 representation = Representation::Integer32(); 4021 representation = Representation::Integer32();
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
4058 } 4060 }
4059 4061
4060 4062
4061 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { 4063 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
4062 ASSERT(ToRegister(instr->context()).is(rsi)); 4064 ASSERT(ToRegister(instr->context()).is(rsi));
4063 ASSERT(ToRegister(instr->object()).is(rdx)); 4065 ASSERT(ToRegister(instr->object()).is(rdx));
4064 ASSERT(ToRegister(instr->value()).is(rax)); 4066 ASSERT(ToRegister(instr->value()).is(rax));
4065 4067
4066 __ Move(rcx, instr->hydrogen()->name()); 4068 __ Move(rcx, instr->hydrogen()->name());
4067 Handle<Code> ic = StoreIC::initialize_stub(isolate(), 4069 Handle<Code> ic = StoreIC::initialize_stub(isolate(),
4068 instr->strict_mode_flag(), 4070 instr->strict_mode_flag());
4069 NOT_CONTEXTUAL);
4070 CallCode(ic, RelocInfo::CODE_TARGET, instr); 4071 CallCode(ic, RelocInfo::CODE_TARGET, instr);
4071 } 4072 }
4072 4073
4073 4074
4074 void LCodeGen::ApplyCheckIf(Condition cc, LBoundsCheck* check) { 4075 void LCodeGen::ApplyCheckIf(Condition cc, LBoundsCheck* check) {
4075 if (FLAG_debug_code && check->hydrogen()->skip_check()) { 4076 if (FLAG_debug_code && check->hydrogen()->skip_check()) {
4076 Label done; 4077 Label done;
4077 __ j(NegateCondition(cc), &done, Label::kNear); 4078 __ j(NegateCondition(cc), &done, Label::kNear);
4078 __ int3(); 4079 __ int3();
4079 __ bind(&done); 4080 __ bind(&done);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
4135 // the input representation for the key to be an integer, the input 4136 // the input representation for the key to be an integer, the input
4136 // gets replaced during bound check elimination with the index 4137 // gets replaced during bound check elimination with the index
4137 // argument to the bounds check, which can be tagged, so that case 4138 // argument to the bounds check, which can be tagged, so that case
4138 // must be handled here, too. 4139 // must be handled here, too.
4139 if (instr->hydrogen()->IsDehoisted()) { 4140 if (instr->hydrogen()->IsDehoisted()) {
4140 // Sign extend key because it could be a 32 bit negative value 4141 // Sign extend key because it could be a 32 bit negative value
4141 // and the dehoisted address computation happens in 64 bits 4142 // and the dehoisted address computation happens in 64 bits
4142 __ movsxlq(key_reg, key_reg); 4143 __ movsxlq(key_reg, key_reg);
4143 } 4144 }
4144 } 4145 }
4146 int base_offset = instr->is_fixed_typed_array()
4147 ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
4148 : 0;
4145 Operand operand(BuildFastArrayOperand( 4149 Operand operand(BuildFastArrayOperand(
4146 instr->elements(), 4150 instr->elements(),
4147 key, 4151 key,
4148 elements_kind, 4152 elements_kind,
4149 0, 4153 base_offset,
4150 instr->additional_index())); 4154 instr->additional_index()));
4151 4155
4152 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 4156 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
4157 elements_kind == FLOAT32_ELEMENTS) {
4153 XMMRegister value(ToDoubleRegister(instr->value())); 4158 XMMRegister value(ToDoubleRegister(instr->value()));
4154 __ cvtsd2ss(value, value); 4159 __ cvtsd2ss(value, value);
4155 __ movss(operand, value); 4160 __ movss(operand, value);
4156 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 4161 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS ||
4162 elements_kind == FLOAT64_ELEMENTS) {
4157 __ movsd(operand, ToDoubleRegister(instr->value())); 4163 __ movsd(operand, ToDoubleRegister(instr->value()));
4158 } else { 4164 } else {
4159 Register value(ToRegister(instr->value())); 4165 Register value(ToRegister(instr->value()));
4160 switch (elements_kind) { 4166 switch (elements_kind) {
4161 case EXTERNAL_PIXEL_ELEMENTS: 4167 case EXTERNAL_PIXEL_ELEMENTS:
4162 case EXTERNAL_BYTE_ELEMENTS: 4168 case EXTERNAL_BYTE_ELEMENTS:
4163 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 4169 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4170 case INT8_ELEMENTS:
4171 case UINT8_ELEMENTS:
4172 case UINT8_CLAMPED_ELEMENTS:
4164 __ movb(operand, value); 4173 __ movb(operand, value);
4165 break; 4174 break;
4166 case EXTERNAL_SHORT_ELEMENTS: 4175 case EXTERNAL_SHORT_ELEMENTS:
4167 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 4176 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4177 case INT16_ELEMENTS:
4178 case UINT16_ELEMENTS:
4168 __ movw(operand, value); 4179 __ movw(operand, value);
4169 break; 4180 break;
4170 case EXTERNAL_INT_ELEMENTS: 4181 case EXTERNAL_INT_ELEMENTS:
4171 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 4182 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4183 case INT32_ELEMENTS:
4184 case UINT32_ELEMENTS:
4172 __ movl(operand, value); 4185 __ movl(operand, value);
4173 break; 4186 break;
4174 case EXTERNAL_FLOAT_ELEMENTS: 4187 case EXTERNAL_FLOAT_ELEMENTS:
4175 case EXTERNAL_DOUBLE_ELEMENTS: 4188 case EXTERNAL_DOUBLE_ELEMENTS:
4189 case FLOAT32_ELEMENTS:
4190 case FLOAT64_ELEMENTS:
4176 case FAST_ELEMENTS: 4191 case FAST_ELEMENTS:
4177 case FAST_SMI_ELEMENTS: 4192 case FAST_SMI_ELEMENTS:
4178 case FAST_DOUBLE_ELEMENTS: 4193 case FAST_DOUBLE_ELEMENTS:
4179 case FAST_HOLEY_ELEMENTS: 4194 case FAST_HOLEY_ELEMENTS:
4180 case FAST_HOLEY_SMI_ELEMENTS: 4195 case FAST_HOLEY_SMI_ELEMENTS:
4181 case FAST_HOLEY_DOUBLE_ELEMENTS: 4196 case FAST_HOLEY_DOUBLE_ELEMENTS:
4182 case DICTIONARY_ELEMENTS: 4197 case DICTIONARY_ELEMENTS:
4183 case NON_STRICT_ARGUMENTS_ELEMENTS: 4198 case NON_STRICT_ARGUMENTS_ELEMENTS:
4184 UNREACHABLE(); 4199 UNREACHABLE();
4185 break; 4200 break;
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
4297 key_reg, 4312 key_reg,
4298 value, 4313 value,
4299 kSaveFPRegs, 4314 kSaveFPRegs,
4300 EMIT_REMEMBERED_SET, 4315 EMIT_REMEMBERED_SET,
4301 check_needed); 4316 check_needed);
4302 } 4317 }
4303 } 4318 }
4304 4319
4305 4320
4306 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { 4321 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
4307 if (instr->is_external()) { 4322 if (instr->is_typed_elements()) {
4308 DoStoreKeyedExternalArray(instr); 4323 DoStoreKeyedExternalArray(instr);
4309 } else if (instr->hydrogen()->value()->representation().IsDouble()) { 4324 } else if (instr->hydrogen()->value()->representation().IsDouble()) {
4310 DoStoreKeyedFixedDoubleArray(instr); 4325 DoStoreKeyedFixedDoubleArray(instr);
4311 } else { 4326 } else {
4312 DoStoreKeyedFixedArray(instr); 4327 DoStoreKeyedFixedArray(instr);
4313 } 4328 }
4314 } 4329 }
4315 4330
4316 4331
4317 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { 4332 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
(...skipping 16 matching lines...) Expand all
4334 Handle<Map> to_map = instr->transitioned_map(); 4349 Handle<Map> to_map = instr->transitioned_map();
4335 ElementsKind from_kind = instr->from_kind(); 4350 ElementsKind from_kind = instr->from_kind();
4336 ElementsKind to_kind = instr->to_kind(); 4351 ElementsKind to_kind = instr->to_kind();
4337 4352
4338 Label not_applicable; 4353 Label not_applicable;
4339 __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); 4354 __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map);
4340 __ j(not_equal, &not_applicable); 4355 __ j(not_equal, &not_applicable);
4341 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { 4356 if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
4342 Register new_map_reg = ToRegister(instr->new_map_temp()); 4357 Register new_map_reg = ToRegister(instr->new_map_temp());
4343 __ Move(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT); 4358 __ Move(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT);
4344 __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); 4359 __ movp(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg);
4345 // Write barrier. 4360 // Write barrier.
4346 ASSERT_NE(instr->temp(), NULL); 4361 ASSERT_NE(instr->temp(), NULL);
4347 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, 4362 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
4348 ToRegister(instr->temp()), kDontSaveFPRegs); 4363 ToRegister(instr->temp()), kDontSaveFPRegs);
4349 } else { 4364 } else {
4350 ASSERT(ToRegister(instr->context()).is(rsi)); 4365 ASSERT(ToRegister(instr->context()).is(rsi));
4351 PushSafepointRegistersScope scope(this); 4366 PushSafepointRegistersScope scope(this);
4352 if (!object_reg.is(rax)) { 4367 if (!object_reg.is(rax)) {
4353 __ movq(rax, object_reg); 4368 __ movp(rax, object_reg);
4354 } 4369 }
4355 __ Move(rbx, to_map); 4370 __ Move(rbx, to_map);
4356 TransitionElementsKindStub stub(from_kind, to_kind); 4371 TransitionElementsKindStub stub(from_kind, to_kind);
4357 __ CallStub(&stub); 4372 __ CallStub(&stub);
4358 RecordSafepointWithRegisters( 4373 RecordSafepointWithRegisters(
4359 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); 4374 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
4360 } 4375 }
4361 __ bind(&not_applicable); 4376 __ bind(&not_applicable);
4362 } 4377 }
4363 4378
4364 4379
4365 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { 4380 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
4366 Register object = ToRegister(instr->object()); 4381 Register object = ToRegister(instr->object());
4367 Register temp = ToRegister(instr->temp()); 4382 Register temp = ToRegister(instr->temp());
4368 Label no_memento_found; 4383 Label no_memento_found;
4369 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); 4384 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
4370 DeoptimizeIf(equal, instr->environment()); 4385 DeoptimizeIf(equal, instr->environment());
4371 __ bind(&no_memento_found); 4386 __ bind(&no_memento_found);
4372 } 4387 }
4373 4388
4374 4389
4375 void LCodeGen::DoStringAdd(LStringAdd* instr) { 4390 void LCodeGen::DoStringAdd(LStringAdd* instr) {
4376 ASSERT(ToRegister(instr->context()).is(rsi)); 4391 ASSERT(ToRegister(instr->context()).is(rsi));
4377 if (FLAG_new_string_add) { 4392 ASSERT(ToRegister(instr->left()).is(rdx));
4378 ASSERT(ToRegister(instr->left()).is(rdx)); 4393 ASSERT(ToRegister(instr->right()).is(rax));
4379 ASSERT(ToRegister(instr->right()).is(rax)); 4394 StringAddStub stub(instr->hydrogen()->flags(),
4380 NewStringAddStub stub(instr->hydrogen()->flags(), 4395 isolate()->heap()->GetPretenureMode());
4381 isolate()->heap()->GetPretenureMode()); 4396 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
4382 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
4383 } else {
4384 EmitPushTaggedOperand(instr->left());
4385 EmitPushTaggedOperand(instr->right());
4386 StringAddStub stub(instr->hydrogen()->flags());
4387 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
4388 }
4389 } 4397 }
4390 4398
4391 4399
4392 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { 4400 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
4393 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { 4401 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode {
4394 public: 4402 public:
4395 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) 4403 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
4396 : LDeferredCode(codegen), instr_(instr) { } 4404 : LDeferredCode(codegen), instr_(instr) { }
4397 virtual void Generate() V8_OVERRIDE { 4405 virtual void Generate() V8_OVERRIDE {
4398 codegen()->DoDeferredStringCharCodeAt(instr_); 4406 codegen()->DoDeferredStringCharCodeAt(instr_);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
4462 4470
4463 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); 4471 ASSERT(instr->hydrogen()->value()->representation().IsInteger32());
4464 Register char_code = ToRegister(instr->char_code()); 4472 Register char_code = ToRegister(instr->char_code());
4465 Register result = ToRegister(instr->result()); 4473 Register result = ToRegister(instr->result());
4466 ASSERT(!char_code.is(result)); 4474 ASSERT(!char_code.is(result));
4467 4475
4468 __ cmpl(char_code, Immediate(String::kMaxOneByteCharCode)); 4476 __ cmpl(char_code, Immediate(String::kMaxOneByteCharCode));
4469 __ j(above, deferred->entry()); 4477 __ j(above, deferred->entry());
4470 __ movsxlq(char_code, char_code); 4478 __ movsxlq(char_code, char_code);
4471 __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex); 4479 __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex);
4472 __ movq(result, FieldOperand(result, 4480 __ movp(result, FieldOperand(result,
4473 char_code, times_pointer_size, 4481 char_code, times_pointer_size,
4474 FixedArray::kHeaderSize)); 4482 FixedArray::kHeaderSize));
4475 __ CompareRoot(result, Heap::kUndefinedValueRootIndex); 4483 __ CompareRoot(result, Heap::kUndefinedValueRootIndex);
4476 __ j(equal, deferred->entry()); 4484 __ j(equal, deferred->entry());
4477 __ bind(deferred->exit()); 4485 __ bind(deferred->exit());
4478 } 4486 }
4479 4487
4480 4488
4481 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { 4489 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
4482 Register char_code = ToRegister(instr->char_code()); 4490 Register char_code = ToRegister(instr->char_code());
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
4608 // Put a valid pointer value in the stack slot where the result 4616 // Put a valid pointer value in the stack slot where the result
4609 // register is stored, as this register is in the pointer map, but contains an 4617 // register is stored, as this register is in the pointer map, but contains an
4610 // integer value. 4618 // integer value.
4611 __ StoreToSafepointRegisterSlot(reg, Immediate(0)); 4619 __ StoreToSafepointRegisterSlot(reg, Immediate(0));
4612 4620
4613 // NumberTagU uses the context from the frame, rather than 4621 // NumberTagU uses the context from the frame, rather than
4614 // the environment's HContext or HInlinedContext value. 4622 // the environment's HContext or HInlinedContext value.
4615 // They only call Runtime::kAllocateHeapNumber. 4623 // They only call Runtime::kAllocateHeapNumber.
4616 // The corresponding HChange instructions are added in a phase that does 4624 // The corresponding HChange instructions are added in a phase that does
4617 // not have easy access to the local context. 4625 // not have easy access to the local context.
4618 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 4626 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
4619 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 4627 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
4620 RecordSafepointWithRegisters( 4628 RecordSafepointWithRegisters(
4621 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); 4629 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
4622 4630
4623 if (!reg.is(rax)) __ movq(reg, rax); 4631 if (!reg.is(rax)) __ movp(reg, rax);
4624 4632
4625 // Done. Put the value in temp_xmm into the value of the allocated heap 4633 // Done. Put the value in temp_xmm into the value of the allocated heap
4626 // number. 4634 // number.
4627 __ bind(&done); 4635 __ bind(&done);
4628 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), temp_xmm); 4636 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), temp_xmm);
4629 __ StoreToSafepointRegisterSlot(reg, reg); 4637 __ StoreToSafepointRegisterSlot(reg, reg);
4630 } 4638 }
4631 4639
4632 4640
4633 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { 4641 void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4665 Register reg = ToRegister(instr->result()); 4673 Register reg = ToRegister(instr->result());
4666 __ Move(reg, Smi::FromInt(0)); 4674 __ Move(reg, Smi::FromInt(0));
4667 4675
4668 { 4676 {
4669 PushSafepointRegistersScope scope(this); 4677 PushSafepointRegistersScope scope(this);
4670 // NumberTagD uses the context from the frame, rather than 4678 // NumberTagD uses the context from the frame, rather than
4671 // the environment's HContext or HInlinedContext value. 4679 // the environment's HContext or HInlinedContext value.
4672 // They only call Runtime::kAllocateHeapNumber. 4680 // They only call Runtime::kAllocateHeapNumber.
4673 // The corresponding HChange instructions are added in a phase that does 4681 // The corresponding HChange instructions are added in a phase that does
4674 // not have easy access to the local context. 4682 // not have easy access to the local context.
4675 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 4683 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
4676 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 4684 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
4677 RecordSafepointWithRegisters( 4685 RecordSafepointWithRegisters(
4678 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); 4686 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
4679 __ movq(kScratchRegister, rax); 4687 __ movp(kScratchRegister, rax);
4680 } 4688 }
4681 __ movq(reg, kScratchRegister); 4689 __ movp(reg, kScratchRegister);
4682 } 4690 }
4683 4691
4684 4692
4685 void LCodeGen::DoSmiTag(LSmiTag* instr) { 4693 void LCodeGen::DoSmiTag(LSmiTag* instr) {
4686 ASSERT(instr->value()->Equals(instr->result())); 4694 ASSERT(instr->value()->Equals(instr->result()));
4687 Register input = ToRegister(instr->value()); 4695 Register input = ToRegister(instr->value());
4688 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); 4696 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow));
4689 __ Integer32ToSmi(input, input); 4697 __ Integer32ToSmi(input, input);
4690 } 4698 }
4691 4699
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
4920 LOperand* input = instr->value(); 4928 LOperand* input = instr->value();
4921 Condition cc = masm()->CheckSmi(ToRegister(input)); 4929 Condition cc = masm()->CheckSmi(ToRegister(input));
4922 DeoptimizeIf(cc, instr->environment()); 4930 DeoptimizeIf(cc, instr->environment());
4923 } 4931 }
4924 } 4932 }
4925 4933
4926 4934
4927 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 4935 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
4928 Register input = ToRegister(instr->value()); 4936 Register input = ToRegister(instr->value());
4929 4937
4930 __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); 4938 __ movp(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset));
4931 4939
4932 if (instr->hydrogen()->is_interval_check()) { 4940 if (instr->hydrogen()->is_interval_check()) {
4933 InstanceType first; 4941 InstanceType first;
4934 InstanceType last; 4942 InstanceType last;
4935 instr->hydrogen()->GetCheckInterval(&first, &last); 4943 instr->hydrogen()->GetCheckInterval(&first, &last);
4936 4944
4937 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), 4945 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset),
4938 Immediate(static_cast<int8_t>(first))); 4946 Immediate(static_cast<int8_t>(first)));
4939 4947
4940 // If there is only one type in the interval check for equality. 4948 // If there is only one type in the interval check for equality.
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
5068 5076
5069 // Check for heap number 5077 // Check for heap number
5070 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5078 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5071 factory()->heap_number_map()); 5079 factory()->heap_number_map());
5072 __ j(equal, &heap_number, Label::kNear); 5080 __ j(equal, &heap_number, Label::kNear);
5073 5081
5074 // Check for undefined. Undefined is converted to zero for clamping 5082 // Check for undefined. Undefined is converted to zero for clamping
5075 // conversions. 5083 // conversions.
5076 __ Cmp(input_reg, factory()->undefined_value()); 5084 __ Cmp(input_reg, factory()->undefined_value());
5077 DeoptimizeIf(not_equal, instr->environment()); 5085 DeoptimizeIf(not_equal, instr->environment());
5078 __ movq(input_reg, Immediate(0)); 5086 __ movp(input_reg, Immediate(0));
5079 __ jmp(&done, Label::kNear); 5087 __ jmp(&done, Label::kNear);
5080 5088
5081 // Heap number 5089 // Heap number
5082 __ bind(&heap_number); 5090 __ bind(&heap_number);
5083 __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset)); 5091 __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset));
5084 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg); 5092 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg);
5085 __ jmp(&done, Label::kNear); 5093 __ jmp(&done, Label::kNear);
5086 5094
5087 // smi 5095 // smi
5088 __ bind(&is_smi); 5096 __ bind(&is_smi);
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
5203 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { 5211 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
5204 ASSERT(ToRegister(instr->context()).is(rsi)); 5212 ASSERT(ToRegister(instr->context()).is(rsi));
5205 Label materialized; 5213 Label materialized;
5206 // Registers will be used as follows: 5214 // Registers will be used as follows:
5207 // rcx = literals array. 5215 // rcx = literals array.
5208 // rbx = regexp literal. 5216 // rbx = regexp literal.
5209 // rax = regexp literal clone. 5217 // rax = regexp literal clone.
5210 int literal_offset = 5218 int literal_offset =
5211 FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); 5219 FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
5212 __ Move(rcx, instr->hydrogen()->literals()); 5220 __ Move(rcx, instr->hydrogen()->literals());
5213 __ movq(rbx, FieldOperand(rcx, literal_offset)); 5221 __ movp(rbx, FieldOperand(rcx, literal_offset));
5214 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); 5222 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
5215 __ j(not_equal, &materialized, Label::kNear); 5223 __ j(not_equal, &materialized, Label::kNear);
5216 5224
5217 // Create regexp literal using runtime function 5225 // Create regexp literal using runtime function
5218 // Result will be in rax. 5226 // Result will be in rax.
5219 __ push(rcx); 5227 __ push(rcx);
5220 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); 5228 __ Push(Smi::FromInt(instr->hydrogen()->literal_index()));
5221 __ Push(instr->hydrogen()->pattern()); 5229 __ Push(instr->hydrogen()->pattern());
5222 __ Push(instr->hydrogen()->flags()); 5230 __ Push(instr->hydrogen()->flags());
5223 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); 5231 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
5224 __ movq(rbx, rax); 5232 __ movp(rbx, rax);
5225 5233
5226 __ bind(&materialized); 5234 __ bind(&materialized);
5227 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 5235 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
5228 Label allocated, runtime_allocate; 5236 Label allocated, runtime_allocate;
5229 __ Allocate(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT); 5237 __ Allocate(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT);
5230 __ jmp(&allocated, Label::kNear); 5238 __ jmp(&allocated, Label::kNear);
5231 5239
5232 __ bind(&runtime_allocate); 5240 __ bind(&runtime_allocate);
5233 __ push(rbx); 5241 __ push(rbx);
5234 __ Push(Smi::FromInt(size)); 5242 __ Push(Smi::FromInt(size));
5235 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); 5243 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
5236 __ pop(rbx); 5244 __ pop(rbx);
5237 5245
5238 __ bind(&allocated); 5246 __ bind(&allocated);
5239 // Copy the content into the newly allocated memory. 5247 // Copy the content into the newly allocated memory.
5240 // (Unroll copy loop once for better throughput). 5248 // (Unroll copy loop once for better throughput).
5241 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { 5249 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
5242 __ movq(rdx, FieldOperand(rbx, i)); 5250 __ movp(rdx, FieldOperand(rbx, i));
5243 __ movq(rcx, FieldOperand(rbx, i + kPointerSize)); 5251 __ movp(rcx, FieldOperand(rbx, i + kPointerSize));
5244 __ movq(FieldOperand(rax, i), rdx); 5252 __ movp(FieldOperand(rax, i), rdx);
5245 __ movq(FieldOperand(rax, i + kPointerSize), rcx); 5253 __ movp(FieldOperand(rax, i + kPointerSize), rcx);
5246 } 5254 }
5247 if ((size % (2 * kPointerSize)) != 0) { 5255 if ((size % (2 * kPointerSize)) != 0) {
5248 __ movq(rdx, FieldOperand(rbx, size - kPointerSize)); 5256 __ movp(rdx, FieldOperand(rbx, size - kPointerSize));
5249 __ movq(FieldOperand(rax, size - kPointerSize), rdx); 5257 __ movp(FieldOperand(rax, size - kPointerSize), rdx);
5250 } 5258 }
5251 } 5259 }
5252 5260
5253 5261
5254 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { 5262 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
5255 ASSERT(ToRegister(instr->context()).is(rsi)); 5263 ASSERT(ToRegister(instr->context()).is(rsi));
5256 // Use the fast case closure allocation code that allocates in new 5264 // Use the fast case closure allocation code that allocates in new
5257 // space for nested functions that don't need literals cloning. 5265 // space for nested functions that don't need literals cloning.
5258 bool pretenure = instr->hydrogen()->pretenure(); 5266 bool pretenure = instr->hydrogen()->pretenure();
5259 if (!pretenure && instr->hydrogen()->has_no_literals()) { 5267 if (!pretenure && instr->hydrogen()->has_no_literals()) {
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
5341 5349
5342 } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) { 5350 } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) {
5343 __ CompareRoot(input, Heap::kNullValueRootIndex); 5351 __ CompareRoot(input, Heap::kNullValueRootIndex);
5344 final_branch_condition = equal; 5352 final_branch_condition = equal;
5345 5353
5346 } else if (type_name->Equals(heap()->undefined_string())) { 5354 } else if (type_name->Equals(heap()->undefined_string())) {
5347 __ CompareRoot(input, Heap::kUndefinedValueRootIndex); 5355 __ CompareRoot(input, Heap::kUndefinedValueRootIndex);
5348 __ j(equal, true_label, true_distance); 5356 __ j(equal, true_label, true_distance);
5349 __ JumpIfSmi(input, false_label, false_distance); 5357 __ JumpIfSmi(input, false_label, false_distance);
5350 // Check for undetectable objects => true. 5358 // Check for undetectable objects => true.
5351 __ movq(input, FieldOperand(input, HeapObject::kMapOffset)); 5359 __ movp(input, FieldOperand(input, HeapObject::kMapOffset));
5352 __ testb(FieldOperand(input, Map::kBitFieldOffset), 5360 __ testb(FieldOperand(input, Map::kBitFieldOffset),
5353 Immediate(1 << Map::kIsUndetectable)); 5361 Immediate(1 << Map::kIsUndetectable));
5354 final_branch_condition = not_zero; 5362 final_branch_condition = not_zero;
5355 5363
5356 } else if (type_name->Equals(heap()->function_string())) { 5364 } else if (type_name->Equals(heap()->function_string())) {
5357 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 5365 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
5358 __ JumpIfSmi(input, false_label, false_distance); 5366 __ JumpIfSmi(input, false_label, false_distance);
5359 __ CmpObjectType(input, JS_FUNCTION_TYPE, input); 5367 __ CmpObjectType(input, JS_FUNCTION_TYPE, input);
5360 __ j(equal, true_label, true_distance); 5368 __ j(equal, true_label, true_distance);
5361 __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE); 5369 __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE);
(...skipping 25 matching lines...) Expand all
5387 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 5395 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
5388 Register temp = ToRegister(instr->temp()); 5396 Register temp = ToRegister(instr->temp());
5389 5397
5390 EmitIsConstructCall(temp); 5398 EmitIsConstructCall(temp);
5391 EmitBranch(instr, equal); 5399 EmitBranch(instr, equal);
5392 } 5400 }
5393 5401
5394 5402
5395 void LCodeGen::EmitIsConstructCall(Register temp) { 5403 void LCodeGen::EmitIsConstructCall(Register temp) {
5396 // Get the frame pointer for the calling frame. 5404 // Get the frame pointer for the calling frame.
5397 __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 5405 __ movp(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
5398 5406
5399 // Skip the arguments adaptor frame if it exists. 5407 // Skip the arguments adaptor frame if it exists.
5400 Label check_frame_marker; 5408 Label check_frame_marker;
5401 __ Cmp(Operand(temp, StandardFrameConstants::kContextOffset), 5409 __ Cmp(Operand(temp, StandardFrameConstants::kContextOffset),
5402 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 5410 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
5403 __ j(not_equal, &check_frame_marker, Label::kNear); 5411 __ j(not_equal, &check_frame_marker, Label::kNear);
5404 __ movq(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset)); 5412 __ movp(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset));
5405 5413
5406 // Check the marker in the calling frame. 5414 // Check the marker in the calling frame.
5407 __ bind(&check_frame_marker); 5415 __ bind(&check_frame_marker);
5408 __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), 5416 __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset),
5409 Smi::FromInt(StackFrame::CONSTRUCT)); 5417 Smi::FromInt(StackFrame::CONSTRUCT));
5410 } 5418 }
5411 5419
5412 5420
5413 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { 5421 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) {
5414 if (!info()->IsStub()) { 5422 if (!info()->IsStub()) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
5453 } 5461 }
5454 5462
5455 5463
5456 void LCodeGen::DoDummyUse(LDummyUse* instr) { 5464 void LCodeGen::DoDummyUse(LDummyUse* instr) {
5457 // Nothing to see here, move on! 5465 // Nothing to see here, move on!
5458 } 5466 }
5459 5467
5460 5468
5461 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { 5469 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
5462 PushSafepointRegistersScope scope(this); 5470 PushSafepointRegistersScope scope(this);
5463 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 5471 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
5464 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); 5472 __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
5465 RecordSafepointWithLazyDeopt(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0); 5473 RecordSafepointWithLazyDeopt(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0);
5466 ASSERT(instr->HasEnvironment()); 5474 ASSERT(instr->HasEnvironment());
5467 LEnvironment* env = instr->environment(); 5475 LEnvironment* env = instr->environment();
5468 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); 5476 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
5469 } 5477 }
5470 5478
5471 5479
5472 void LCodeGen::DoStackCheck(LStackCheck* instr) { 5480 void LCodeGen::DoStackCheck(LStackCheck* instr) {
5473 class DeferredStackCheck V8_FINAL : public LDeferredCode { 5481 class DeferredStackCheck V8_FINAL : public LDeferredCode {
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
5547 Condition cc = masm()->CheckSmi(rax); 5555 Condition cc = masm()->CheckSmi(rax);
5548 DeoptimizeIf(cc, instr->environment()); 5556 DeoptimizeIf(cc, instr->environment());
5549 5557
5550 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 5558 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
5551 __ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx); 5559 __ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx);
5552 DeoptimizeIf(below_equal, instr->environment()); 5560 DeoptimizeIf(below_equal, instr->environment());
5553 5561
5554 Label use_cache, call_runtime; 5562 Label use_cache, call_runtime;
5555 __ CheckEnumCache(null_value, &call_runtime); 5563 __ CheckEnumCache(null_value, &call_runtime);
5556 5564
5557 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset)); 5565 __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
5558 __ jmp(&use_cache, Label::kNear); 5566 __ jmp(&use_cache, Label::kNear);
5559 5567
5560 // Get the set of properties to enumerate. 5568 // Get the set of properties to enumerate.
5561 __ bind(&call_runtime); 5569 __ bind(&call_runtime);
5562 __ push(rax); 5570 __ push(rax);
5563 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); 5571 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
5564 5572
5565 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 5573 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
5566 Heap::kMetaMapRootIndex); 5574 Heap::kMetaMapRootIndex);
5567 DeoptimizeIf(not_equal, instr->environment()); 5575 DeoptimizeIf(not_equal, instr->environment());
5568 __ bind(&use_cache); 5576 __ bind(&use_cache);
5569 } 5577 }
5570 5578
5571 5579
5572 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { 5580 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
5573 Register map = ToRegister(instr->map()); 5581 Register map = ToRegister(instr->map());
5574 Register result = ToRegister(instr->result()); 5582 Register result = ToRegister(instr->result());
5575 Label load_cache, done; 5583 Label load_cache, done;
5576 __ EnumLength(result, map); 5584 __ EnumLength(result, map);
5577 __ Cmp(result, Smi::FromInt(0)); 5585 __ Cmp(result, Smi::FromInt(0));
5578 __ j(not_equal, &load_cache, Label::kNear); 5586 __ j(not_equal, &load_cache, Label::kNear);
5579 __ LoadRoot(result, Heap::kEmptyFixedArrayRootIndex); 5587 __ LoadRoot(result, Heap::kEmptyFixedArrayRootIndex);
5580 __ jmp(&done, Label::kNear); 5588 __ jmp(&done, Label::kNear);
5581 __ bind(&load_cache); 5589 __ bind(&load_cache);
5582 __ LoadInstanceDescriptors(map, result); 5590 __ LoadInstanceDescriptors(map, result);
5583 __ movq(result, 5591 __ movp(result,
5584 FieldOperand(result, DescriptorArray::kEnumCacheOffset)); 5592 FieldOperand(result, DescriptorArray::kEnumCacheOffset));
5585 __ movq(result, 5593 __ movp(result,
5586 FieldOperand(result, FixedArray::SizeFor(instr->idx()))); 5594 FieldOperand(result, FixedArray::SizeFor(instr->idx())));
5587 __ bind(&done); 5595 __ bind(&done);
5588 Condition cc = masm()->CheckSmi(result); 5596 Condition cc = masm()->CheckSmi(result);
5589 DeoptimizeIf(cc, instr->environment()); 5597 DeoptimizeIf(cc, instr->environment());
5590 } 5598 }
5591 5599
5592 5600
5593 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { 5601 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
5594 Register object = ToRegister(instr->value()); 5602 Register object = ToRegister(instr->value());
5595 __ cmpq(ToRegister(instr->map()), 5603 __ cmpq(ToRegister(instr->map()),
5596 FieldOperand(object, HeapObject::kMapOffset)); 5604 FieldOperand(object, HeapObject::kMapOffset));
5597 DeoptimizeIf(not_equal, instr->environment()); 5605 DeoptimizeIf(not_equal, instr->environment());
5598 } 5606 }
5599 5607
5600 5608
5601 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { 5609 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
5602 Register object = ToRegister(instr->object()); 5610 Register object = ToRegister(instr->object());
5603 Register index = ToRegister(instr->index()); 5611 Register index = ToRegister(instr->index());
5604 5612
5605 Label out_of_object, done; 5613 Label out_of_object, done;
5606 __ SmiToInteger32(index, index); 5614 __ SmiToInteger32(index, index);
5607 __ cmpl(index, Immediate(0)); 5615 __ cmpl(index, Immediate(0));
5608 __ j(less, &out_of_object, Label::kNear); 5616 __ j(less, &out_of_object, Label::kNear);
5609 __ movq(object, FieldOperand(object, 5617 __ movp(object, FieldOperand(object,
5610 index, 5618 index,
5611 times_pointer_size, 5619 times_pointer_size,
5612 JSObject::kHeaderSize)); 5620 JSObject::kHeaderSize));
5613 __ jmp(&done, Label::kNear); 5621 __ jmp(&done, Label::kNear);
5614 5622
5615 __ bind(&out_of_object); 5623 __ bind(&out_of_object);
5616 __ movq(object, FieldOperand(object, JSObject::kPropertiesOffset)); 5624 __ movp(object, FieldOperand(object, JSObject::kPropertiesOffset));
5617 __ negl(index); 5625 __ negl(index);
5618 // Index is now equal to out of object property index plus 1. 5626 // Index is now equal to out of object property index plus 1.
5619 __ movq(object, FieldOperand(object, 5627 __ movp(object, FieldOperand(object,
5620 index, 5628 index,
5621 times_pointer_size, 5629 times_pointer_size,
5622 FixedArray::kHeaderSize - kPointerSize)); 5630 FixedArray::kHeaderSize - kPointerSize));
5623 __ bind(&done); 5631 __ bind(&done);
5624 } 5632 }
5625 5633
5626 5634
5627 #undef __ 5635 #undef __
5628 5636
5629 } } // namespace v8::internal 5637 } } // namespace v8::internal
5630 5638
5631 #endif // V8_TARGET_ARCH_X64 5639 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/ic-x64.cc ('k') | src/x64/lithium-gap-resolver-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698