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

Side by Side Diff: src/x64/code-stubs-x64.cc

Issue 151163005: A64: Synchronize with r16356. (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/builtins-x64.cc ('k') | src/x64/codegen-x64.h » ('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 21 matching lines...) Expand all
32 #include "bootstrapper.h" 32 #include "bootstrapper.h"
33 #include "code-stubs.h" 33 #include "code-stubs.h"
34 #include "regexp-macro-assembler.h" 34 #include "regexp-macro-assembler.h"
35 #include "stub-cache.h" 35 #include "stub-cache.h"
36 #include "runtime.h" 36 #include "runtime.h"
37 37
38 namespace v8 { 38 namespace v8 {
39 namespace internal { 39 namespace internal {
40 40
41 41
42 void FastNewClosureStub::InitializeInterfaceDescriptor(
43 Isolate* isolate,
44 CodeStubInterfaceDescriptor* descriptor) {
45 static Register registers[] = { rbx };
46 descriptor->register_param_count_ = 1;
47 descriptor->register_params_ = registers;
48 descriptor->deoptimization_handler_ =
49 Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry;
50 }
51
52
42 void ToNumberStub::InitializeInterfaceDescriptor( 53 void ToNumberStub::InitializeInterfaceDescriptor(
43 Isolate* isolate, 54 Isolate* isolate,
44 CodeStubInterfaceDescriptor* descriptor) { 55 CodeStubInterfaceDescriptor* descriptor) {
45 static Register registers[] = { rax }; 56 static Register registers[] = { rax };
46 descriptor->register_param_count_ = 1; 57 descriptor->register_param_count_ = 1;
47 descriptor->register_params_ = registers; 58 descriptor->register_params_ = registers;
48 descriptor->deoptimization_handler_ = NULL; 59 descriptor->deoptimization_handler_ = NULL;
49 } 60 }
50 61
51 62
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 __ push(descriptor->register_params_[i]); 299 __ push(descriptor->register_params_[i]);
289 } 300 }
290 ExternalReference miss = descriptor->miss_handler(); 301 ExternalReference miss = descriptor->miss_handler();
291 __ CallExternalReference(miss, descriptor->register_param_count_); 302 __ CallExternalReference(miss, descriptor->register_param_count_);
292 } 303 }
293 304
294 __ Ret(); 305 __ Ret();
295 } 306 }
296 307
297 308
298 void FastNewClosureStub::Generate(MacroAssembler* masm) {
299 // Create a new closure from the given function info in new
300 // space. Set the context to the current context in rsi.
301 Counters* counters = masm->isolate()->counters();
302
303 Label gc;
304 __ Allocate(JSFunction::kSize, rax, rbx, rcx, &gc, TAG_OBJECT);
305
306 __ IncrementCounter(counters->fast_new_closure_total(), 1);
307
308 // Get the function info from the stack.
309 __ movq(rdx, Operand(rsp, 1 * kPointerSize));
310
311 int map_index = Context::FunctionMapIndex(language_mode_, is_generator_);
312
313 // Compute the function map in the current native context and set that
314 // as the map of the allocated object.
315 __ movq(rcx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
316 __ movq(rcx, FieldOperand(rcx, GlobalObject::kNativeContextOffset));
317 __ movq(rbx, Operand(rcx, Context::SlotOffset(map_index)));
318 __ movq(FieldOperand(rax, JSObject::kMapOffset), rbx);
319
320 // Initialize the rest of the function. We don't have to update the
321 // write barrier because the allocated object is in new space.
322 __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex);
323 __ LoadRoot(r8, Heap::kTheHoleValueRootIndex);
324 __ LoadRoot(rdi, Heap::kUndefinedValueRootIndex);
325 __ movq(FieldOperand(rax, JSObject::kPropertiesOffset), rbx);
326 __ movq(FieldOperand(rax, JSObject::kElementsOffset), rbx);
327 __ movq(FieldOperand(rax, JSFunction::kPrototypeOrInitialMapOffset), r8);
328 __ movq(FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset), rdx);
329 __ movq(FieldOperand(rax, JSFunction::kContextOffset), rsi);
330 __ movq(FieldOperand(rax, JSFunction::kLiteralsOffset), rbx);
331
332 // Initialize the code pointer in the function to be the one
333 // found in the shared function info object.
334 // But first check if there is an optimized version for our context.
335 Label check_optimized;
336 Label install_unoptimized;
337 if (FLAG_cache_optimized_code) {
338 __ movq(rbx,
339 FieldOperand(rdx, SharedFunctionInfo::kOptimizedCodeMapOffset));
340 __ testq(rbx, rbx);
341 __ j(not_zero, &check_optimized, Label::kNear);
342 }
343 __ bind(&install_unoptimized);
344 __ movq(FieldOperand(rax, JSFunction::kNextFunctionLinkOffset),
345 rdi); // Initialize with undefined.
346 __ movq(rdx, FieldOperand(rdx, SharedFunctionInfo::kCodeOffset));
347 __ lea(rdx, FieldOperand(rdx, Code::kHeaderSize));
348 __ movq(FieldOperand(rax, JSFunction::kCodeEntryOffset), rdx);
349
350 // Return and remove the on-stack parameter.
351 __ ret(1 * kPointerSize);
352
353 __ bind(&check_optimized);
354
355 __ IncrementCounter(counters->fast_new_closure_try_optimized(), 1);
356
357 // rcx holds native context, rbx points to fixed array of 3-element entries
358 // (native context, optimized code, literals).
359 // The optimized code map must never be empty, so check the first elements.
360 Label install_optimized;
361 // Speculatively move code object into edx.
362 __ movq(rdx, FieldOperand(rbx, SharedFunctionInfo::kFirstCodeSlot));
363 __ cmpq(rcx, FieldOperand(rbx, SharedFunctionInfo::kFirstContextSlot));
364 __ j(equal, &install_optimized);
365
366 // Iterate through the rest of map backwards. rdx holds an index.
367 Label loop;
368 Label restore;
369 __ movq(rdx, FieldOperand(rbx, FixedArray::kLengthOffset));
370 __ SmiToInteger32(rdx, rdx);
371 __ bind(&loop);
372 // Do not double check first entry.
373 __ cmpq(rdx, Immediate(SharedFunctionInfo::kSecondEntryIndex));
374 __ j(equal, &restore);
375 __ subq(rdx, Immediate(SharedFunctionInfo::kEntryLength));
376 __ cmpq(rcx, FieldOperand(rbx,
377 rdx,
378 times_pointer_size,
379 FixedArray::kHeaderSize));
380 __ j(not_equal, &loop, Label::kNear);
381 // Hit: fetch the optimized code.
382 __ movq(rdx, FieldOperand(rbx,
383 rdx,
384 times_pointer_size,
385 FixedArray::kHeaderSize + 1 * kPointerSize));
386
387 __ bind(&install_optimized);
388 __ IncrementCounter(counters->fast_new_closure_install_optimized(), 1);
389
390 // TODO(fschneider): Idea: store proper code pointers in the map and either
391 // unmangle them on marking or do nothing as the whole map is discarded on
392 // major GC anyway.
393 __ lea(rdx, FieldOperand(rdx, Code::kHeaderSize));
394 __ movq(FieldOperand(rax, JSFunction::kCodeEntryOffset), rdx);
395
396 // Now link a function into a list of optimized functions.
397 __ movq(rdx, ContextOperand(rcx, Context::OPTIMIZED_FUNCTIONS_LIST));
398
399 __ movq(FieldOperand(rax, JSFunction::kNextFunctionLinkOffset), rdx);
400 // No need for write barrier as JSFunction (rax) is in the new space.
401
402 __ movq(ContextOperand(rcx, Context::OPTIMIZED_FUNCTIONS_LIST), rax);
403 // Store JSFunction (rax) into rdx before issuing write barrier as
404 // it clobbers all the registers passed.
405 __ movq(rdx, rax);
406 __ RecordWriteContextSlot(
407 rcx,
408 Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST),
409 rdx,
410 rbx,
411 kDontSaveFPRegs);
412
413 // Return and remove the on-stack parameter.
414 __ ret(1 * kPointerSize);
415
416 __ bind(&restore);
417 __ movq(rdx, Operand(rsp, 1 * kPointerSize));
418 __ jmp(&install_unoptimized);
419
420 // Create a new closure through the slower runtime call.
421 __ bind(&gc);
422 __ PopReturnAddressTo(rcx);
423 __ pop(rdx);
424 __ push(rsi);
425 __ push(rdx);
426 __ PushRoot(Heap::kFalseValueRootIndex);
427 __ PushReturnAddressFrom(rcx);
428 __ TailCallRuntime(Runtime::kNewClosure, 3, 1);
429 }
430
431
432 void FastNewContextStub::Generate(MacroAssembler* masm) { 309 void FastNewContextStub::Generate(MacroAssembler* masm) {
433 // Try to allocate the context in new space. 310 // Try to allocate the context in new space.
434 Label gc; 311 Label gc;
435 int length = slots_ + Context::MIN_CONTEXT_SLOTS; 312 int length = slots_ + Context::MIN_CONTEXT_SLOTS;
436 __ Allocate((length * kPointerSize) + FixedArray::kHeaderSize, 313 __ Allocate((length * kPointerSize) + FixedArray::kHeaderSize,
437 rax, rbx, rcx, &gc, TAG_OBJECT); 314 rax, rbx, rcx, &gc, TAG_OBJECT);
438 315
439 // Get the function from the stack. 316 // Get the function from the stack.
440 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); 317 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER);
318 __ movq(rcx, args.GetArgumentOperand(0));
441 319
442 // Set up the object header. 320 // Set up the object header.
443 __ LoadRoot(kScratchRegister, Heap::kFunctionContextMapRootIndex); 321 __ LoadRoot(kScratchRegister, Heap::kFunctionContextMapRootIndex);
444 __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister); 322 __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister);
445 __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length)); 323 __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length));
446 324
447 // Set up the fixed slots. 325 // Set up the fixed slots.
448 __ Set(rbx, 0); // Set to NULL. 326 __ Set(rbx, 0); // Set to NULL.
449 __ movq(Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)), rcx); 327 __ movq(Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)), rcx);
450 __ movq(Operand(rax, Context::SlotOffset(Context::PREVIOUS_INDEX)), rsi); 328 __ movq(Operand(rax, Context::SlotOffset(Context::PREVIOUS_INDEX)), rsi);
(...skipping 25 matching lines...) Expand all
476 // [rsp + (1 * kPointerSize)] : function 354 // [rsp + (1 * kPointerSize)] : function
477 // [rsp + (2 * kPointerSize)] : serialized scope info 355 // [rsp + (2 * kPointerSize)] : serialized scope info
478 356
479 // Try to allocate the context in new space. 357 // Try to allocate the context in new space.
480 Label gc; 358 Label gc;
481 int length = slots_ + Context::MIN_CONTEXT_SLOTS; 359 int length = slots_ + Context::MIN_CONTEXT_SLOTS;
482 __ Allocate(FixedArray::SizeFor(length), 360 __ Allocate(FixedArray::SizeFor(length),
483 rax, rbx, rcx, &gc, TAG_OBJECT); 361 rax, rbx, rcx, &gc, TAG_OBJECT);
484 362
485 // Get the function from the stack. 363 // Get the function from the stack.
486 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); 364 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER);
487 365 __ movq(rcx, args.GetArgumentOperand(1));
488 // Get the serialized scope info from the stack. 366 // Get the serialized scope info from the stack.
489 __ movq(rbx, Operand(rsp, 2 * kPointerSize)); 367 __ movq(rbx, args.GetArgumentOperand(0));
490 368
491 // Set up the object header. 369 // Set up the object header.
492 __ LoadRoot(kScratchRegister, Heap::kBlockContextMapRootIndex); 370 __ LoadRoot(kScratchRegister, Heap::kBlockContextMapRootIndex);
493 __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister); 371 __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister);
494 __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length)); 372 __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length));
495 373
496 // If this block context is nested in the native context we get a smi 374 // If this block context is nested in the native context we get a smi
497 // sentinel instead of a function. The block context should get the 375 // sentinel instead of a function. The block context should get the
498 // canonical empty function of the native context as its closure which 376 // canonical empty function of the native context as its closure which
499 // we still have to look up. 377 // we still have to look up.
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 public: 431 public:
554 enum ConvertUndefined { 432 enum ConvertUndefined {
555 CONVERT_UNDEFINED_TO_ZERO, 433 CONVERT_UNDEFINED_TO_ZERO,
556 BAILOUT_ON_UNDEFINED 434 BAILOUT_ON_UNDEFINED
557 }; 435 };
558 // Load the operands from rdx and rax into xmm0 and xmm1, as doubles. 436 // Load the operands from rdx and rax into xmm0 and xmm1, as doubles.
559 // If the operands are not both numbers, jump to not_numbers. 437 // If the operands are not both numbers, jump to not_numbers.
560 // Leaves rdx and rax unchanged. SmiOperands assumes both are smis. 438 // Leaves rdx and rax unchanged. SmiOperands assumes both are smis.
561 // NumberOperands assumes both are smis or heap numbers. 439 // NumberOperands assumes both are smis or heap numbers.
562 static void LoadSSE2SmiOperands(MacroAssembler* masm); 440 static void LoadSSE2SmiOperands(MacroAssembler* masm);
563 static void LoadSSE2NumberOperands(MacroAssembler* masm);
564 static void LoadSSE2UnknownOperands(MacroAssembler* masm, 441 static void LoadSSE2UnknownOperands(MacroAssembler* masm,
565 Label* not_numbers); 442 Label* not_numbers);
566 443
567 // Takes the operands in rdx and rax and loads them as integers in rax 444 // Takes the operands in rdx and rax and loads them as integers in rax
568 // and rcx. 445 // and rcx.
569 static void LoadAsIntegers(MacroAssembler* masm, 446 static void LoadAsIntegers(MacroAssembler* masm,
570 Label* operand_conversion_failure, 447 Label* operand_conversion_failure,
571 Register heap_number_map); 448 Register heap_number_map);
572 // As above, but we know the operands to be numbers. In that case,
573 // conversion can't fail.
574 static void LoadNumbersAsIntegers(MacroAssembler* masm);
575 449
576 // Tries to convert two values to smis losslessly. 450 // Tries to convert two values to smis losslessly.
577 // This fails if either argument is not a Smi nor a HeapNumber, 451 // This fails if either argument is not a Smi nor a HeapNumber,
578 // or if it's a HeapNumber with a value that can't be converted 452 // or if it's a HeapNumber with a value that can't be converted
579 // losslessly to a Smi. In that case, control transitions to the 453 // losslessly to a Smi. In that case, control transitions to the
580 // on_not_smis label. 454 // on_not_smis label.
581 // On success, either control goes to the on_success label (if one is 455 // On success, either control goes to the on_success label (if one is
582 // provided), or it falls through at the end of the code (if on_success 456 // provided), or it falls through at the end of the code (if on_success
583 // is NULL). 457 // is NULL).
584 // On success, both first and second holds Smi tagged values. 458 // On success, both first and second holds Smi tagged values.
(...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after
1256 // Output: 1130 // Output:
1257 // xmm1 : untagged double result. 1131 // xmm1 : untagged double result.
1258 1132
1259 Label runtime_call; 1133 Label runtime_call;
1260 Label runtime_call_clear_stack; 1134 Label runtime_call_clear_stack;
1261 Label skip_cache; 1135 Label skip_cache;
1262 const bool tagged = (argument_type_ == TAGGED); 1136 const bool tagged = (argument_type_ == TAGGED);
1263 if (tagged) { 1137 if (tagged) {
1264 Label input_not_smi, loaded; 1138 Label input_not_smi, loaded;
1265 // Test that rax is a number. 1139 // Test that rax is a number.
1266 __ movq(rax, Operand(rsp, kPointerSize)); 1140 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER);
1141 __ movq(rax, args.GetArgumentOperand(0));
1267 __ JumpIfNotSmi(rax, &input_not_smi, Label::kNear); 1142 __ JumpIfNotSmi(rax, &input_not_smi, Label::kNear);
1268 // Input is a smi. Untag and load it onto the FPU stack. 1143 // Input is a smi. Untag and load it onto the FPU stack.
1269 // Then load the bits of the double into rbx. 1144 // Then load the bits of the double into rbx.
1270 __ SmiToInteger32(rax, rax); 1145 __ SmiToInteger32(rax, rax);
1271 __ subq(rsp, Immediate(kDoubleSize)); 1146 __ subq(rsp, Immediate(kDoubleSize));
1272 __ cvtlsi2sd(xmm1, rax); 1147 __ cvtlsi2sd(xmm1, rax);
1273 __ movsd(Operand(rsp, 0), xmm1); 1148 __ movsd(Operand(rsp, 0), xmm1);
1274 __ movq(rbx, xmm1); 1149 __ movq(rbx, xmm1);
1275 __ movq(rdx, xmm1); 1150 __ movq(rdx, xmm1);
1276 __ fld_d(Operand(rsp, 0)); 1151 __ fld_d(Operand(rsp, 0));
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
1541 ASSERT(type == TranscendentalCache::LOG); 1416 ASSERT(type == TranscendentalCache::LOG);
1542 __ fldln2(); 1417 __ fldln2();
1543 __ fxch(); 1418 __ fxch();
1544 __ fyl2x(); 1419 __ fyl2x();
1545 } 1420 }
1546 } 1421 }
1547 1422
1548 1423
1549 // Input: rdx, rax are the left and right objects of a bit op. 1424 // Input: rdx, rax are the left and right objects of a bit op.
1550 // Output: rax, rcx are left and right integers for a bit op. 1425 // Output: rax, rcx are left and right integers for a bit op.
1551 void FloatingPointHelper::LoadNumbersAsIntegers(MacroAssembler* masm) {
1552 // Check float operands.
1553 Label done;
1554 Label rax_is_smi;
1555 Label rax_is_object;
1556 Label rdx_is_object;
1557
1558 __ JumpIfNotSmi(rdx, &rdx_is_object);
1559 __ SmiToInteger32(rdx, rdx);
1560 __ JumpIfSmi(rax, &rax_is_smi);
1561
1562 __ bind(&rax_is_object);
1563 DoubleToIStub stub1(rax, rcx, HeapNumber::kValueOffset - kHeapObjectTag,
1564 true);
1565 __ call(stub1.GetCode(masm->isolate()), RelocInfo::CODE_TARGET);
1566
1567 __ jmp(&done);
1568
1569 __ bind(&rdx_is_object);
1570 DoubleToIStub stub2(rdx, rdx, HeapNumber::kValueOffset - kHeapObjectTag,
1571 true);
1572 __ call(stub1.GetCode(masm->isolate()), RelocInfo::CODE_TARGET);
1573 __ JumpIfNotSmi(rax, &rax_is_object);
1574
1575 __ bind(&rax_is_smi);
1576 __ SmiToInteger32(rcx, rax);
1577
1578 __ bind(&done);
1579 __ movl(rax, rdx);
1580 }
1581
1582
1583 // Input: rdx, rax are the left and right objects of a bit op.
1584 // Output: rax, rcx are left and right integers for a bit op.
1585 // Jump to conversion_failure: rdx and rax are unchanged. 1426 // Jump to conversion_failure: rdx and rax are unchanged.
1586 void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm, 1427 void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
1587 Label* conversion_failure, 1428 Label* conversion_failure,
1588 Register heap_number_map) { 1429 Register heap_number_map) {
1589 // Check float operands. 1430 // Check float operands.
1590 Label arg1_is_object, check_undefined_arg1; 1431 Label arg1_is_object, check_undefined_arg1;
1591 Label arg2_is_object, check_undefined_arg2; 1432 Label arg2_is_object, check_undefined_arg2;
1592 Label load_arg2, done; 1433 Label load_arg2, done;
1593 1434
1594 __ JumpIfNotSmi(rdx, &arg1_is_object); 1435 __ JumpIfNotSmi(rdx, &arg1_is_object);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1638 1479
1639 1480
1640 void FloatingPointHelper::LoadSSE2SmiOperands(MacroAssembler* masm) { 1481 void FloatingPointHelper::LoadSSE2SmiOperands(MacroAssembler* masm) {
1641 __ SmiToInteger32(kScratchRegister, rdx); 1482 __ SmiToInteger32(kScratchRegister, rdx);
1642 __ cvtlsi2sd(xmm0, kScratchRegister); 1483 __ cvtlsi2sd(xmm0, kScratchRegister);
1643 __ SmiToInteger32(kScratchRegister, rax); 1484 __ SmiToInteger32(kScratchRegister, rax);
1644 __ cvtlsi2sd(xmm1, kScratchRegister); 1485 __ cvtlsi2sd(xmm1, kScratchRegister);
1645 } 1486 }
1646 1487
1647 1488
1648 void FloatingPointHelper::LoadSSE2NumberOperands(MacroAssembler* masm) {
1649 Label load_smi_rdx, load_nonsmi_rax, load_smi_rax, done;
1650 // Load operand in rdx into xmm0.
1651 __ JumpIfSmi(rdx, &load_smi_rdx);
1652 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
1653 // Load operand in rax into xmm1.
1654 __ JumpIfSmi(rax, &load_smi_rax);
1655 __ bind(&load_nonsmi_rax);
1656 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
1657 __ jmp(&done);
1658
1659 __ bind(&load_smi_rdx);
1660 __ SmiToInteger32(kScratchRegister, rdx);
1661 __ cvtlsi2sd(xmm0, kScratchRegister);
1662 __ JumpIfNotSmi(rax, &load_nonsmi_rax);
1663
1664 __ bind(&load_smi_rax);
1665 __ SmiToInteger32(kScratchRegister, rax);
1666 __ cvtlsi2sd(xmm1, kScratchRegister);
1667
1668 __ bind(&done);
1669 }
1670
1671
1672 void FloatingPointHelper::LoadSSE2UnknownOperands(MacroAssembler* masm, 1489 void FloatingPointHelper::LoadSSE2UnknownOperands(MacroAssembler* masm,
1673 Label* not_numbers) { 1490 Label* not_numbers) {
1674 Label load_smi_rdx, load_nonsmi_rax, load_smi_rax, load_float_rax, done; 1491 Label load_smi_rdx, load_nonsmi_rax, load_smi_rax, load_float_rax, done;
1675 // Load operand in rdx into xmm0, or branch to not_numbers. 1492 // Load operand in rdx into xmm0, or branch to not_numbers.
1676 __ LoadRoot(rcx, Heap::kHeapNumberMapRootIndex); 1493 __ LoadRoot(rcx, Heap::kHeapNumberMapRootIndex);
1677 __ JumpIfSmi(rdx, &load_smi_rdx); 1494 __ JumpIfSmi(rdx, &load_smi_rdx);
1678 __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), rcx); 1495 __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), rcx);
1679 __ j(not_equal, not_numbers); // Argument in rdx is not a number. 1496 __ j(not_equal, not_numbers); // Argument in rdx is not a number.
1680 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); 1497 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
1681 // Load operand in rax into xmm1, or branch to not_numbers. 1498 // Load operand in rax into xmm1, or branch to not_numbers.
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1789 1606
1790 // Save 1 in double_result - we need this several times later on. 1607 // Save 1 in double_result - we need this several times later on.
1791 __ movq(scratch, Immediate(1)); 1608 __ movq(scratch, Immediate(1));
1792 __ cvtlsi2sd(double_result, scratch); 1609 __ cvtlsi2sd(double_result, scratch);
1793 1610
1794 if (exponent_type_ == ON_STACK) { 1611 if (exponent_type_ == ON_STACK) {
1795 Label base_is_smi, unpack_exponent; 1612 Label base_is_smi, unpack_exponent;
1796 // The exponent and base are supplied as arguments on the stack. 1613 // The exponent and base are supplied as arguments on the stack.
1797 // This can only happen if the stub is called from non-optimized code. 1614 // This can only happen if the stub is called from non-optimized code.
1798 // Load input parameters from stack. 1615 // Load input parameters from stack.
1799 __ movq(base, Operand(rsp, 2 * kPointerSize)); 1616 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER);
1800 __ movq(exponent, Operand(rsp, 1 * kPointerSize)); 1617 __ movq(base, args.GetArgumentOperand(0));
1618 __ movq(exponent, args.GetArgumentOperand(1));
1801 __ JumpIfSmi(base, &base_is_smi, Label::kNear); 1619 __ JumpIfSmi(base, &base_is_smi, Label::kNear);
1802 __ CompareRoot(FieldOperand(base, HeapObject::kMapOffset), 1620 __ CompareRoot(FieldOperand(base, HeapObject::kMapOffset),
1803 Heap::kHeapNumberMapRootIndex); 1621 Heap::kHeapNumberMapRootIndex);
1804 __ j(not_equal, &call_runtime); 1622 __ j(not_equal, &call_runtime);
1805 1623
1806 __ movsd(double_base, FieldOperand(base, HeapNumber::kValueOffset)); 1624 __ movsd(double_base, FieldOperand(base, HeapNumber::kValueOffset));
1807 __ jmp(&unpack_exponent, Label::kNear); 1625 __ jmp(&unpack_exponent, Label::kNear);
1808 1626
1809 __ bind(&base_is_smi); 1627 __ bind(&base_is_smi);
1810 __ SmiToInteger32(base, base); 1628 __ SmiToInteger32(base, base);
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after
2223 // rsp[0] : return address 2041 // rsp[0] : return address
2224 // rsp[8] : number of parameters (tagged) 2042 // rsp[8] : number of parameters (tagged)
2225 // rsp[16] : receiver displacement 2043 // rsp[16] : receiver displacement
2226 // rsp[24] : function 2044 // rsp[24] : function
2227 // Registers used over the whole function: 2045 // Registers used over the whole function:
2228 // rbx: the mapped parameter count (untagged) 2046 // rbx: the mapped parameter count (untagged)
2229 // rax: the allocated object (tagged). 2047 // rax: the allocated object (tagged).
2230 2048
2231 Factory* factory = masm->isolate()->factory(); 2049 Factory* factory = masm->isolate()->factory();
2232 2050
2233 __ SmiToInteger64(rbx, Operand(rsp, 1 * kPointerSize)); 2051 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER);
2052 __ SmiToInteger64(rbx, args.GetArgumentOperand(2));
2234 // rbx = parameter count (untagged) 2053 // rbx = parameter count (untagged)
2235 2054
2236 // Check if the calling frame is an arguments adaptor frame. 2055 // Check if the calling frame is an arguments adaptor frame.
2237 Label runtime; 2056 Label runtime;
2238 Label adaptor_frame, try_allocate; 2057 Label adaptor_frame, try_allocate;
2239 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2058 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2240 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); 2059 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
2241 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2060 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2242 __ j(equal, &adaptor_frame); 2061 __ j(equal, &adaptor_frame);
2243 2062
2244 // No adaptor, parameter count = argument count. 2063 // No adaptor, parameter count = argument count.
2245 __ movq(rcx, rbx); 2064 __ movq(rcx, rbx);
2246 __ jmp(&try_allocate, Label::kNear); 2065 __ jmp(&try_allocate, Label::kNear);
2247 2066
2248 // We have an adaptor frame. Patch the parameters pointer. 2067 // We have an adaptor frame. Patch the parameters pointer.
2249 __ bind(&adaptor_frame); 2068 __ bind(&adaptor_frame);
2250 __ SmiToInteger64(rcx, 2069 __ SmiToInteger64(rcx,
2251 Operand(rdx, 2070 Operand(rdx,
2252 ArgumentsAdaptorFrameConstants::kLengthOffset)); 2071 ArgumentsAdaptorFrameConstants::kLengthOffset));
2253 __ lea(rdx, Operand(rdx, rcx, times_pointer_size, 2072 __ lea(rdx, Operand(rdx, rcx, times_pointer_size,
2254 StandardFrameConstants::kCallerSPOffset)); 2073 StandardFrameConstants::kCallerSPOffset));
2255 __ movq(Operand(rsp, 2 * kPointerSize), rdx); 2074 __ movq(args.GetArgumentOperand(1), rdx);
2256 2075
2257 // rbx = parameter count (untagged) 2076 // rbx = parameter count (untagged)
2258 // rcx = argument count (untagged) 2077 // rcx = argument count (untagged)
2259 // Compute the mapped parameter count = min(rbx, rcx) in rbx. 2078 // Compute the mapped parameter count = min(rbx, rcx) in rbx.
2260 __ cmpq(rbx, rcx); 2079 __ cmpq(rbx, rcx);
2261 __ j(less_equal, &try_allocate, Label::kNear); 2080 __ j(less_equal, &try_allocate, Label::kNear);
2262 __ movq(rbx, rcx); 2081 __ movq(rbx, rcx);
2263 2082
2264 __ bind(&try_allocate); 2083 __ bind(&try_allocate);
2265 2084
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2306 // rcx = argument count (untagged) 2125 // rcx = argument count (untagged)
2307 // rdi = address of boilerplate object (tagged) 2126 // rdi = address of boilerplate object (tagged)
2308 // Copy the JS object part. 2127 // Copy the JS object part.
2309 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { 2128 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
2310 __ movq(rdx, FieldOperand(rdi, i)); 2129 __ movq(rdx, FieldOperand(rdi, i));
2311 __ movq(FieldOperand(rax, i), rdx); 2130 __ movq(FieldOperand(rax, i), rdx);
2312 } 2131 }
2313 2132
2314 // Set up the callee in-object property. 2133 // Set up the callee in-object property.
2315 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); 2134 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
2316 __ movq(rdx, Operand(rsp, 3 * kPointerSize)); 2135 __ movq(rdx, args.GetArgumentOperand(0));
2317 __ movq(FieldOperand(rax, JSObject::kHeaderSize + 2136 __ movq(FieldOperand(rax, JSObject::kHeaderSize +
2318 Heap::kArgumentsCalleeIndex * kPointerSize), 2137 Heap::kArgumentsCalleeIndex * kPointerSize),
2319 rdx); 2138 rdx);
2320 2139
2321 // Use the length (smi tagged) and set that as an in-object property too. 2140 // Use the length (smi tagged) and set that as an in-object property too.
2322 // Note: rcx is tagged from here on. 2141 // Note: rcx is tagged from here on.
2323 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); 2142 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
2324 __ Integer32ToSmi(rcx, rcx); 2143 __ Integer32ToSmi(rcx, rcx);
2325 __ movq(FieldOperand(rax, JSObject::kHeaderSize + 2144 __ movq(FieldOperand(rax, JSObject::kHeaderSize +
2326 Heap::kArgumentsLengthIndex * kPointerSize), 2145 Heap::kArgumentsLengthIndex * kPointerSize),
(...skipping 30 matching lines...) Expand all
2357 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 2176 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1
2358 // The mapped parameter thus need to get indices 2177 // The mapped parameter thus need to get indices
2359 // MIN_CONTEXT_SLOTS+parameter_count-1 .. 2178 // MIN_CONTEXT_SLOTS+parameter_count-1 ..
2360 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count 2179 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count
2361 // We loop from right to left. 2180 // We loop from right to left.
2362 Label parameters_loop, parameters_test; 2181 Label parameters_loop, parameters_test;
2363 2182
2364 // Load tagged parameter count into r9. 2183 // Load tagged parameter count into r9.
2365 __ Integer32ToSmi(r9, rbx); 2184 __ Integer32ToSmi(r9, rbx);
2366 __ Move(r8, Smi::FromInt(Context::MIN_CONTEXT_SLOTS)); 2185 __ Move(r8, Smi::FromInt(Context::MIN_CONTEXT_SLOTS));
2367 __ addq(r8, Operand(rsp, 1 * kPointerSize)); 2186 __ addq(r8, args.GetArgumentOperand(2));
2368 __ subq(r8, r9); 2187 __ subq(r8, r9);
2369 __ Move(r11, factory->the_hole_value()); 2188 __ Move(r11, factory->the_hole_value());
2370 __ movq(rdx, rdi); 2189 __ movq(rdx, rdi);
2371 __ lea(rdi, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize)); 2190 __ lea(rdi, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize));
2372 // r9 = loop variable (tagged) 2191 // r9 = loop variable (tagged)
2373 // r8 = mapping index (tagged) 2192 // r8 = mapping index (tagged)
2374 // r11 = the hole value 2193 // r11 = the hole value
2375 // rdx = address of parameter map (tagged) 2194 // rdx = address of parameter map (tagged)
2376 // rdi = address of backing store (tagged) 2195 // rdi = address of backing store (tagged)
2377 __ jmp(&parameters_test, Label::kNear); 2196 __ jmp(&parameters_test, Label::kNear);
(...skipping 18 matching lines...) Expand all
2396 2215
2397 // rcx = argument count (tagged) 2216 // rcx = argument count (tagged)
2398 // rdi = address of backing store (tagged) 2217 // rdi = address of backing store (tagged)
2399 // Copy arguments header and remaining slots (if there are any). 2218 // Copy arguments header and remaining slots (if there are any).
2400 __ Move(FieldOperand(rdi, FixedArray::kMapOffset), 2219 __ Move(FieldOperand(rdi, FixedArray::kMapOffset),
2401 factory->fixed_array_map()); 2220 factory->fixed_array_map());
2402 __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); 2221 __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rcx);
2403 2222
2404 Label arguments_loop, arguments_test; 2223 Label arguments_loop, arguments_test;
2405 __ movq(r8, rbx); 2224 __ movq(r8, rbx);
2406 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); 2225 __ movq(rdx, args.GetArgumentOperand(1));
2407 // Untag rcx for the loop below. 2226 // Untag rcx for the loop below.
2408 __ SmiToInteger64(rcx, rcx); 2227 __ SmiToInteger64(rcx, rcx);
2409 __ lea(kScratchRegister, Operand(r8, times_pointer_size, 0)); 2228 __ lea(kScratchRegister, Operand(r8, times_pointer_size, 0));
2410 __ subq(rdx, kScratchRegister); 2229 __ subq(rdx, kScratchRegister);
2411 __ jmp(&arguments_test, Label::kNear); 2230 __ jmp(&arguments_test, Label::kNear);
2412 2231
2413 __ bind(&arguments_loop); 2232 __ bind(&arguments_loop);
2414 __ subq(rdx, Immediate(kPointerSize)); 2233 __ subq(rdx, Immediate(kPointerSize));
2415 __ movq(r9, Operand(rdx, 0)); 2234 __ movq(r9, Operand(rdx, 0));
2416 __ movq(FieldOperand(rdi, r8, 2235 __ movq(FieldOperand(rdi, r8,
2417 times_pointer_size, 2236 times_pointer_size,
2418 FixedArray::kHeaderSize), 2237 FixedArray::kHeaderSize),
2419 r9); 2238 r9);
2420 __ addq(r8, Immediate(1)); 2239 __ addq(r8, Immediate(1));
2421 2240
2422 __ bind(&arguments_test); 2241 __ bind(&arguments_test);
2423 __ cmpq(r8, rcx); 2242 __ cmpq(r8, rcx);
2424 __ j(less, &arguments_loop, Label::kNear); 2243 __ j(less, &arguments_loop, Label::kNear);
2425 2244
2426 // Return and remove the on-stack parameters. 2245 // Return and remove the on-stack parameters.
2427 __ ret(3 * kPointerSize); 2246 __ ret(3 * kPointerSize);
2428 2247
2429 // Do the runtime call to allocate the arguments object. 2248 // Do the runtime call to allocate the arguments object.
2430 // rcx = argument count (untagged) 2249 // rcx = argument count (untagged)
2431 __ bind(&runtime); 2250 __ bind(&runtime);
2432 __ Integer32ToSmi(rcx, rcx); 2251 __ Integer32ToSmi(rcx, rcx);
2433 __ movq(Operand(rsp, 1 * kPointerSize), rcx); // Patch argument count. 2252 __ movq(args.GetArgumentOperand(2), rcx); // Patch argument count.
2434 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); 2253 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
2435 } 2254 }
2436 2255
2437 2256
2438 void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) { 2257 void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) {
2439 // rsp[0] : return address 2258 // rsp[0] : return address
2440 // rsp[8] : number of parameters 2259 // rsp[8] : number of parameters
2441 // rsp[16] : receiver displacement 2260 // rsp[16] : receiver displacement
2442 // rsp[24] : function 2261 // rsp[24] : function
2443 2262
2444 // Check if the calling frame is an arguments adaptor frame. 2263 // Check if the calling frame is an arguments adaptor frame.
2445 Label runtime; 2264 Label runtime;
2446 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2265 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2447 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); 2266 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
2448 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2267 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2449 __ j(not_equal, &runtime); 2268 __ j(not_equal, &runtime);
2450 2269
2451 // Patch the arguments.length and the parameters pointer. 2270 // Patch the arguments.length and the parameters pointer.
2271 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER);
2452 __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2272 __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2453 __ movq(Operand(rsp, 1 * kPointerSize), rcx); 2273 __ movq(args.GetArgumentOperand(2), rcx);
2454 __ SmiToInteger64(rcx, rcx); 2274 __ SmiToInteger64(rcx, rcx);
2455 __ lea(rdx, Operand(rdx, rcx, times_pointer_size, 2275 __ lea(rdx, Operand(rdx, rcx, times_pointer_size,
2456 StandardFrameConstants::kCallerSPOffset)); 2276 StandardFrameConstants::kCallerSPOffset));
2457 __ movq(Operand(rsp, 2 * kPointerSize), rdx); 2277 __ movq(args.GetArgumentOperand(1), rdx);
2458 2278
2459 __ bind(&runtime); 2279 __ bind(&runtime);
2460 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); 2280 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
2461 } 2281 }
2462 2282
2463 2283
2464 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { 2284 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
2465 // rsp[0] : return address 2285 // rsp[0] : return address
2466 // rsp[8] : number of parameters 2286 // rsp[8] : number of parameters
2467 // rsp[16] : receiver displacement 2287 // rsp[16] : receiver displacement
2468 // rsp[24] : function 2288 // rsp[24] : function
2469 2289
2470 // Check if the calling frame is an arguments adaptor frame. 2290 // Check if the calling frame is an arguments adaptor frame.
2471 Label adaptor_frame, try_allocate, runtime; 2291 Label adaptor_frame, try_allocate, runtime;
2472 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2292 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2473 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); 2293 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
2474 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2294 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2475 __ j(equal, &adaptor_frame); 2295 __ j(equal, &adaptor_frame);
2476 2296
2477 // Get the length from the frame. 2297 // Get the length from the frame.
2478 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); 2298 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER);
2299 __ movq(rcx, args.GetArgumentOperand(2));
2479 __ SmiToInteger64(rcx, rcx); 2300 __ SmiToInteger64(rcx, rcx);
2480 __ jmp(&try_allocate); 2301 __ jmp(&try_allocate);
2481 2302
2482 // Patch the arguments.length and the parameters pointer. 2303 // Patch the arguments.length and the parameters pointer.
2483 __ bind(&adaptor_frame); 2304 __ bind(&adaptor_frame);
2484 __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2305 __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2485 __ movq(Operand(rsp, 1 * kPointerSize), rcx); 2306 __ movq(args.GetArgumentOperand(2), rcx);
2486 __ SmiToInteger64(rcx, rcx); 2307 __ SmiToInteger64(rcx, rcx);
2487 __ lea(rdx, Operand(rdx, rcx, times_pointer_size, 2308 __ lea(rdx, Operand(rdx, rcx, times_pointer_size,
2488 StandardFrameConstants::kCallerSPOffset)); 2309 StandardFrameConstants::kCallerSPOffset));
2489 __ movq(Operand(rsp, 2 * kPointerSize), rdx); 2310 __ movq(args.GetArgumentOperand(1), rdx);
2490 2311
2491 // Try the new space allocation. Start out with computing the size of 2312 // Try the new space allocation. Start out with computing the size of
2492 // the arguments object and the elements array. 2313 // the arguments object and the elements array.
2493 Label add_arguments_object; 2314 Label add_arguments_object;
2494 __ bind(&try_allocate); 2315 __ bind(&try_allocate);
2495 __ testq(rcx, rcx); 2316 __ testq(rcx, rcx);
2496 __ j(zero, &add_arguments_object, Label::kNear); 2317 __ j(zero, &add_arguments_object, Label::kNear);
2497 __ lea(rcx, Operand(rcx, times_pointer_size, FixedArray::kHeaderSize)); 2318 __ lea(rcx, Operand(rcx, times_pointer_size, FixedArray::kHeaderSize));
2498 __ bind(&add_arguments_object); 2319 __ bind(&add_arguments_object);
2499 __ addq(rcx, Immediate(Heap::kArgumentsObjectSizeStrict)); 2320 __ addq(rcx, Immediate(Heap::kArgumentsObjectSizeStrict));
2500 2321
2501 // Do the allocation of both objects in one go. 2322 // Do the allocation of both objects in one go.
2502 __ Allocate(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT); 2323 __ Allocate(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT);
2503 2324
2504 // Get the arguments boilerplate from the current native context. 2325 // Get the arguments boilerplate from the current native context.
2505 __ movq(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 2326 __ movq(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
2506 __ movq(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset)); 2327 __ movq(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset));
2507 const int offset = 2328 const int offset =
2508 Context::SlotOffset(Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX); 2329 Context::SlotOffset(Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX);
2509 __ movq(rdi, Operand(rdi, offset)); 2330 __ movq(rdi, Operand(rdi, offset));
2510 2331
2511 // Copy the JS object part. 2332 // Copy the JS object part.
2512 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { 2333 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
2513 __ movq(rbx, FieldOperand(rdi, i)); 2334 __ movq(rbx, FieldOperand(rdi, i));
2514 __ movq(FieldOperand(rax, i), rbx); 2335 __ movq(FieldOperand(rax, i), rbx);
2515 } 2336 }
2516 2337
2517 // Get the length (smi tagged) and set that as an in-object property too. 2338 // Get the length (smi tagged) and set that as an in-object property too.
2518 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); 2339 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
2519 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); 2340 __ movq(rcx, args.GetArgumentOperand(2));
2520 __ movq(FieldOperand(rax, JSObject::kHeaderSize + 2341 __ movq(FieldOperand(rax, JSObject::kHeaderSize +
2521 Heap::kArgumentsLengthIndex * kPointerSize), 2342 Heap::kArgumentsLengthIndex * kPointerSize),
2522 rcx); 2343 rcx);
2523 2344
2524 // If there are no actual arguments, we're done. 2345 // If there are no actual arguments, we're done.
2525 Label done; 2346 Label done;
2526 __ testq(rcx, rcx); 2347 __ testq(rcx, rcx);
2527 __ j(zero, &done); 2348 __ j(zero, &done);
2528 2349
2529 // Get the parameters pointer from the stack. 2350 // Get the parameters pointer from the stack.
2530 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); 2351 __ movq(rdx, args.GetArgumentOperand(1));
2531 2352
2532 // Set up the elements pointer in the allocated arguments object and 2353 // Set up the elements pointer in the allocated arguments object and
2533 // initialize the header in the elements fixed array. 2354 // initialize the header in the elements fixed array.
2534 __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSizeStrict)); 2355 __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSizeStrict));
2535 __ movq(FieldOperand(rax, JSObject::kElementsOffset), rdi); 2356 __ movq(FieldOperand(rax, JSObject::kElementsOffset), rdi);
2536 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex); 2357 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex);
2537 __ movq(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); 2358 __ movq(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister);
2538 2359
2539 2360
2540 __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); 2361 __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rcx);
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after
3003 __ movq(rdi, FieldOperand(rdi, SlicedString::kParentOffset)); 2824 __ movq(rdi, FieldOperand(rdi, SlicedString::kParentOffset));
3004 __ jmp(&check_underlying); 2825 __ jmp(&check_underlying);
3005 #endif // V8_INTERPRETED_REGEXP 2826 #endif // V8_INTERPRETED_REGEXP
3006 } 2827 }
3007 2828
3008 2829
3009 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { 2830 void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
3010 const int kMaxInlineLength = 100; 2831 const int kMaxInlineLength = 100;
3011 Label slowcase; 2832 Label slowcase;
3012 Label done; 2833 Label done;
3013 __ movq(r8, Operand(rsp, kPointerSize * 3)); 2834 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER);
2835 __ movq(r8, args.GetArgumentOperand(0));
3014 __ JumpIfNotSmi(r8, &slowcase); 2836 __ JumpIfNotSmi(r8, &slowcase);
3015 __ SmiToInteger32(rbx, r8); 2837 __ SmiToInteger32(rbx, r8);
3016 __ cmpl(rbx, Immediate(kMaxInlineLength)); 2838 __ cmpl(rbx, Immediate(kMaxInlineLength));
3017 __ j(above, &slowcase); 2839 __ j(above, &slowcase);
3018 // Smi-tagging is equivalent to multiplying by 2. 2840 // Smi-tagging is equivalent to multiplying by 2.
3019 STATIC_ASSERT(kSmiTag == 0); 2841 STATIC_ASSERT(kSmiTag == 0);
3020 STATIC_ASSERT(kSmiTagSize == 1); 2842 STATIC_ASSERT(kSmiTagSize == 1);
3021 // Allocate RegExpResult followed by FixedArray with size in rbx. 2843 // Allocate RegExpResult followed by FixedArray with size in rbx.
3022 // JSArray: [Map][empty properties][Elements][Length-smi][index][input] 2844 // JSArray: [Map][empty properties][Elements][Length-smi][index][input]
3023 // Elements: [Map][Length][..elements..] 2845 // Elements: [Map][Length][..elements..]
(...skipping 17 matching lines...) Expand all
3041 2863
3042 // Set empty properties FixedArray. 2864 // Set empty properties FixedArray.
3043 __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex); 2865 __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex);
3044 __ movq(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister); 2866 __ movq(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister);
3045 2867
3046 // Set elements to point to FixedArray allocated right after the JSArray. 2868 // Set elements to point to FixedArray allocated right after the JSArray.
3047 __ lea(rcx, Operand(rax, JSRegExpResult::kSize)); 2869 __ lea(rcx, Operand(rax, JSRegExpResult::kSize));
3048 __ movq(FieldOperand(rax, JSObject::kElementsOffset), rcx); 2870 __ movq(FieldOperand(rax, JSObject::kElementsOffset), rcx);
3049 2871
3050 // Set input, index and length fields from arguments. 2872 // Set input, index and length fields from arguments.
3051 __ movq(r8, Operand(rsp, kPointerSize * 1)); 2873 __ movq(r8, args.GetArgumentOperand(2));
3052 __ movq(FieldOperand(rax, JSRegExpResult::kInputOffset), r8); 2874 __ movq(FieldOperand(rax, JSRegExpResult::kInputOffset), r8);
3053 __ movq(r8, Operand(rsp, kPointerSize * 2)); 2875 __ movq(r8, args.GetArgumentOperand(1));
3054 __ movq(FieldOperand(rax, JSRegExpResult::kIndexOffset), r8); 2876 __ movq(FieldOperand(rax, JSRegExpResult::kIndexOffset), r8);
3055 __ movq(r8, Operand(rsp, kPointerSize * 3)); 2877 __ movq(r8, args.GetArgumentOperand(0));
3056 __ movq(FieldOperand(rax, JSArray::kLengthOffset), r8); 2878 __ movq(FieldOperand(rax, JSArray::kLengthOffset), r8);
3057 2879
3058 // Fill out the elements FixedArray. 2880 // Fill out the elements FixedArray.
3059 // rax: JSArray. 2881 // rax: JSArray.
3060 // rcx: FixedArray. 2882 // rcx: FixedArray.
3061 // rbx: Number of elements in array as int32. 2883 // rbx: Number of elements in array as int32.
3062 2884
3063 // Set map. 2885 // Set map.
3064 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex); 2886 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex);
3065 __ movq(FieldOperand(rcx, HeapObject::kMapOffset), kScratchRegister); 2887 __ movq(FieldOperand(rcx, HeapObject::kMapOffset), kScratchRegister);
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
3176 // but times_twice_pointer_size (multiplication by 16) scale factor 2998 // but times_twice_pointer_size (multiplication by 16) scale factor
3177 // is not supported by addrmode on x64 platform. 2999 // is not supported by addrmode on x64 platform.
3178 // So we have to premultiply entry index before lookup. 3000 // So we have to premultiply entry index before lookup.
3179 __ shl(hash, Immediate(kPointerSizeLog2 + 1)); 3001 __ shl(hash, Immediate(kPointerSizeLog2 + 1));
3180 } 3002 }
3181 3003
3182 3004
3183 void NumberToStringStub::Generate(MacroAssembler* masm) { 3005 void NumberToStringStub::Generate(MacroAssembler* masm) {
3184 Label runtime; 3006 Label runtime;
3185 3007
3186 __ movq(rbx, Operand(rsp, kPointerSize)); 3008 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER);
3009 __ movq(rbx, args.GetArgumentOperand(0));
3187 3010
3188 // Generate code to lookup number in the number string cache. 3011 // Generate code to lookup number in the number string cache.
3189 GenerateLookupNumberStringCache(masm, rbx, rax, r8, r9, &runtime); 3012 GenerateLookupNumberStringCache(masm, rbx, rax, r8, r9, &runtime);
3190 __ ret(1 * kPointerSize); 3013 __ ret(1 * kPointerSize);
3191 3014
3192 __ bind(&runtime); 3015 __ bind(&runtime);
3193 // Handle number to string in the runtime system if not found in the cache. 3016 // Handle number to string in the runtime system if not found in the cache.
3194 __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1); 3017 __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1);
3195 } 3018 }
3196 3019
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
3587 3410
3588 __ bind(&done); 3411 __ bind(&done);
3589 } 3412 }
3590 3413
3591 3414
3592 void CallFunctionStub::Generate(MacroAssembler* masm) { 3415 void CallFunctionStub::Generate(MacroAssembler* masm) {
3593 // rbx : cache cell for call target 3416 // rbx : cache cell for call target
3594 // rdi : the function to call 3417 // rdi : the function to call
3595 Isolate* isolate = masm->isolate(); 3418 Isolate* isolate = masm->isolate();
3596 Label slow, non_function; 3419 Label slow, non_function;
3420 StackArgumentsAccessor args(rsp, argc_);
3597 3421
3598 // The receiver might implicitly be the global object. This is 3422 // The receiver might implicitly be the global object. This is
3599 // indicated by passing the hole as the receiver to the call 3423 // indicated by passing the hole as the receiver to the call
3600 // function stub. 3424 // function stub.
3601 if (ReceiverMightBeImplicit()) { 3425 if (ReceiverMightBeImplicit()) {
3602 Label call; 3426 Label call;
3603 // Get the receiver from the stack. 3427 // Get the receiver from the stack.
3604 // +1 ~ return address 3428 __ movq(rax, args.GetReceiverOperand());
3605 __ movq(rax, Operand(rsp, (argc_ + 1) * kPointerSize));
3606 // Call as function is indicated with the hole. 3429 // Call as function is indicated with the hole.
3607 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 3430 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
3608 __ j(not_equal, &call, Label::kNear); 3431 __ j(not_equal, &call, Label::kNear);
3609 // Patch the receiver on the stack with the global receiver object. 3432 // Patch the receiver on the stack with the global receiver object.
3610 __ movq(rcx, GlobalObjectOperand()); 3433 __ movq(rcx, GlobalObjectOperand());
3611 __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); 3434 __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
3612 __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rcx); 3435 __ movq(args.GetReceiverOperand(), rcx);
3613 __ bind(&call); 3436 __ bind(&call);
3614 } 3437 }
3615 3438
3616 // Check that the function really is a JavaScript function. 3439 // Check that the function really is a JavaScript function.
3617 __ JumpIfSmi(rdi, &non_function); 3440 __ JumpIfSmi(rdi, &non_function);
3618 // Goto slow case if we do not have a function. 3441 // Goto slow case if we do not have a function.
3619 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); 3442 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
3620 __ j(not_equal, &slow); 3443 __ j(not_equal, &slow);
3621 3444
3622 if (RecordCallTarget()) { 3445 if (RecordCallTarget()) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
3664 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); 3487 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY);
3665 { 3488 {
3666 Handle<Code> adaptor = 3489 Handle<Code> adaptor =
3667 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); 3490 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();
3668 __ jmp(adaptor, RelocInfo::CODE_TARGET); 3491 __ jmp(adaptor, RelocInfo::CODE_TARGET);
3669 } 3492 }
3670 3493
3671 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead 3494 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead
3672 // of the original receiver from the call site). 3495 // of the original receiver from the call site).
3673 __ bind(&non_function); 3496 __ bind(&non_function);
3674 __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rdi); 3497 __ movq(args.GetReceiverOperand(), rdi);
3675 __ Set(rax, argc_); 3498 __ Set(rax, argc_);
3676 __ Set(rbx, 0); 3499 __ Set(rbx, 0);
3677 __ SetCallKind(rcx, CALL_AS_METHOD); 3500 __ SetCallKind(rcx, CALL_AS_METHOD);
3678 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); 3501 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
3679 Handle<Code> adaptor = 3502 Handle<Code> adaptor =
3680 Isolate::Current()->builtins()->ArgumentsAdaptorTrampoline(); 3503 Isolate::Current()->builtins()->ArgumentsAdaptorTrampoline();
3681 __ Jump(adaptor, RelocInfo::CODE_TARGET); 3504 __ Jump(adaptor, RelocInfo::CODE_TARGET);
3682 } 3505 }
3683 3506
3684 3507
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after
4199 // Move(kScratchRegister, Factory::the_hole_value()) 4022 // Move(kScratchRegister, Factory::the_hole_value())
4200 // in front of the hole value address. 4023 // in front of the hole value address.
4201 static const unsigned int kWordBeforeMapCheckValue = 0xBA49FF78; 4024 static const unsigned int kWordBeforeMapCheckValue = 0xBA49FF78;
4202 // The last 4 bytes of the instruction sequence 4025 // The last 4 bytes of the instruction sequence
4203 // __ j(not_equal, &cache_miss); 4026 // __ j(not_equal, &cache_miss);
4204 // __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); 4027 // __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex);
4205 // before the offset of the hole value in the root array. 4028 // before the offset of the hole value in the root array.
4206 static const unsigned int kWordBeforeResultValue = 0x458B4909; 4029 static const unsigned int kWordBeforeResultValue = 0x458B4909;
4207 // Only the inline check flag is supported on X64. 4030 // Only the inline check flag is supported on X64.
4208 ASSERT(flags_ == kNoFlags || HasCallSiteInlineCheck()); 4031 ASSERT(flags_ == kNoFlags || HasCallSiteInlineCheck());
4209 int extra_stack_space = HasCallSiteInlineCheck() ? kPointerSize : 0; 4032 int extra_argument_offset = HasCallSiteInlineCheck() ? 1 : 0;
4210 4033
4211 // Get the object - go slow case if it's a smi. 4034 // Get the object - go slow case if it's a smi.
4212 Label slow; 4035 Label slow;
4213 4036 StackArgumentsAccessor args(rsp, 2 + extra_argument_offset,
4214 __ movq(rax, Operand(rsp, 2 * kPointerSize + extra_stack_space)); 4037 ARGUMENTS_DONT_CONTAIN_RECEIVER);
4038 __ movq(rax, args.GetArgumentOperand(0));
4215 __ JumpIfSmi(rax, &slow); 4039 __ JumpIfSmi(rax, &slow);
4216 4040
4217 // Check that the left hand is a JS object. Leave its map in rax. 4041 // Check that the left hand is a JS object. Leave its map in rax.
4218 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rax); 4042 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rax);
4219 __ j(below, &slow); 4043 __ j(below, &slow);
4220 __ CmpInstanceType(rax, LAST_SPEC_OBJECT_TYPE); 4044 __ CmpInstanceType(rax, LAST_SPEC_OBJECT_TYPE);
4221 __ j(above, &slow); 4045 __ j(above, &slow);
4222 4046
4223 // Get the prototype of the function. 4047 // Get the prototype of the function.
4224 __ movq(rdx, Operand(rsp, 1 * kPointerSize + extra_stack_space)); 4048 __ movq(rdx, args.GetArgumentOperand(1));
4225 // rdx is function, rax is map. 4049 // rdx is function, rax is map.
4226 4050
4227 // If there is a call site cache don't look in the global cache, but do the 4051 // If there is a call site cache don't look in the global cache, but do the
4228 // real lookup and update the call site cache. 4052 // real lookup and update the call site cache.
4229 if (!HasCallSiteInlineCheck()) { 4053 if (!HasCallSiteInlineCheck()) {
4230 // Look up the function and the map in the instanceof cache. 4054 // Look up the function and the map in the instanceof cache.
4231 Label miss; 4055 Label miss;
4232 __ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex); 4056 __ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex);
4233 __ j(not_equal, &miss, Label::kNear); 4057 __ j(not_equal, &miss, Label::kNear);
4234 __ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex); 4058 __ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex);
(...skipping 14 matching lines...) Expand all
4249 4073
4250 // Register mapping: 4074 // Register mapping:
4251 // rax is object map. 4075 // rax is object map.
4252 // rdx is function. 4076 // rdx is function.
4253 // rbx is function prototype. 4077 // rbx is function prototype.
4254 if (!HasCallSiteInlineCheck()) { 4078 if (!HasCallSiteInlineCheck()) {
4255 __ StoreRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex); 4079 __ StoreRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex);
4256 __ StoreRoot(rax, Heap::kInstanceofCacheMapRootIndex); 4080 __ StoreRoot(rax, Heap::kInstanceofCacheMapRootIndex);
4257 } else { 4081 } else {
4258 // Get return address and delta to inlined map check. 4082 // Get return address and delta to inlined map check.
4259 __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize)); 4083 __ movq(kScratchRegister, StackOperandForReturnAddress(0));
4260 __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize)); 4084 __ subq(kScratchRegister, args.GetArgumentOperand(2));
4261 if (FLAG_debug_code) { 4085 if (FLAG_debug_code) {
4262 __ movl(rdi, Immediate(kWordBeforeMapCheckValue)); 4086 __ movl(rdi, Immediate(kWordBeforeMapCheckValue));
4263 __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), rdi); 4087 __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), rdi);
4264 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCheck); 4088 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCheck);
4265 } 4089 }
4266 __ movq(kScratchRegister, 4090 __ movq(kScratchRegister,
4267 Operand(kScratchRegister, kOffsetToMapCheckValue)); 4091 Operand(kScratchRegister, kOffsetToMapCheckValue));
4268 __ movq(Operand(kScratchRegister, 0), rax); 4092 __ movq(Operand(kScratchRegister, 0), rax);
4269 } 4093 }
4270 4094
(...skipping 19 matching lines...) Expand all
4290 // Store bitwise zero in the cache. This is a Smi in GC terms. 4114 // Store bitwise zero in the cache. This is a Smi in GC terms.
4291 STATIC_ASSERT(kSmiTag == 0); 4115 STATIC_ASSERT(kSmiTag == 0);
4292 __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); 4116 __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
4293 } else { 4117 } else {
4294 // Store offset of true in the root array at the inline check site. 4118 // Store offset of true in the root array at the inline check site.
4295 int true_offset = 0x100 + 4119 int true_offset = 0x100 +
4296 (Heap::kTrueValueRootIndex << kPointerSizeLog2) - kRootRegisterBias; 4120 (Heap::kTrueValueRootIndex << kPointerSizeLog2) - kRootRegisterBias;
4297 // Assert it is a 1-byte signed value. 4121 // Assert it is a 1-byte signed value.
4298 ASSERT(true_offset >= 0 && true_offset < 0x100); 4122 ASSERT(true_offset >= 0 && true_offset < 0x100);
4299 __ movl(rax, Immediate(true_offset)); 4123 __ movl(rax, Immediate(true_offset));
4300 __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize)); 4124 __ movq(kScratchRegister, StackOperandForReturnAddress(0));
4301 __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize)); 4125 __ subq(kScratchRegister, args.GetArgumentOperand(2));
4302 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); 4126 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax);
4303 if (FLAG_debug_code) { 4127 if (FLAG_debug_code) {
4304 __ movl(rax, Immediate(kWordBeforeResultValue)); 4128 __ movl(rax, Immediate(kWordBeforeResultValue));
4305 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); 4129 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax);
4306 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); 4130 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov);
4307 } 4131 }
4308 __ Set(rax, 0); 4132 __ Set(rax, 0);
4309 } 4133 }
4310 __ ret(2 * kPointerSize + extra_stack_space); 4134 __ ret((2 + extra_argument_offset) * kPointerSize);
4311 4135
4312 __ bind(&is_not_instance); 4136 __ bind(&is_not_instance);
4313 if (!HasCallSiteInlineCheck()) { 4137 if (!HasCallSiteInlineCheck()) {
4314 // We have to store a non-zero value in the cache. 4138 // We have to store a non-zero value in the cache.
4315 __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex); 4139 __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex);
4316 } else { 4140 } else {
4317 // Store offset of false in the root array at the inline check site. 4141 // Store offset of false in the root array at the inline check site.
4318 int false_offset = 0x100 + 4142 int false_offset = 0x100 +
4319 (Heap::kFalseValueRootIndex << kPointerSizeLog2) - kRootRegisterBias; 4143 (Heap::kFalseValueRootIndex << kPointerSizeLog2) - kRootRegisterBias;
4320 // Assert it is a 1-byte signed value. 4144 // Assert it is a 1-byte signed value.
4321 ASSERT(false_offset >= 0 && false_offset < 0x100); 4145 ASSERT(false_offset >= 0 && false_offset < 0x100);
4322 __ movl(rax, Immediate(false_offset)); 4146 __ movl(rax, Immediate(false_offset));
4323 __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize)); 4147 __ movq(kScratchRegister, StackOperandForReturnAddress(0));
4324 __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize)); 4148 __ subq(kScratchRegister, args.GetArgumentOperand(2));
4325 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); 4149 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax);
4326 if (FLAG_debug_code) { 4150 if (FLAG_debug_code) {
4327 __ movl(rax, Immediate(kWordBeforeResultValue)); 4151 __ movl(rax, Immediate(kWordBeforeResultValue));
4328 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); 4152 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax);
4329 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); 4153 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov);
4330 } 4154 }
4331 } 4155 }
4332 __ ret(2 * kPointerSize + extra_stack_space); 4156 __ ret((2 + extra_argument_offset) * kPointerSize);
4333 4157
4334 // Slow-case: Go through the JavaScript implementation. 4158 // Slow-case: Go through the JavaScript implementation.
4335 __ bind(&slow); 4159 __ bind(&slow);
4336 if (HasCallSiteInlineCheck()) { 4160 if (HasCallSiteInlineCheck()) {
4337 // Remove extra value from the stack. 4161 // Remove extra value from the stack.
4338 __ PopReturnAddressTo(rcx); 4162 __ PopReturnAddressTo(rcx);
4339 __ pop(rax); 4163 __ pop(rax);
4340 __ PushReturnAddressFrom(rcx); 4164 __ PushReturnAddressFrom(rcx);
4341 } 4165 }
4342 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 4166 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
4480 4304
4481 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); 4305 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
4482 } 4306 }
4483 4307
4484 4308
4485 void StringAddStub::Generate(MacroAssembler* masm) { 4309 void StringAddStub::Generate(MacroAssembler* masm) {
4486 Label call_runtime, call_builtin; 4310 Label call_runtime, call_builtin;
4487 Builtins::JavaScript builtin_id = Builtins::ADD; 4311 Builtins::JavaScript builtin_id = Builtins::ADD;
4488 4312
4489 // Load the two arguments. 4313 // Load the two arguments.
4490 __ movq(rax, Operand(rsp, 2 * kPointerSize)); // First argument (left). 4314 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER);
4491 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); // Second argument (right). 4315 __ movq(rax, args.GetArgumentOperand(0)); // First argument (left).
4316 __ movq(rdx, args.GetArgumentOperand(1)); // Second argument (right).
4492 4317
4493 // Make sure that both arguments are strings if not known in advance. 4318 // Make sure that both arguments are strings if not known in advance.
4494 // Otherwise, at least one of the arguments is definitely a string, 4319 // Otherwise, at least one of the arguments is definitely a string,
4495 // and we convert the one that is not known to be a string. 4320 // and we convert the one that is not known to be a string.
4496 if ((flags_ & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) { 4321 if ((flags_ & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) {
4497 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT); 4322 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT);
4498 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT); 4323 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT);
4499 __ JumpIfSmi(rax, &call_runtime); 4324 __ JumpIfSmi(rax, &call_runtime);
4500 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, r8); 4325 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, r8);
4501 __ j(above_equal, &call_runtime); 4326 __ j(above_equal, &call_runtime);
(...skipping 986 matching lines...) Expand 10 before | Expand all | Expand 10 after
5488 5313
5489 5314
5490 void StringCompareStub::Generate(MacroAssembler* masm) { 5315 void StringCompareStub::Generate(MacroAssembler* masm) {
5491 Label runtime; 5316 Label runtime;
5492 5317
5493 // Stack frame on entry. 5318 // Stack frame on entry.
5494 // rsp[0] : return address 5319 // rsp[0] : return address
5495 // rsp[8] : right string 5320 // rsp[8] : right string
5496 // rsp[16] : left string 5321 // rsp[16] : left string
5497 5322
5498 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // left 5323 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER);
5499 __ movq(rax, Operand(rsp, 1 * kPointerSize)); // right 5324 __ movq(rdx, args.GetArgumentOperand(0)); // left
5325 __ movq(rax, args.GetArgumentOperand(1)); // right
5500 5326
5501 // Check for identity. 5327 // Check for identity.
5502 Label not_same; 5328 Label not_same;
5503 __ cmpq(rdx, rax); 5329 __ cmpq(rdx, rax);
5504 __ j(not_equal, &not_same, Label::kNear); 5330 __ j(not_equal, &not_same, Label::kNear);
5505 __ Move(rax, Smi::FromInt(EQUAL)); 5331 __ Move(rax, Smi::FromInt(EQUAL));
5506 Counters* counters = masm->isolate()->counters(); 5332 Counters* counters = masm->isolate()->counters();
5507 __ IncrementCounter(counters->string_compare_native(), 1); 5333 __ IncrementCounter(counters->string_compare_native(), 1);
5508 __ ret(2 * kPointerSize); 5334 __ ret(2 * kPointerSize);
5509 5335
(...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after
6002 5828
6003 __ SmiToInteger32(scratch, FieldOperand(dictionary_, kCapacityOffset)); 5829 __ SmiToInteger32(scratch, FieldOperand(dictionary_, kCapacityOffset));
6004 __ decl(scratch); 5830 __ decl(scratch);
6005 __ push(scratch); 5831 __ push(scratch);
6006 5832
6007 // If names of slots in range from 1 to kProbes - 1 for the hash value are 5833 // If names of slots in range from 1 to kProbes - 1 for the hash value are
6008 // not equal to the name and kProbes-th slot is not used (its name is the 5834 // not equal to the name and kProbes-th slot is not used (its name is the
6009 // undefined value), it guarantees the hash table doesn't contain the 5835 // undefined value), it guarantees the hash table doesn't contain the
6010 // property. It's true even if some slots represent deleted properties 5836 // property. It's true even if some slots represent deleted properties
6011 // (their names are the null value). 5837 // (their names are the null value).
5838 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER,
5839 kPointerSize);
6012 for (int i = kInlinedProbes; i < kTotalProbes; i++) { 5840 for (int i = kInlinedProbes; i < kTotalProbes; i++) {
6013 // Compute the masked index: (hash + i + i * i) & mask. 5841 // Compute the masked index: (hash + i + i * i) & mask.
6014 __ movq(scratch, Operand(rsp, 2 * kPointerSize)); 5842 __ movq(scratch, args.GetArgumentOperand(1));
6015 if (i > 0) { 5843 if (i > 0) {
6016 __ addl(scratch, Immediate(NameDictionary::GetProbeOffset(i))); 5844 __ addl(scratch, Immediate(NameDictionary::GetProbeOffset(i)));
6017 } 5845 }
6018 __ and_(scratch, Operand(rsp, 0)); 5846 __ and_(scratch, Operand(rsp, 0));
6019 5847
6020 // Scale the index by multiplying by the entry size. 5848 // Scale the index by multiplying by the entry size.
6021 ASSERT(NameDictionary::kEntrySize == 3); 5849 ASSERT(NameDictionary::kEntrySize == 3);
6022 __ lea(index_, Operand(scratch, scratch, times_2, 0)); // index *= 3. 5850 __ lea(index_, Operand(scratch, scratch, times_2, 0)); // index *= 3.
6023 5851
6024 // Having undefined at this place means the name is not contained. 5852 // Having undefined at this place means the name is not contained.
6025 __ movq(scratch, Operand(dictionary_, 5853 __ movq(scratch, Operand(dictionary_,
6026 index_, 5854 index_,
6027 times_pointer_size, 5855 times_pointer_size,
6028 kElementsStartOffset - kHeapObjectTag)); 5856 kElementsStartOffset - kHeapObjectTag));
6029 5857
6030 __ Cmp(scratch, masm->isolate()->factory()->undefined_value()); 5858 __ Cmp(scratch, masm->isolate()->factory()->undefined_value());
6031 __ j(equal, &not_in_dictionary); 5859 __ j(equal, &not_in_dictionary);
6032 5860
6033 // Stop if found the property. 5861 // Stop if found the property.
6034 __ cmpq(scratch, Operand(rsp, 3 * kPointerSize)); 5862 __ cmpq(scratch, args.GetArgumentOperand(0));
6035 __ j(equal, &in_dictionary); 5863 __ j(equal, &in_dictionary);
6036 5864
6037 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { 5865 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
6038 // If we hit a key that is not a unique name during negative 5866 // If we hit a key that is not a unique name during negative
6039 // lookup we have to bailout as this key might be equal to the 5867 // lookup we have to bailout as this key might be equal to the
6040 // key we are looking for. 5868 // key we are looking for.
6041 5869
6042 // Check if the entry name is not a unique name. 5870 // Check if the entry name is not a unique name.
6043 __ movq(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); 5871 __ movq(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
6044 __ JumpIfNotUniqueName(FieldOperand(scratch, Map::kInstanceTypeOffset), 5872 __ JumpIfNotUniqueName(FieldOperand(scratch, Map::kInstanceTypeOffset),
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
6376 // clobbers rbx, rdx, rdi 6204 // clobbers rbx, rdx, rdi
6377 // ----------------------------------- 6205 // -----------------------------------
6378 6206
6379 Label element_done; 6207 Label element_done;
6380 Label double_elements; 6208 Label double_elements;
6381 Label smi_element; 6209 Label smi_element;
6382 Label slow_elements; 6210 Label slow_elements;
6383 Label fast_elements; 6211 Label fast_elements;
6384 6212
6385 // Get array literal index, array literal and its map. 6213 // Get array literal index, array literal and its map.
6386 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); 6214 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER);
6387 __ movq(rbx, Operand(rsp, 2 * kPointerSize)); 6215 __ movq(rdx, args.GetArgumentOperand(1));
6216 __ movq(rbx, args.GetArgumentOperand(0));
6388 __ movq(rdi, FieldOperand(rbx, JSObject::kMapOffset)); 6217 __ movq(rdi, FieldOperand(rbx, JSObject::kMapOffset));
6389 6218
6390 __ CheckFastElements(rdi, &double_elements); 6219 __ CheckFastElements(rdi, &double_elements);
6391 6220
6392 // FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS 6221 // FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS
6393 __ JumpIfSmi(rax, &smi_element); 6222 __ JumpIfSmi(rax, &smi_element);
6394 __ CheckFastSmiElements(rdi, &fast_elements); 6223 __ CheckFastSmiElements(rdi, &fast_elements);
6395 6224
6396 // Store into the array literal requires a elements transition. Call into 6225 // Store into the array literal requires a elements transition. Call into
6397 // the runtime. 6226 // the runtime.
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
6544 Handle<Object> undefined_sentinel( 6373 Handle<Object> undefined_sentinel(
6545 masm->isolate()->heap()->undefined_value(), 6374 masm->isolate()->heap()->undefined_value(),
6546 masm->isolate()); 6375 masm->isolate());
6547 6376
6548 // is the low bit set? If so, we are holey and that is good. 6377 // is the low bit set? If so, we are holey and that is good.
6549 __ testb(rdx, Immediate(1)); 6378 __ testb(rdx, Immediate(1));
6550 Label normal_sequence; 6379 Label normal_sequence;
6551 __ j(not_zero, &normal_sequence); 6380 __ j(not_zero, &normal_sequence);
6552 6381
6553 // look at the first argument 6382 // look at the first argument
6554 __ movq(rcx, Operand(rsp, kPointerSize)); 6383 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER);
6384 __ movq(rcx, args.GetArgumentOperand(0));
6555 __ testq(rcx, rcx); 6385 __ testq(rcx, rcx);
6556 __ j(zero, &normal_sequence); 6386 __ j(zero, &normal_sequence);
6557 6387
6558 // We are going to create a holey array, but our kind is non-holey. 6388 // We are going to create a holey array, but our kind is non-holey.
6559 // Fix kind and retry (only if we have an allocation site in the cell). 6389 // Fix kind and retry (only if we have an allocation site in the cell).
6560 __ incl(rdx); 6390 __ incl(rdx);
6561 __ Cmp(rbx, undefined_sentinel); 6391 __ Cmp(rbx, undefined_sentinel);
6562 __ j(equal, &normal_sequence); 6392 __ j(equal, &normal_sequence);
6563 __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset)); 6393 __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset));
6564 Handle<Map> allocation_site_map( 6394 Handle<Map> allocation_site_map(
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
6723 InternalArrayNoArgumentConstructorStub stub0(kind); 6553 InternalArrayNoArgumentConstructorStub stub0(kind);
6724 __ TailCallStub(&stub0); 6554 __ TailCallStub(&stub0);
6725 6555
6726 __ bind(&not_zero_case); 6556 __ bind(&not_zero_case);
6727 __ cmpl(rax, Immediate(1)); 6557 __ cmpl(rax, Immediate(1));
6728 __ j(greater, &not_one_case); 6558 __ j(greater, &not_one_case);
6729 6559
6730 if (IsFastPackedElementsKind(kind)) { 6560 if (IsFastPackedElementsKind(kind)) {
6731 // We might need to create a holey array 6561 // We might need to create a holey array
6732 // look at the first argument 6562 // look at the first argument
6733 __ movq(rcx, Operand(rsp, kPointerSize)); 6563 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER);
6564 __ movq(rcx, args.GetArgumentOperand(0));
6734 __ testq(rcx, rcx); 6565 __ testq(rcx, rcx);
6735 __ j(zero, &normal_sequence); 6566 __ j(zero, &normal_sequence);
6736 6567
6737 InternalArraySingleArgumentConstructorStub 6568 InternalArraySingleArgumentConstructorStub
6738 stub1_holey(GetHoleyElementsKind(kind)); 6569 stub1_holey(GetHoleyElementsKind(kind));
6739 __ TailCallStub(&stub1_holey); 6570 __ TailCallStub(&stub1_holey);
6740 } 6571 }
6741 6572
6742 __ bind(&normal_sequence); 6573 __ bind(&normal_sequence);
6743 InternalArraySingleArgumentConstructorStub stub1(kind); 6574 InternalArraySingleArgumentConstructorStub stub1(kind);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
6800 __ bind(&fast_elements_case); 6631 __ bind(&fast_elements_case);
6801 GenerateCase(masm, FAST_ELEMENTS); 6632 GenerateCase(masm, FAST_ELEMENTS);
6802 } 6633 }
6803 6634
6804 6635
6805 #undef __ 6636 #undef __
6806 6637
6807 } } // namespace v8::internal 6638 } } // namespace v8::internal
6808 6639
6809 #endif // V8_TARGET_ARCH_X64 6640 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/builtins-x64.cc ('k') | src/x64/codegen-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698