Chromium Code Reviews| 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 |