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

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

Issue 660095: Merge revision 3813 to 3930 from bleeding_edge to partial snapshots branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
Patch Set: '' Created 10 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/ia32/assembler-ia32.cc ('k') | src/ia32/codegen-ia32.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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-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 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 86
87 // Jump to the function-specific construct stub. 87 // Jump to the function-specific construct stub.
88 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 88 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
89 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kConstructStubOffset)); 89 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kConstructStubOffset));
90 __ lea(ebx, FieldOperand(ebx, Code::kHeaderSize)); 90 __ lea(ebx, FieldOperand(ebx, Code::kHeaderSize));
91 __ jmp(Operand(ebx)); 91 __ jmp(Operand(ebx));
92 92
93 // edi: called object 93 // edi: called object
94 // eax: number of arguments 94 // eax: number of arguments
95 __ bind(&non_function_call); 95 __ bind(&non_function_call);
96 96 // CALL_NON_FUNCTION expects the non-function constructor as receiver
97 // (instead of the original receiver from the call site). The receiver is
98 // stack element argc+1.
99 __ mov(Operand(esp, eax, times_4, kPointerSize), edi);
97 // Set expected number of arguments to zero (not changing eax). 100 // Set expected number of arguments to zero (not changing eax).
98 __ Set(ebx, Immediate(0)); 101 __ Set(ebx, Immediate(0));
99 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); 102 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
100 __ jmp(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), 103 __ jmp(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
101 RelocInfo::CODE_TARGET); 104 RelocInfo::CODE_TARGET);
102 } 105 }
103 106
104 107
105 static void Generate_JSConstructStubHelper(MacroAssembler* masm, 108 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
106 bool is_api_function) { 109 bool is_api_function) {
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 { Label done; 433 { Label done;
431 __ test(eax, Operand(eax)); 434 __ test(eax, Operand(eax));
432 __ j(not_zero, &done, taken); 435 __ j(not_zero, &done, taken);
433 __ pop(ebx); 436 __ pop(ebx);
434 __ push(Immediate(Factory::undefined_value())); 437 __ push(Immediate(Factory::undefined_value()));
435 __ push(ebx); 438 __ push(ebx);
436 __ inc(eax); 439 __ inc(eax);
437 __ bind(&done); 440 __ bind(&done);
438 } 441 }
439 442
440 // 2. Get the function to call from the stack. 443 // 2. Get the function to call (passed as receiver) from the stack, check
441 { Label done, non_function, function; 444 // if it is a function.
442 // +1 ~ return address. 445 Label non_function;
443 __ mov(edi, Operand(esp, eax, times_4, +1 * kPointerSize)); 446 // 1 ~ return address.
444 __ test(edi, Immediate(kSmiTagMask)); 447 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize));
445 __ j(zero, &non_function, not_taken); 448 __ test(edi, Immediate(kSmiTagMask));
446 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 449 __ j(zero, &non_function, not_taken);
447 __ j(equal, &function, taken); 450 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
451 __ j(not_equal, &non_function, not_taken);
448 452
449 // Non-function called: Clear the function to force exception.
450 __ bind(&non_function);
451 __ xor_(edi, Operand(edi));
452 __ jmp(&done);
453 453
454 // Function called: Change context eagerly to get the right global object. 454 // 3a. Patch the first argument if necessary when calling a function.
455 __ bind(&function); 455 Label shift_arguments;
456 { Label convert_to_object, use_global_receiver, patch_receiver;
457 // Change context eagerly in case we need the global receiver.
456 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 458 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
457 459
458 __ bind(&done); 460 __ mov(ebx, Operand(esp, eax, times_4, 0)); // First argument.
459 }
460
461 // 3. Make sure first argument is an object; convert if necessary.
462 { Label call_to_object, use_global_receiver, patch_receiver, done;
463 __ mov(ebx, Operand(esp, eax, times_4, 0));
464
465 __ test(ebx, Immediate(kSmiTagMask)); 461 __ test(ebx, Immediate(kSmiTagMask));
466 __ j(zero, &call_to_object); 462 __ j(zero, &convert_to_object);
467 463
468 __ cmp(ebx, Factory::null_value()); 464 __ cmp(ebx, Factory::null_value());
469 __ j(equal, &use_global_receiver); 465 __ j(equal, &use_global_receiver);
470 __ cmp(ebx, Factory::undefined_value()); 466 __ cmp(ebx, Factory::undefined_value());
471 __ j(equal, &use_global_receiver); 467 __ j(equal, &use_global_receiver);
472 468
473 __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset)); 469 __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset));
474 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 470 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
475 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); 471 __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
476 __ j(less, &call_to_object); 472 __ j(below, &convert_to_object);
477 __ cmp(ecx, LAST_JS_OBJECT_TYPE); 473 __ cmp(ecx, LAST_JS_OBJECT_TYPE);
478 __ j(less_equal, &done); 474 __ j(below_equal, &shift_arguments);
479 475
480 __ bind(&call_to_object); 476 __ bind(&convert_to_object);
481 __ EnterInternalFrame(); // preserves eax, ebx, edi 477 __ EnterInternalFrame(); // In order to preserve argument count.
482
483 // Store the arguments count on the stack (smi tagged).
484 __ SmiTag(eax); 478 __ SmiTag(eax);
485 __ push(eax); 479 __ push(eax);
486 480
487 __ push(edi); // save edi across the call
488 __ push(ebx); 481 __ push(ebx);
489 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 482 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
490 __ mov(ebx, eax); 483 __ mov(ebx, eax);
491 __ pop(edi); // restore edi after the call
492 484
493 // Get the arguments count and untag it.
494 __ pop(eax); 485 __ pop(eax);
495 __ SmiUntag(eax); 486 __ SmiUntag(eax);
496
497 __ LeaveInternalFrame(); 487 __ LeaveInternalFrame();
488 // Restore the function to edi.
489 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize));
498 __ jmp(&patch_receiver); 490 __ jmp(&patch_receiver);
499 491
500 // Use the global receiver object from the called function as the receiver. 492 // Use the global receiver object from the called function as the
493 // receiver.
501 __ bind(&use_global_receiver); 494 __ bind(&use_global_receiver);
502 const int kGlobalIndex = 495 const int kGlobalIndex =
503 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 496 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
504 __ mov(ebx, FieldOperand(esi, kGlobalIndex)); 497 __ mov(ebx, FieldOperand(esi, kGlobalIndex));
505 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalContextOffset)); 498 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalContextOffset));
506 __ mov(ebx, FieldOperand(ebx, kGlobalIndex)); 499 __ mov(ebx, FieldOperand(ebx, kGlobalIndex));
507 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); 500 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
508 501
509 __ bind(&patch_receiver); 502 __ bind(&patch_receiver);
510 __ mov(Operand(esp, eax, times_4, 0), ebx); 503 __ mov(Operand(esp, eax, times_4, 0), ebx);
511 504
512 __ bind(&done); 505 __ jmp(&shift_arguments);
513 } 506 }
514 507
515 // 4. Check that the function really is a function. 508 // 3b. Patch the first argument when calling a non-function. The
516 { Label done; 509 // CALL_NON_FUNCTION builtin expects the non-function callee as
517 __ test(edi, Operand(edi)); 510 // receiver, so overwrite the first argument which will ultimately
518 __ j(not_zero, &done, taken); 511 // become the receiver.
519 __ xor_(ebx, Operand(ebx)); 512 __ bind(&non_function);
520 // CALL_NON_FUNCTION will expect to find the non-function callee on the 513 __ mov(Operand(esp, eax, times_4, 0), edi);
521 // expression stack of the caller. Transfer it from receiver to the 514 // Clear edi to indicate a non-function being called.
522 // caller's expression stack (and make the first argument the receiver 515 __ xor_(edi, Operand(edi));
523 // for CALL_NON_FUNCTION) by decrementing the argument count.
524 __ dec(eax);
525 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
526 __ jmp(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
527 RelocInfo::CODE_TARGET);
528 __ bind(&done);
529 }
530 516
531 // 5. Shift arguments and return address one slot down on the stack 517 // 4. Shift arguments and return address one slot down on the stack
532 // (overwriting the receiver). 518 // (overwriting the original receiver). Adjust argument count to make
519 // the original first argument the new receiver.
520 __ bind(&shift_arguments);
533 { Label loop; 521 { Label loop;
534 __ mov(ecx, eax); 522 __ mov(ecx, eax);
535 __ bind(&loop); 523 __ bind(&loop);
536 __ mov(ebx, Operand(esp, ecx, times_4, 0)); 524 __ mov(ebx, Operand(esp, ecx, times_4, 0));
537 __ mov(Operand(esp, ecx, times_4, kPointerSize), ebx); 525 __ mov(Operand(esp, ecx, times_4, kPointerSize), ebx);
538 __ dec(ecx); 526 __ dec(ecx);
539 __ j(not_sign, &loop); 527 __ j(not_sign, &loop); // While non-negative (to copy return address).
540 __ pop(ebx); // Discard copy of return address. 528 __ pop(ebx); // Discard copy of return address.
541 __ dec(eax); // One fewer argument (first argument is new receiver). 529 __ dec(eax); // One fewer argument (first argument is new receiver).
542 } 530 }
543 531
544 // 6. Get the code to call from the function and check that the number of 532 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin.
545 // expected arguments matches what we're providing. 533 { Label function;
546 { __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 534 __ test(edi, Operand(edi));
547 __ mov(ebx, 535 __ j(not_zero, &function, taken);
548 FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); 536 __ xor_(ebx, Operand(ebx));
549 __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset)); 537 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
550 __ lea(edx, FieldOperand(edx, Code::kHeaderSize)); 538 __ jmp(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
551 __ cmp(eax, Operand(ebx)); 539 RelocInfo::CODE_TARGET);
552 __ j(not_equal, Handle<Code>(builtin(ArgumentsAdaptorTrampoline))); 540 __ bind(&function);
553 } 541 }
554 542
555 // 7. Jump (tail-call) to the code in register edx without checking arguments. 543 // 5b. Get the code to call from the function and check that the number of
544 // expected arguments matches what we're providing. If so, jump
545 // (tail-call) to the code in register edx without checking arguments.
546 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
547 __ mov(ebx,
548 FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
549 __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset));
550 __ lea(edx, FieldOperand(edx, Code::kHeaderSize));
551 __ cmp(eax, Operand(ebx));
552 __ j(not_equal, Handle<Code>(builtin(ArgumentsAdaptorTrampoline)));
553
556 ParameterCount expected(0); 554 ParameterCount expected(0);
557 __ InvokeCode(Operand(edx), expected, expected, JUMP_FUNCTION); 555 __ InvokeCode(Operand(edx), expected, expected, JUMP_FUNCTION);
558 } 556 }
559 557
560 558
561 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { 559 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
562 __ EnterInternalFrame(); 560 __ EnterInternalFrame();
563 561
564 __ push(Operand(ebp, 4 * kPointerSize)); // push this 562 __ push(Operand(ebp, 4 * kPointerSize)); // push this
565 __ push(Operand(ebp, 2 * kPointerSize)); // push arguments 563 __ push(Operand(ebp, 2 * kPointerSize)); // push arguments
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 638
641 // Push the receiver. 639 // Push the receiver.
642 __ bind(&push_receiver); 640 __ bind(&push_receiver);
643 __ push(ebx); 641 __ push(ebx);
644 642
645 // Copy all arguments from the array to the stack. 643 // Copy all arguments from the array to the stack.
646 Label entry, loop; 644 Label entry, loop;
647 __ mov(eax, Operand(ebp, kIndexOffset)); 645 __ mov(eax, Operand(ebp, kIndexOffset));
648 __ jmp(&entry); 646 __ jmp(&entry);
649 __ bind(&loop); 647 __ bind(&loop);
650 __ mov(ecx, Operand(ebp, 2 * kPointerSize)); // load arguments 648 __ mov(edx, Operand(ebp, 2 * kPointerSize)); // load arguments
651 __ push(ecx);
652 __ push(eax);
653 649
654 // Use inline caching to speed up access to arguments. 650 // Use inline caching to speed up access to arguments.
655 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 651 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
656 __ call(ic, RelocInfo::CODE_TARGET); 652 __ call(ic, RelocInfo::CODE_TARGET);
657 // It is important that we do not have a test instruction after the 653 // It is important that we do not have a test instruction after the
658 // call. A test instruction after the call is used to indicate that 654 // call. A test instruction after the call is used to indicate that
659 // we have generated an inline version of the keyed load. In this 655 // we have generated an inline version of the keyed load. In this
660 // case, we know that we are not generating a test instruction next. 656 // case, we know that we are not generating a test instruction next.
661 657
662 // Remove IC arguments from the stack and push the nth argument. 658 // Push the nth argument.
663 __ add(Operand(esp), Immediate(2 * kPointerSize));
664 __ push(eax); 659 __ push(eax);
665 660
666 // Update the index on the stack and in register eax. 661 // Update the index on the stack and in register eax.
667 __ mov(eax, Operand(ebp, kIndexOffset)); 662 __ mov(eax, Operand(ebp, kIndexOffset));
668 __ add(Operand(eax), Immediate(1 << kSmiTagSize)); 663 __ add(Operand(eax), Immediate(1 << kSmiTagSize));
669 __ mov(Operand(ebp, kIndexOffset), eax); 664 __ mov(Operand(ebp, kIndexOffset), eax);
670 665
671 __ bind(&entry); 666 __ bind(&entry);
672 __ cmp(eax, Operand(ebp, kLimitOffset)); 667 __ cmp(eax, Operand(ebp, kLimitOffset));
673 __ j(not_equal, &loop); 668 __ j(not_equal, &loop);
(...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after
1254 // Dont adapt arguments. 1249 // Dont adapt arguments.
1255 // ------------------------------------------- 1250 // -------------------------------------------
1256 __ bind(&dont_adapt_arguments); 1251 __ bind(&dont_adapt_arguments);
1257 __ jmp(Operand(edx)); 1252 __ jmp(Operand(edx));
1258 } 1253 }
1259 1254
1260 1255
1261 #undef __ 1256 #undef __
1262 1257
1263 } } // namespace v8::internal 1258 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/assembler-ia32.cc ('k') | src/ia32/codegen-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698