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

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

Issue 6341: Improve the generated code for the instanceof operator. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 12 years, 2 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
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 876 matching lines...) Expand 10 before | Expand all | Expand 10 after
887 } 887 }
888 888
889 889
890 class ToBooleanStub: public CodeStub { 890 class ToBooleanStub: public CodeStub {
891 public: 891 public:
892 ToBooleanStub() { } 892 ToBooleanStub() { }
893 893
894 void Generate(MacroAssembler* masm); 894 void Generate(MacroAssembler* masm);
895 895
896 private: 896 private:
897
898 Major MajorKey() { return ToBoolean; } 897 Major MajorKey() { return ToBoolean; }
899
900 int MinorKey() { return 0; } 898 int MinorKey() { return 0; }
901
902 const char* GetName() { return "ToBooleanStub"; }
903
904 #ifdef DEBUG
905 void Print() {
906 PrintF("ToBooleanStub\n");
907 }
908 #endif
909 }; 899 };
910 900
911 901
912 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and 902 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and
913 // convert it to a boolean in the condition code register or jump to 903 // convert it to a boolean in the condition code register or jump to
914 // 'false_target'/'true_target' as appropriate. 904 // 'false_target'/'true_target' as appropriate.
915 void Ia32CodeGenerator::ToBoolean(Label* true_target, Label* false_target) { 905 void Ia32CodeGenerator::ToBoolean(Label* true_target, Label* false_target) {
916 Comment cmnt(masm_, "[ ToBoolean"); 906 Comment cmnt(masm_, "[ ToBoolean");
917 907
918 // The value to convert should be popped from the stack. 908 // The value to convert should be popped from the stack.
(...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after
1469 bool strict_; 1459 bool strict_;
1470 1460
1471 Major MajorKey() { return Compare; } 1461 Major MajorKey() { return Compare; }
1472 1462
1473 int MinorKey() { 1463 int MinorKey() {
1474 // Encode the three parameters in a unique 16 bit value. 1464 // Encode the three parameters in a unique 16 bit value.
1475 ASSERT(static_cast<int>(cc_) < (1 << 15)); 1465 ASSERT(static_cast<int>(cc_) < (1 << 15));
1476 return (static_cast<int>(cc_) << 1) | (strict_ ? 1 : 0); 1466 return (static_cast<int>(cc_) << 1) | (strict_ ? 1 : 0);
1477 } 1467 }
1478 1468
1479 const char* GetName() { return "CompareStub"; }
1480
1481 #ifdef DEBUG 1469 #ifdef DEBUG
1482 void Print() { 1470 void Print() {
1483 PrintF("CompareStub (cc %d), (strict %s)\n", 1471 PrintF("CompareStub (cc %d), (strict %s)\n",
1484 static_cast<int>(cc_), 1472 static_cast<int>(cc_),
1485 strict_ ? "true" : "false"); 1473 strict_ ? "true" : "false");
1486 } 1474 }
1487 #endif 1475 #endif
1488 }; 1476 };
1489 1477
1490 1478
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1578 1566
1579 class CallFunctionStub: public CodeStub { 1567 class CallFunctionStub: public CodeStub {
1580 public: 1568 public:
1581 explicit CallFunctionStub(int argc) : argc_(argc) { } 1569 explicit CallFunctionStub(int argc) : argc_(argc) { }
1582 1570
1583 void Generate(MacroAssembler* masm); 1571 void Generate(MacroAssembler* masm);
1584 1572
1585 private: 1573 private:
1586 int argc_; 1574 int argc_;
1587 1575
1588 const char* GetName() { return "CallFunctionStub"; }
1589
1590 #ifdef DEBUG 1576 #ifdef DEBUG
1591 void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); } 1577 void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); }
1592 #endif 1578 #endif
1593 1579
1594 Major MajorKey() { return CallFunction; } 1580 Major MajorKey() { return CallFunction; }
1595 int MinorKey() { return argc_; } 1581 int MinorKey() { return argc_; }
1596 }; 1582 };
1597 1583
1598 1584
1599 // Call the function just below TOS on the stack with the given 1585 // Call the function just below TOS on the stack with the given
(...skipping 1914 matching lines...) Expand 10 before | Expand all | Expand 10 after
3514 explicit RevertToNumberStub(bool is_increment) 3500 explicit RevertToNumberStub(bool is_increment)
3515 : is_increment_(is_increment) { } 3501 : is_increment_(is_increment) { }
3516 3502
3517 private: 3503 private:
3518 bool is_increment_; 3504 bool is_increment_;
3519 3505
3520 Major MajorKey() { return RevertToNumber; } 3506 Major MajorKey() { return RevertToNumber; }
3521 int MinorKey() { return is_increment_ ? 1 : 0; } 3507 int MinorKey() { return is_increment_ ? 1 : 0; }
3522 void Generate(MacroAssembler* masm); 3508 void Generate(MacroAssembler* masm);
3523 3509
3524 const char* GetName() { return "RevertToNumberStub"; }
3525
3526 #ifdef DEBUG 3510 #ifdef DEBUG
3527 void Print() { 3511 void Print() {
3528 PrintF("RevertToNumberStub (is_increment %s)\n", 3512 PrintF("RevertToNumberStub (is_increment %s)\n",
3529 is_increment_ ? "true" : "false"); 3513 is_increment_ ? "true" : "false");
3530 } 3514 }
3531 #endif 3515 #endif
3532 }; 3516 };
3533 3517
3534 3518
3535 class CounterOpStub: public CodeStub { 3519 class CounterOpStub: public CodeStub {
3536 public: 3520 public:
3537 CounterOpStub(int result_offset, bool is_postfix, bool is_increment) 3521 CounterOpStub(int result_offset, bool is_postfix, bool is_increment)
3538 : result_offset_(result_offset), 3522 : result_offset_(result_offset),
3539 is_postfix_(is_postfix), 3523 is_postfix_(is_postfix),
3540 is_increment_(is_increment) { } 3524 is_increment_(is_increment) { }
3541 3525
3542 private: 3526 private:
3543 int result_offset_; 3527 int result_offset_;
3544 bool is_postfix_; 3528 bool is_postfix_;
3545 bool is_increment_; 3529 bool is_increment_;
3546 3530
3547 Major MajorKey() { return CounterOp; } 3531 Major MajorKey() { return CounterOp; }
3548 int MinorKey() { 3532 int MinorKey() {
3549 return ((result_offset_ << 2) | 3533 return ((result_offset_ << 2) |
3550 (is_postfix_ ? 2 : 0) | 3534 (is_postfix_ ? 2 : 0) |
3551 (is_increment_ ? 1 : 0)); 3535 (is_increment_ ? 1 : 0));
3552 } 3536 }
3553 void Generate(MacroAssembler* masm); 3537 void Generate(MacroAssembler* masm);
3554 3538
3555 const char* GetName() { return "CounterOpStub"; }
3556
3557 #ifdef DEBUG 3539 #ifdef DEBUG
3558 void Print() { 3540 void Print() {
3559 PrintF("CounterOpStub (result_offset %d), (is_postfix %s)," 3541 PrintF("CounterOpStub (result_offset %d), (is_postfix %s),"
3560 " (is_increment %s)\n", 3542 " (is_increment %s)\n",
3561 result_offset_, 3543 result_offset_,
3562 is_postfix_ ? "true" : "false", 3544 is_postfix_ ? "true" : "false",
3563 is_increment_ ? "true" : "false"); 3545 is_increment_ ? "true" : "false");
3564 } 3546 }
3565 #endif 3547 #endif
3566 }; 3548 };
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
3747 } 3729 }
3748 } 3730 }
3749 } 3731 }
3750 3732
3751 3733
3752 void Ia32CodeGenerator::VisitThisFunction(ThisFunction* node) { 3734 void Ia32CodeGenerator::VisitThisFunction(ThisFunction* node) {
3753 __ push(FunctionOperand()); 3735 __ push(FunctionOperand());
3754 } 3736 }
3755 3737
3756 3738
3739 class InstanceofStub: public CodeStub {
3740 public:
3741 InstanceofStub() { }
3742
3743 void Generate(MacroAssembler* masm);
3744
3745 private:
3746 Major MajorKey() { return Instanceof; }
3747 int MinorKey() { return 0; }
3748 };
3749
3750
3757 void Ia32CodeGenerator::VisitCompareOperation(CompareOperation* node) { 3751 void Ia32CodeGenerator::VisitCompareOperation(CompareOperation* node) {
3758 Comment cmnt(masm_, "[ CompareOperation"); 3752 Comment cmnt(masm_, "[ CompareOperation");
3759 3753
3760 // Get the expressions from the node. 3754 // Get the expressions from the node.
3761 Expression* left = node->left(); 3755 Expression* left = node->left();
3762 Expression* right = node->right(); 3756 Expression* right = node->right();
3763 Token::Value op = node->op(); 3757 Token::Value op = node->op();
3764 3758
3765 // NOTE: To make null checks efficient, we check if either left or 3759 // NOTE: To make null checks efficient, we check if either left or
3766 // right is the literal 'null'. If so, we optimize the code by 3760 // right is the literal 'null'. If so, we optimize the code by
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
3927 case Token::IN: { 3921 case Token::IN: {
3928 Load(left); 3922 Load(left);
3929 Load(right); 3923 Load(right);
3930 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 3924 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
3931 __ push(eax); // push the result 3925 __ push(eax); // push the result
3932 return; 3926 return;
3933 } 3927 }
3934 case Token::INSTANCEOF: { 3928 case Token::INSTANCEOF: {
3935 Load(left); 3929 Load(left);
3936 Load(right); 3930 Load(right);
3937 __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION); 3931 InstanceofStub stub;
3938 __ push(eax); // push the result 3932 __ CallStub(&stub);
3933 __ test(eax, Operand(eax));
3934 cc_reg_ = zero;
3939 return; 3935 return;
3940 } 3936 }
3941 default: 3937 default:
3942 UNREACHABLE(); 3938 UNREACHABLE();
3943 } 3939 }
3944 3940
3945 // Optimize for the case where (at least) one of the expressions 3941 // Optimize for the case where (at least) one of the expressions
3946 // is a literal small integer. 3942 // is a literal small integer.
3947 if (IsInlineSmi(left->AsLiteral())) { 3943 if (IsInlineSmi(left->AsLiteral())) {
3948 Load(right); 3944 Load(right);
(...skipping 1333 matching lines...) Expand 10 before | Expand all | Expand 10 after
5282 __ pop(esi); 5278 __ pop(esi);
5283 __ pop(edi); 5279 __ pop(edi);
5284 __ add(Operand(esp), Immediate(2 * kPointerSize)); // remove markers 5280 __ add(Operand(esp), Immediate(2 * kPointerSize)); // remove markers
5285 5281
5286 // Restore frame pointer and return. 5282 // Restore frame pointer and return.
5287 __ pop(ebp); 5283 __ pop(ebp);
5288 __ ret(0); 5284 __ ret(0);
5289 } 5285 }
5290 5286
5291 5287
5288 void InstanceofStub::Generate(MacroAssembler* masm) {
5289 // Get the object - go slow case if it's a smi.
5290 Label slow;
5291 __ mov(eax, Operand(esp, 2 * kPointerSize)); // 2 ~ return address, function
5292 __ test(eax, Immediate(kSmiTagMask));
5293 __ j(zero, &slow, not_taken);
5294
5295 // Check that the left hand is a JS object.
5296 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); // ebx - object map
5297 __ movzx_b(ecx, FieldOperand(eax, Map::kInstanceTypeOffset)); // ecx - type
5298 __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
5299 __ j(less, &slow, not_taken);
5300 __ cmp(ecx, LAST_JS_OBJECT_TYPE);
5301 __ j(greater, &slow, not_taken);
5302
5303 // Get the prototype of the function.
5304 __ mov(edx, Operand(esp, 1 * kPointerSize)); // 1 ~ return address
5305 __ TryGetFunctionPrototype(edx, ebx, ecx, &slow);
5306
5307 // Register mapping: eax is object map and ebx is function prototype.
5308 __ mov(ecx, FieldOperand(eax, Map::kPrototypeOffset));
5309
5310 // Loop through the prototype chain looking for the function prototype.
5311 Label loop, is_instance, is_not_instance;
5312 __ bind(&loop);
5313 __ cmp(ecx, Operand(ebx));
5314 __ j(equal, &is_instance);
5315 __ cmp(Operand(ecx), Immediate(Factory::null_value()));
5316 __ j(equal, &is_not_instance);
5317 __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset));
5318 __ mov(ecx, FieldOperand(ecx, Map::kPrototypeOffset));
5319 __ jmp(&loop);
5320
5321 __ bind(&is_instance);
5322 __ Set(eax, Immediate(0));
5323 __ ret(2 * kPointerSize);
5324
5325 __ bind(&is_not_instance);
5326 __ Set(eax, Immediate(Smi::FromInt(1)));
5327 __ ret(2 * kPointerSize);
5328
5329 // Slow-case: Go through the JavaScript implementation.
5330 __ bind(&slow);
5331 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5332 }
5333
5334
5292 #undef __ 5335 #undef __
5293 5336
5294 // ----------------------------------------------------------------------------- 5337 // -----------------------------------------------------------------------------
5295 // CodeGenerator interfaces 5338 // CodeGenerator interfaces
5296 5339
5297 // MakeCode() is just a wrapper for CodeGenerator::MakeCode() 5340 // MakeCode() is just a wrapper for CodeGenerator::MakeCode()
5298 // so we don't have to expose the entire CodeGenerator class in 5341 // so we don't have to expose the entire CodeGenerator class in
5299 // the .h file. 5342 // the .h file.
5300 Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* fun, 5343 Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* fun,
5301 Handle<Script> script, 5344 Handle<Script> script,
5302 bool is_eval) { 5345 bool is_eval) {
5303 Handle<Code> code = Ia32CodeGenerator::MakeCode(fun, script, is_eval); 5346 Handle<Code> code = Ia32CodeGenerator::MakeCode(fun, script, is_eval);
5304 if (!code.is_null()) { 5347 if (!code.is_null()) {
5305 Counters::total_compiled_code_size.Increment(code->instruction_size()); 5348 Counters::total_compiled_code_size.Increment(code->instruction_size());
5306 } 5349 }
5307 return code; 5350 return code;
5308 } 5351 }
5309 5352
5310 5353
5311 } } // namespace v8::internal 5354 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-arm.cc ('k') | src/macro-assembler-ia32.h » ('j') | src/macro-assembler-ia32.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698