OLD | NEW |
---|---|
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 5979 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5990 | 5990 |
5991 | 5991 |
5992 void CodeGenerator::VisitThisFunction(ThisFunction* node) { | 5992 void CodeGenerator::VisitThisFunction(ThisFunction* node) { |
5993 frame_->PushFunction(); | 5993 frame_->PushFunction(); |
5994 } | 5994 } |
5995 | 5995 |
5996 | 5996 |
5997 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { | 5997 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { |
5998 Comment cmnt(masm_, "[ CompareOperation"); | 5998 Comment cmnt(masm_, "[ CompareOperation"); |
5999 | 5999 |
6000 bool left_already_loaded = false; | |
6001 | |
6000 // Get the expressions from the node. | 6002 // Get the expressions from the node. |
6001 Expression* left = node->left(); | 6003 Expression* left = node->left(); |
6002 Expression* right = node->right(); | 6004 Expression* right = node->right(); |
6003 Token::Value op = node->op(); | 6005 Token::Value op = node->op(); |
6004 // To make typeof testing for natives implemented in JavaScript really | 6006 // To make typeof testing for natives implemented in JavaScript really |
6005 // efficient, we generate special code for expressions of the form: | 6007 // efficient, we generate special code for expressions of the form: |
6006 // 'typeof <expression> == <string>'. | 6008 // 'typeof <expression> == <string>'. |
6007 UnaryOperation* operation = left->AsUnaryOperation(); | 6009 UnaryOperation* operation = left->AsUnaryOperation(); |
6008 if ((op == Token::EQ || op == Token::EQ_STRICT) && | 6010 if ((op == Token::EQ || op == Token::EQ_STRICT) && |
6009 (operation != NULL && operation->op() == Token::TYPEOF) && | 6011 (operation != NULL && operation->op() == Token::TYPEOF) && |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6070 } else if (check->Equals(Heap::function_symbol())) { | 6072 } else if (check->Equals(Heap::function_symbol())) { |
6071 __ test(answer.reg(), Immediate(kSmiTagMask)); | 6073 __ test(answer.reg(), Immediate(kSmiTagMask)); |
6072 destination()->false_target()->Branch(zero); | 6074 destination()->false_target()->Branch(zero); |
6073 frame_->Spill(answer.reg()); | 6075 frame_->Spill(answer.reg()); |
6074 __ CmpObjectType(answer.reg(), JS_FUNCTION_TYPE, answer.reg()); | 6076 __ CmpObjectType(answer.reg(), JS_FUNCTION_TYPE, answer.reg()); |
6075 destination()->true_target()->Branch(equal); | 6077 destination()->true_target()->Branch(equal); |
6076 // Regular expressions are callable so typeof == 'function'. | 6078 // Regular expressions are callable so typeof == 'function'. |
6077 __ CmpInstanceType(answer.reg(), JS_REGEXP_TYPE); | 6079 __ CmpInstanceType(answer.reg(), JS_REGEXP_TYPE); |
6078 answer.Unuse(); | 6080 answer.Unuse(); |
6079 destination()->Split(equal); | 6081 destination()->Split(equal); |
6080 | |
6081 } else if (check->Equals(Heap::object_symbol())) { | 6082 } else if (check->Equals(Heap::object_symbol())) { |
6082 __ test(answer.reg(), Immediate(kSmiTagMask)); | 6083 __ test(answer.reg(), Immediate(kSmiTagMask)); |
6083 destination()->false_target()->Branch(zero); | 6084 destination()->false_target()->Branch(zero); |
6084 __ cmp(answer.reg(), Factory::null_value()); | 6085 __ cmp(answer.reg(), Factory::null_value()); |
6085 destination()->true_target()->Branch(equal); | 6086 destination()->true_target()->Branch(equal); |
6086 | 6087 |
6087 Result map = allocator()->Allocate(); | 6088 Result map = allocator()->Allocate(); |
6088 ASSERT(map.is_valid()); | 6089 ASSERT(map.is_valid()); |
6089 // Regular expressions are typeof == 'function', not 'object'. | 6090 // Regular expressions are typeof == 'function', not 'object'. |
6090 __ CmpObjectType(answer.reg(), JS_REGEXP_TYPE, map.reg()); | 6091 __ CmpObjectType(answer.reg(), JS_REGEXP_TYPE, map.reg()); |
(...skipping 11 matching lines...) Expand all Loading... | |
6102 answer.Unuse(); | 6103 answer.Unuse(); |
6103 map.Unuse(); | 6104 map.Unuse(); |
6104 destination()->Split(less_equal); | 6105 destination()->Split(less_equal); |
6105 } else { | 6106 } else { |
6106 // Uncommon case: typeof testing against a string literal that is | 6107 // Uncommon case: typeof testing against a string literal that is |
6107 // never returned from the typeof operator. | 6108 // never returned from the typeof operator. |
6108 answer.Unuse(); | 6109 answer.Unuse(); |
6109 destination()->Goto(false); | 6110 destination()->Goto(false); |
6110 } | 6111 } |
6111 return; | 6112 return; |
6113 } else if (op == Token::LT && | |
6114 right->AsLiteral() != NULL && | |
6115 right->AsLiteral()->handle()->IsHeapNumber()) { | |
6116 Handle<HeapNumber> check(HeapNumber::cast(*right->AsLiteral()->handle())); | |
6117 if (check->value() == 2147483648.0) { // 0x80000000. | |
6118 Load(left); | |
6119 left_already_loaded = true; | |
6120 Result lhs = frame_->Pop(); | |
6121 lhs.ToRegister(); | |
6122 __ test(lhs.reg(), Immediate(kSmiTagMask)); | |
6123 destination()->true_target()->Branch(zero); // All Smis are less. | |
6124 Result scratch = allocator()->Allocate(); | |
6125 ASSERT(scratch.is_valid()); | |
6126 __ mov(scratch.reg(), FieldOperand(lhs.reg(), HeapObject::kMapOffset)); | |
6127 __ cmp(scratch.reg(), Factory::heap_number_map()); | |
6128 JumpTarget not_a_number; | |
6129 not_a_number.Branch(not_equal, &lhs); | |
6130 __ mov(scratch.reg(), FieldOperand(lhs.reg(), HeapNumber::kExponentOffset) ); | |
Søren Thygesen Gjesse
2009/12/21 14:59:39
Line longer than 80 chars.
| |
6131 __ cmp(Operand(scratch.reg()), Immediate(0xfff00000)); | |
6132 not_a_number.Branch(above_equal, &lhs); // It's a negative NaN or -Infini ty. | |
Søren Thygesen Gjesse
2009/12/21 14:59:39
Ditto.
| |
6133 const uint32_t borderline_exponent = | |
6134 (HeapNumber::kExponentBias + 31) << HeapNumber::kExponentShift; | |
6135 __ cmp(Operand(scratch.reg()), Immediate(borderline_exponent)); | |
6136 scratch.Unuse(); | |
6137 lhs.Unuse(); | |
6138 destination()->true_target()->Branch(less); | |
6139 destination()->false_target()->Jump(); | |
6140 | |
6141 not_a_number.Bind(&lhs); | |
6142 frame_->Push(&lhs); | |
6143 } | |
6112 } | 6144 } |
6113 | 6145 |
6114 Condition cc = no_condition; | 6146 Condition cc = no_condition; |
6115 bool strict = false; | 6147 bool strict = false; |
6116 switch (op) { | 6148 switch (op) { |
6117 case Token::EQ_STRICT: | 6149 case Token::EQ_STRICT: |
6118 strict = true; | 6150 strict = true; |
6119 // Fall through | 6151 // Fall through |
6120 case Token::EQ: | 6152 case Token::EQ: |
6121 cc = equal; | 6153 cc = equal; |
6122 break; | 6154 break; |
6123 case Token::LT: | 6155 case Token::LT: |
6124 cc = less; | 6156 cc = less; |
6125 break; | 6157 break; |
6126 case Token::GT: | 6158 case Token::GT: |
6127 cc = greater; | 6159 cc = greater; |
6128 break; | 6160 break; |
6129 case Token::LTE: | 6161 case Token::LTE: |
6130 cc = less_equal; | 6162 cc = less_equal; |
6131 break; | 6163 break; |
6132 case Token::GTE: | 6164 case Token::GTE: |
6133 cc = greater_equal; | 6165 cc = greater_equal; |
6134 break; | 6166 break; |
6135 case Token::IN: { | 6167 case Token::IN: { |
6136 Load(left); | 6168 if (!left_already_loaded) Load(left); |
6137 Load(right); | 6169 Load(right); |
6138 Result answer = frame_->InvokeBuiltin(Builtins::IN, CALL_FUNCTION, 2); | 6170 Result answer = frame_->InvokeBuiltin(Builtins::IN, CALL_FUNCTION, 2); |
6139 frame_->Push(&answer); // push the result | 6171 frame_->Push(&answer); // push the result |
6140 return; | 6172 return; |
6141 } | 6173 } |
6142 case Token::INSTANCEOF: { | 6174 case Token::INSTANCEOF: { |
6143 Load(left); | 6175 if (!left_already_loaded) Load(left); |
6144 Load(right); | 6176 Load(right); |
6145 InstanceofStub stub; | 6177 InstanceofStub stub; |
6146 Result answer = frame_->CallStub(&stub, 2); | 6178 Result answer = frame_->CallStub(&stub, 2); |
6147 answer.ToRegister(); | 6179 answer.ToRegister(); |
6148 __ test(answer.reg(), Operand(answer.reg())); | 6180 __ test(answer.reg(), Operand(answer.reg())); |
6149 answer.Unuse(); | 6181 answer.Unuse(); |
6150 destination()->Split(zero); | 6182 destination()->Split(zero); |
6151 return; | 6183 return; |
6152 } | 6184 } |
6153 default: | 6185 default: |
6154 UNREACHABLE(); | 6186 UNREACHABLE(); |
6155 } | 6187 } |
6156 Load(left); | 6188 if (!left_already_loaded) Load(left); |
6157 Load(right); | 6189 Load(right); |
6158 Comparison(node, cc, strict, destination()); | 6190 Comparison(node, cc, strict, destination()); |
6159 } | 6191 } |
6160 | 6192 |
6161 | 6193 |
6162 #ifdef DEBUG | 6194 #ifdef DEBUG |
6163 bool CodeGenerator::HasValidEntryRegisters() { | 6195 bool CodeGenerator::HasValidEntryRegisters() { |
6164 return (allocator()->count(eax) == (frame()->is_used(eax) ? 1 : 0)) | 6196 return (allocator()->count(eax) == (frame()->is_used(eax) ? 1 : 0)) |
6165 && (allocator()->count(ebx) == (frame()->is_used(ebx) ? 1 : 0)) | 6197 && (allocator()->count(ebx) == (frame()->is_used(ebx) ? 1 : 0)) |
6166 && (allocator()->count(ecx) == (frame()->is_used(ecx) ? 1 : 0)) | 6198 && (allocator()->count(ecx) == (frame()->is_used(ecx) ? 1 : 0)) |
(...skipping 2792 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8959 __ add(Operand(dest), Immediate(2)); | 8991 __ add(Operand(dest), Immediate(2)); |
8960 } | 8992 } |
8961 __ sub(Operand(count), Immediate(1)); | 8993 __ sub(Operand(count), Immediate(1)); |
8962 __ j(not_zero, &loop); | 8994 __ j(not_zero, &loop); |
8963 } | 8995 } |
8964 | 8996 |
8965 | 8997 |
8966 #undef __ | 8998 #undef __ |
8967 | 8999 |
8968 } } // namespace v8::internal | 9000 } } // namespace v8::internal |
OLD | NEW |