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

Side by Side Diff: src/x64/builtins-x64.cc

Issue 196077: X64: Extract all smi operations into MacroAssembler macros. (Closed)
Patch Set: Created 11 years, 3 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
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 54
55 // Store the arguments adaptor context sentinel. 55 // Store the arguments adaptor context sentinel.
56 __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 56 __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
57 57
58 // Push the function on the stack. 58 // Push the function on the stack.
59 __ push(rdi); 59 __ push(rdi);
60 60
61 // Preserve the number of arguments on the stack. Must preserve both 61 // Preserve the number of arguments on the stack. Must preserve both
62 // rax and rbx because these registers are used when copying the 62 // rax and rbx because these registers are used when copying the
63 // arguments and the receiver. 63 // arguments and the receiver.
64 ASSERT(kSmiTagSize == 1); 64 __ Integer32ToSmi(rcx, rax);
65 __ lea(rcx, Operand(rax, rax, times_1, kSmiTag));
66 __ push(rcx); 65 __ push(rcx);
67 } 66 }
68 67
69 68
70 static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { 69 static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
71 // Retrieve the number of arguments from the stack. Number is a Smi. 70 // Retrieve the number of arguments from the stack. Number is a Smi.
72 __ movq(rbx, Operand(rbp, ArgumentsAdaptorFrameConstants::kLengthOffset)); 71 __ movq(rbx, Operand(rbp, ArgumentsAdaptorFrameConstants::kLengthOffset));
73 72
74 // Leave the frame. 73 // Leave the frame.
75 __ movq(rsp, rbp); 74 __ movq(rsp, rbp);
76 __ pop(rbp); 75 __ pop(rbp);
77 76
78 // Remove caller arguments from the stack. 77 // Remove caller arguments from the stack.
79 // rbx holds a Smi, so we convery to dword offset by multiplying by 4. 78 // rbx holds a Smi, so we convery to dword offset by multiplying by 4.
79 // TODO(smi): Find a way to abstract indexing by a smi.
80 ASSERT_EQ(kSmiTagSize, 1 && kSmiTag == 0); 80 ASSERT_EQ(kSmiTagSize, 1 && kSmiTag == 0);
81 ASSERT_EQ(kPointerSize, (1 << kSmiTagSize) * 4); 81 ASSERT_EQ(kPointerSize, (1 << kSmiTagSize) * 4);
82 // TODO(smi): Find way to abstract indexing by a smi.
82 __ pop(rcx); 83 __ pop(rcx);
83 __ lea(rsp, Operand(rsp, rbx, times_4, 1 * kPointerSize)); // 1 ~ receiver 84 // 1 * kPointerSize is offset of receiver.
85 __ lea(rsp, Operand(rsp, rbx, times_half_pointer_size, 1 * kPointerSize));
84 __ push(rcx); 86 __ push(rcx);
85 } 87 }
86 88
87 89
88 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { 90 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
89 // ----------- S t a t e ------------- 91 // ----------- S t a t e -------------
90 // -- rax : actual number of arguments 92 // -- rax : actual number of arguments
91 // -- rbx : expected number of arguments 93 // -- rbx : expected number of arguments
92 // -- rdx : code entry to call 94 // -- rdx : code entry to call
93 // ----------------------------------- 95 // -----------------------------------
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 __ Push(Factory::undefined_value()); 187 __ Push(Factory::undefined_value());
186 __ push(rbx); 188 __ push(rbx);
187 __ incq(rax); 189 __ incq(rax);
188 __ bind(&done); 190 __ bind(&done);
189 } 191 }
190 192
191 // 2. Get the function to call from the stack. 193 // 2. Get the function to call from the stack.
192 { Label done, non_function, function; 194 { Label done, non_function, function;
193 // The function to call is at position n+1 on the stack. 195 // The function to call is at position n+1 on the stack.
194 __ movq(rdi, Operand(rsp, rax, times_pointer_size, +1 * kPointerSize)); 196 __ movq(rdi, Operand(rsp, rax, times_pointer_size, +1 * kPointerSize));
195 __ testl(rdi, Immediate(kSmiTagMask)); 197 __ JumpIfSmi(rdi, &non_function);
196 __ j(zero, &non_function);
197 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); 198 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
198 __ j(equal, &function); 199 __ j(equal, &function);
199 200
200 // Non-function called: Clear the function to force exception. 201 // Non-function called: Clear the function to force exception.
201 __ bind(&non_function); 202 __ bind(&non_function);
202 __ xor_(rdi, rdi); 203 __ xor_(rdi, rdi);
203 __ jmp(&done); 204 __ jmp(&done);
204 205
205 // Function called: Change context eagerly to get the right global object. 206 // Function called: Change context eagerly to get the right global object.
206 __ bind(&function); 207 __ bind(&function);
207 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 208 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
208 209
209 __ bind(&done); 210 __ bind(&done);
210 } 211 }
211 212
212 // 3. Make sure first argument is an object; convert if necessary. 213 // 3. Make sure first argument is an object; convert if necessary.
213 { Label call_to_object, use_global_receiver, patch_receiver, done; 214 { Label call_to_object, use_global_receiver, patch_receiver, done;
214 __ movq(rbx, Operand(rsp, rax, times_pointer_size, 0)); 215 __ movq(rbx, Operand(rsp, rax, times_pointer_size, 0));
215 216
216 __ testl(rbx, Immediate(kSmiTagMask)); 217 __ JumpIfSmi(rbx, &call_to_object);
217 __ j(zero, &call_to_object);
218 218
219 __ CompareRoot(rbx, Heap::kNullValueRootIndex); 219 __ CompareRoot(rbx, Heap::kNullValueRootIndex);
220 __ j(equal, &use_global_receiver); 220 __ j(equal, &use_global_receiver);
221 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); 221 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
222 __ j(equal, &use_global_receiver); 222 __ j(equal, &use_global_receiver);
223 223
224 __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, rcx); 224 __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, rcx);
225 __ j(below, &call_to_object); 225 __ j(below, &call_to_object);
226 __ CmpInstanceType(rcx, LAST_JS_OBJECT_TYPE); 226 __ CmpInstanceType(rcx, LAST_JS_OBJECT_TYPE);
227 __ j(below_equal, &done); 227 __ j(below_equal, &done);
228 228
229 __ bind(&call_to_object); 229 __ bind(&call_to_object);
230 __ EnterInternalFrame(); // preserves rax, rbx, rdi 230 __ EnterInternalFrame(); // preserves rax, rbx, rdi
231 231
232 // Store the arguments count on the stack (smi tagged). 232 // Store the arguments count on the stack (smi tagged).
233 ASSERT(kSmiTag == 0); 233 __ Integer32ToSmi(rax, rax);
234 __ shl(rax, Immediate(kSmiTagSize));
235 __ push(rax); 234 __ push(rax);
236 235
237 __ push(rdi); // save edi across the call 236 __ push(rdi); // save edi across the call
238 __ push(rbx); 237 __ push(rbx);
239 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 238 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
240 __ movq(rbx, rax); 239 __ movq(rbx, rax);
241 __ pop(rdi); // restore edi after the call 240 __ pop(rdi); // restore edi after the call
242 241
243 // Get the arguments count and untag it. 242 // Get the arguments count and untag it.
244 __ pop(rax); 243 __ pop(rax);
245 __ shr(rax, Immediate(kSmiTagSize)); 244 __ SmiToInteger32(rax, rax);
246 245
247 __ LeaveInternalFrame(); 246 __ LeaveInternalFrame();
248 __ jmp(&patch_receiver); 247 __ jmp(&patch_receiver);
249 248
250 // Use the global receiver object from the called function as the receiver. 249 // Use the global receiver object from the called function as the receiver.
251 __ bind(&use_global_receiver); 250 __ bind(&use_global_receiver);
252 const int kGlobalIndex = 251 const int kGlobalIndex =
253 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 252 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
254 __ movq(rbx, FieldOperand(rsi, kGlobalIndex)); 253 __ movq(rbx, FieldOperand(rsi, kGlobalIndex));
255 __ movq(rbx, FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); 254 __ movq(rbx, FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 __ CallRuntime(Runtime::kStackGuard, 1); 348 __ CallRuntime(Runtime::kStackGuard, 1);
350 __ pop(rax); 349 __ pop(rax);
351 __ jmp(&retry_preemption); 350 __ jmp(&retry_preemption);
352 351
353 __ bind(&no_preemption); 352 __ bind(&no_preemption);
354 353
355 Label okay; 354 Label okay;
356 // Make rdx the space we need for the array when it is unrolled onto the 355 // Make rdx the space we need for the array when it is unrolled onto the
357 // stack. 356 // stack.
358 __ movq(rdx, rax); 357 __ movq(rdx, rax);
359 __ shl(rdx, Immediate(kPointerSizeLog2 - kSmiTagSize)); 358 __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rdx, kPointerSizeLog2);
William Hesse 2009/09/10 11:13:22 Does this assume that the smi is zero-extended? I
Lasse Reichstein 2009/09/10 12:28:11 It should not assume anything except that rdx cont
Lasse Reichstein 2009/09/10 12:45:35 Ah, you were referring to the implementation. That
360 __ cmpq(rcx, rdx); 359 __ cmpq(rcx, rdx);
361 __ j(greater, &okay); 360 __ j(greater, &okay);
362 361
363 // Too bad: Out of stack space. 362 // Too bad: Out of stack space.
364 __ push(Operand(rbp, kFunctionOffset)); 363 __ push(Operand(rbp, kFunctionOffset));
365 __ push(rax); 364 __ push(rax);
366 __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION); 365 __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
367 __ bind(&okay); 366 __ bind(&okay);
368 } 367 }
369 368
370 // Push current index and limit. 369 // Push current index and limit.
371 const int kLimitOffset = 370 const int kLimitOffset =
372 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; 371 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
373 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; 372 const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
374 __ push(rax); // limit 373 __ push(rax); // limit
375 __ push(Immediate(0)); // index 374 __ push(Immediate(0)); // index
376 375
377 // Change context eagerly to get the right global object if 376 // Change context eagerly to get the right global object if
378 // necessary. 377 // necessary.
379 __ movq(rdi, Operand(rbp, kFunctionOffset)); 378 __ movq(rdi, Operand(rbp, kFunctionOffset));
380 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 379 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
381 380
382 // Compute the receiver. 381 // Compute the receiver.
383 Label call_to_object, use_global_receiver, push_receiver; 382 Label call_to_object, use_global_receiver, push_receiver;
384 __ movq(rbx, Operand(rbp, kReceiverOffset)); 383 __ movq(rbx, Operand(rbp, kReceiverOffset));
385 __ testl(rbx, Immediate(kSmiTagMask)); 384 __ JumpIfSmi(rbx, &call_to_object);
386 __ j(zero, &call_to_object);
387 __ CompareRoot(rbx, Heap::kNullValueRootIndex); 385 __ CompareRoot(rbx, Heap::kNullValueRootIndex);
388 __ j(equal, &use_global_receiver); 386 __ j(equal, &use_global_receiver);
389 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); 387 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
390 __ j(equal, &use_global_receiver); 388 __ j(equal, &use_global_receiver);
391 389
392 // If given receiver is already a JavaScript object then there's no 390 // If given receiver is already a JavaScript object then there's no
393 // reason for converting it. 391 // reason for converting it.
394 __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, rcx); 392 __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, rcx);
395 __ j(below, &call_to_object); 393 __ j(below, &call_to_object);
396 __ CmpInstanceType(rcx, LAST_JS_OBJECT_TYPE); 394 __ CmpInstanceType(rcx, LAST_JS_OBJECT_TYPE);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 __ movq(rax, Operand(rbp, kIndexOffset)); 437 __ movq(rax, Operand(rbp, kIndexOffset));
440 __ addq(rax, Immediate(Smi::FromInt(1))); 438 __ addq(rax, Immediate(Smi::FromInt(1)));
441 __ movq(Operand(rbp, kIndexOffset), rax); 439 __ movq(Operand(rbp, kIndexOffset), rax);
442 440
443 __ bind(&entry); 441 __ bind(&entry);
444 __ cmpq(rax, Operand(rbp, kLimitOffset)); 442 __ cmpq(rax, Operand(rbp, kLimitOffset));
445 __ j(not_equal, &loop); 443 __ j(not_equal, &loop);
446 444
447 // Invoke the function. 445 // Invoke the function.
448 ParameterCount actual(rax); 446 ParameterCount actual(rax);
449 __ shr(rax, Immediate(kSmiTagSize)); 447 __ SmiToInteger32(rax, rax);
450 __ movq(rdi, Operand(rbp, kFunctionOffset)); 448 __ movq(rdi, Operand(rbp, kFunctionOffset));
451 __ InvokeFunction(rdi, actual, CALL_FUNCTION); 449 __ InvokeFunction(rdi, actual, CALL_FUNCTION);
452 450
453 __ LeaveInternalFrame(); 451 __ LeaveInternalFrame();
454 __ ret(3 * kPointerSize); // remove function, receiver, and arguments 452 __ ret(3 * kPointerSize); // remove function, receiver, and arguments
455 } 453 }
456 454
457 455
458 void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { 456 void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
459 // ----------- S t a t e ------------- 457 // ----------- S t a t e -------------
460 // -- rax: number of arguments 458 // -- rax: number of arguments
461 // -- rdi: constructor function 459 // -- rdi: constructor function
462 // ----------------------------------- 460 // -----------------------------------
463 461
464 Label non_function_call; 462 Label non_function_call;
465 // Check that function is not a smi. 463 // Check that function is not a smi.
466 __ testl(rdi, Immediate(kSmiTagMask)); 464 __ JumpIfSmi(rdi, &non_function_call);
467 __ j(zero, &non_function_call);
468 // Check that function is a JSFunction. 465 // Check that function is a JSFunction.
469 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); 466 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
470 __ j(not_equal, &non_function_call); 467 __ j(not_equal, &non_function_call);
471 468
472 // Jump to the function-specific construct stub. 469 // Jump to the function-specific construct stub.
473 __ movq(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); 470 __ movq(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
474 __ movq(rbx, FieldOperand(rbx, SharedFunctionInfo::kConstructStubOffset)); 471 __ movq(rbx, FieldOperand(rbx, SharedFunctionInfo::kConstructStubOffset));
475 __ lea(rbx, FieldOperand(rbx, Code::kHeaderSize)); 472 __ lea(rbx, FieldOperand(rbx, Code::kHeaderSize));
476 __ jmp(rbx); 473 __ jmp(rbx);
477 474
478 // edi: called object 475 // edi: called object
479 // eax: number of arguments 476 // eax: number of arguments
480 __ bind(&non_function_call); 477 __ bind(&non_function_call);
481 478
482 // Set expected number of arguments to zero (not changing eax). 479 // Set expected number of arguments to zero (not changing eax).
483 __ movq(rbx, Immediate(0)); 480 __ movq(rbx, Immediate(0));
484 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); 481 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
485 __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), 482 __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
486 RelocInfo::CODE_TARGET); 483 RelocInfo::CODE_TARGET);
487 } 484 }
488 485
489 486
490 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 487 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
491 // Enter a construct frame. 488 // Enter a construct frame.
492 __ EnterConstructFrame(); 489 __ EnterConstructFrame();
493 490
494 // Store a smi-tagged arguments count on the stack. 491 // Store a smi-tagged arguments count on the stack.
495 __ shl(rax, Immediate(kSmiTagSize)); 492 __ Integer32ToSmi(rax, rax);
496 __ push(rax); 493 __ push(rax);
497 494
498 // Push the function to invoke on the stack. 495 // Push the function to invoke on the stack.
499 __ push(rdi); 496 __ push(rdi);
500 497
501 // Try to allocate the object without transitioning into C code. If any of the 498 // Try to allocate the object without transitioning into C code. If any of the
502 // preconditions is not met, the code bails out to the runtime call. 499 // preconditions is not met, the code bails out to the runtime call.
503 Label rt_call, allocated; 500 Label rt_call, allocated;
504 if (FLAG_inline_new) { 501 if (FLAG_inline_new) {
505 Label undo_allocation; 502 Label undo_allocation;
506 503
507 #ifdef ENABLE_DEBUGGER_SUPPORT 504 #ifdef ENABLE_DEBUGGER_SUPPORT
508 ExternalReference debug_step_in_fp = 505 ExternalReference debug_step_in_fp =
509 ExternalReference::debug_step_in_fp_address(); 506 ExternalReference::debug_step_in_fp_address();
510 __ movq(kScratchRegister, debug_step_in_fp); 507 __ movq(kScratchRegister, debug_step_in_fp);
511 __ cmpq(Operand(kScratchRegister, 0), Immediate(0)); 508 __ cmpq(Operand(kScratchRegister, 0), Immediate(0));
512 __ j(not_equal, &rt_call); 509 __ j(not_equal, &rt_call);
513 #endif 510 #endif
514 511
515 // Verified that the constructor is a JSFunction. 512 // Verified that the constructor is a JSFunction.
516 // Load the initial map and verify that it is in fact a map. 513 // Load the initial map and verify that it is in fact a map.
517 // rdi: constructor 514 // rdi: constructor
518 __ movq(rax, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); 515 __ movq(rax, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
519 // Will both indicate a NULL and a Smi 516 // Will both indicate a NULL and a Smi
520 __ testl(rax, Immediate(kSmiTagMask)); 517 __ JumpIfSmi(rax, &rt_call);
521 __ j(zero, &rt_call);
522 // rdi: constructor 518 // rdi: constructor
523 // rax: initial map (if proven valid below) 519 // rax: initial map (if proven valid below)
524 __ CmpObjectType(rax, MAP_TYPE, rbx); 520 __ CmpObjectType(rax, MAP_TYPE, rbx);
525 __ j(not_equal, &rt_call); 521 __ j(not_equal, &rt_call);
526 522
527 // Check that the constructor is not constructing a JSFunction (see comments 523 // Check that the constructor is not constructing a JSFunction (see comments
528 // in Runtime_NewObject in runtime.cc). In which case the initial map's 524 // in Runtime_NewObject in runtime.cc). In which case the initial map's
529 // instance type would be JS_FUNCTION_TYPE. 525 // instance type would be JS_FUNCTION_TYPE.
530 // rdi: constructor 526 // rdi: constructor
531 // rax: initial map 527 // rax: initial map
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 __ movq(rbx, rax); // store result in rbx 657 __ movq(rbx, rax); // store result in rbx
662 658
663 // New object allocated. 659 // New object allocated.
664 // rbx: newly allocated object 660 // rbx: newly allocated object
665 __ bind(&allocated); 661 __ bind(&allocated);
666 // Retrieve the function from the stack. 662 // Retrieve the function from the stack.
667 __ pop(rdi); 663 __ pop(rdi);
668 664
669 // Retrieve smi-tagged arguments count from the stack. 665 // Retrieve smi-tagged arguments count from the stack.
670 __ movq(rax, Operand(rsp, 0)); 666 __ movq(rax, Operand(rsp, 0));
671 __ shr(rax, Immediate(kSmiTagSize)); 667 __ SmiToInteger32(rax, rax);
672 668
673 // Push the allocated receiver to the stack. We need two copies 669 // Push the allocated receiver to the stack. We need two copies
674 // because we may have to return the original one and the calling 670 // because we may have to return the original one and the calling
675 // conventions dictate that the called function pops the receiver. 671 // conventions dictate that the called function pops the receiver.
676 __ push(rbx); 672 __ push(rbx);
677 __ push(rbx); 673 __ push(rbx);
678 674
679 // Setup pointer to last argument. 675 // Setup pointer to last argument.
680 __ lea(rbx, Operand(rbp, StandardFrameConstants::kCallerSPOffset)); 676 __ lea(rbx, Operand(rbp, StandardFrameConstants::kCallerSPOffset));
681 677
(...skipping 12 matching lines...) Expand all
694 __ InvokeFunction(rdi, actual, CALL_FUNCTION); 690 __ InvokeFunction(rdi, actual, CALL_FUNCTION);
695 691
696 // Restore context from the frame. 692 // Restore context from the frame.
697 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 693 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
698 694
699 // If the result is an object (in the ECMA sense), we should get rid 695 // If the result is an object (in the ECMA sense), we should get rid
700 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 696 // of the receiver and use the result; see ECMA-262 section 13.2.2-7
701 // on page 74. 697 // on page 74.
702 Label use_receiver, exit; 698 Label use_receiver, exit;
703 // If the result is a smi, it is *not* an object in the ECMA sense. 699 // If the result is a smi, it is *not* an object in the ECMA sense.
704 __ testl(rax, Immediate(kSmiTagMask)); 700 __ JumpIfSmi(rax, &use_receiver);
705 __ j(zero, &use_receiver);
706 701
707 // If the type of the result (stored in its map) is less than 702 // If the type of the result (stored in its map) is less than
708 // FIRST_JS_OBJECT_TYPE, it is not an object in the ECMA sense. 703 // FIRST_JS_OBJECT_TYPE, it is not an object in the ECMA sense.
709 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx); 704 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx);
710 __ j(above_equal, &exit); 705 __ j(above_equal, &exit);
711 706
712 // Throw away the result of the constructor invocation and use the 707 // Throw away the result of the constructor invocation and use the
713 // on-stack receiver as the result. 708 // on-stack receiver as the result.
714 __ bind(&use_receiver); 709 __ bind(&use_receiver);
715 __ movq(rax, Operand(rsp, 0)); 710 __ movq(rax, Operand(rsp, 0));
716 711
717 // Restore the arguments count and leave the construct frame. 712 // Restore the arguments count and leave the construct frame.
718 __ bind(&exit); 713 __ bind(&exit);
719 __ movq(rbx, Operand(rsp, kPointerSize)); // get arguments count 714 __ movq(rbx, Operand(rsp, kPointerSize)); // get arguments count
720 __ LeaveConstructFrame(); 715 __ LeaveConstructFrame();
721 716
722 // Remove caller arguments from the stack and return. 717 // Remove caller arguments from the stack and return.
723 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 718 ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
719 // TODO(smi): Find a way to abstract indexing by a smi.
724 __ pop(rcx); 720 __ pop(rcx);
725 __ lea(rsp, Operand(rsp, rbx, times_4, 1 * kPointerSize)); // 1 ~ receiver 721 // 1 * kPointerSize is offset of receiver.
722 __ lea(rsp, Operand(rsp, rbx, times_half_pointer_size, 1 * kPointerSize));
726 __ push(rcx); 723 __ push(rcx);
727 __ IncrementCounter(&Counters::constructed_objects, 1); 724 __ IncrementCounter(&Counters::constructed_objects, 1);
728 __ ret(0); 725 __ ret(0);
729 } 726 }
730 727
731 728
732 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, 729 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
733 bool is_construct) { 730 bool is_construct) {
734 // Expects five C++ function parameters. 731 // Expects five C++ function parameters.
735 // - Address entry (ignored) 732 // - Address entry (ignored)
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
846 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { 843 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
847 Generate_JSEntryTrampolineHelper(masm, false); 844 Generate_JSEntryTrampolineHelper(masm, false);
848 } 845 }
849 846
850 847
851 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { 848 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
852 Generate_JSEntryTrampolineHelper(masm, true); 849 Generate_JSEntryTrampolineHelper(masm, true);
853 } 850 }
854 851
855 } } // namespace v8::internal 852 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/x64/assembler-x64.cc ('k') | src/x64/codegen-x64.cc » ('j') | src/x64/codegen-x64.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698