OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |