| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 14 matching lines...) Expand all Loading... |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "ast.h" | 30 #include "ast.h" |
| 31 #include "jump-target-inl.h" | 31 #include "jump-target-inl.h" |
| 32 #include "parser.h" | 32 #include "parser.h" |
| 33 #include "scopes.h" | 33 #include "scopes.h" |
| 34 #include "string-stream.h" | 34 #include "string-stream.h" |
| 35 #include "stub-cache.h" | |
| 36 | 35 |
| 37 namespace v8 { | 36 namespace v8 { |
| 38 namespace internal { | 37 namespace internal { |
| 39 | 38 |
| 40 unsigned AstNode::current_id_ = 0; | 39 unsigned AstNode::current_id_ = 0; |
| 41 unsigned AstNode::count_ = 0; | 40 unsigned AstNode::count_ = 0; |
| 42 VariableProxySentinel VariableProxySentinel::this_proxy_(true); | 41 VariableProxySentinel VariableProxySentinel::this_proxy_(true); |
| 43 VariableProxySentinel VariableProxySentinel::identifier_proxy_(false); | 42 VariableProxySentinel VariableProxySentinel::identifier_proxy_(false); |
| 44 ValidLeftHandSideSentinel ValidLeftHandSideSentinel::instance_; | 43 ValidLeftHandSideSentinel ValidLeftHandSideSentinel::instance_; |
| 45 Property Property::this_property_(VariableProxySentinel::this_proxy(), NULL, 0); | 44 Property Property::this_property_(VariableProxySentinel::this_proxy(), NULL, 0); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 } | 158 } |
| 160 return Token::ILLEGAL; | 159 return Token::ILLEGAL; |
| 161 } | 160 } |
| 162 | 161 |
| 163 | 162 |
| 164 bool FunctionLiteral::AllowsLazyCompilation() { | 163 bool FunctionLiteral::AllowsLazyCompilation() { |
| 165 return scope()->AllowsLazyCompilation(); | 164 return scope()->AllowsLazyCompilation(); |
| 166 } | 165 } |
| 167 | 166 |
| 168 | 167 |
| 169 bool FunctionLiteral::AllowOptimize() { | |
| 170 // We can't deal with heap-allocated locals. | |
| 171 return scope()->num_heap_slots() == 0; | |
| 172 } | |
| 173 | |
| 174 | |
| 175 ObjectLiteral::Property::Property(Literal* key, Expression* value) { | 168 ObjectLiteral::Property::Property(Literal* key, Expression* value) { |
| 176 emit_store_ = true; | 169 emit_store_ = true; |
| 177 key_ = key; | 170 key_ = key; |
| 178 value_ = value; | 171 value_ = value; |
| 179 Object* k = *key->handle(); | 172 Object* k = *key->handle(); |
| 180 if (k->IsSymbol() && Heap::Proto_symbol()->Equals(String::cast(k))) { | 173 if (k->IsSymbol() && Heap::Proto_symbol()->Equals(String::cast(k))) { |
| 181 kind_ = PROTOTYPE; | 174 kind_ = PROTOTYPE; |
| 182 } else if (value_->AsMaterializedLiteral() != NULL) { | 175 } else if (value_->AsMaterializedLiteral() != NULL) { |
| 183 kind_ = MATERIALIZED_LITERAL; | 176 kind_ = MATERIALIZED_LITERAL; |
| 184 } else if (value_->AsLiteral() != NULL) { | 177 } else if (value_->AsLiteral() != NULL) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 208 emit_store_ = emit_store; | 201 emit_store_ = emit_store; |
| 209 } | 202 } |
| 210 | 203 |
| 211 | 204 |
| 212 bool ObjectLiteral::Property::emit_store() { | 205 bool ObjectLiteral::Property::emit_store() { |
| 213 return emit_store_; | 206 return emit_store_; |
| 214 } | 207 } |
| 215 | 208 |
| 216 | 209 |
| 217 bool IsEqualString(void* first, void* second) { | 210 bool IsEqualString(void* first, void* second) { |
| 211 ASSERT((*reinterpret_cast<String**>(first))->IsString()); |
| 212 ASSERT((*reinterpret_cast<String**>(second))->IsString()); |
| 218 Handle<String> h1(reinterpret_cast<String**>(first)); | 213 Handle<String> h1(reinterpret_cast<String**>(first)); |
| 219 Handle<String> h2(reinterpret_cast<String**>(second)); | 214 Handle<String> h2(reinterpret_cast<String**>(second)); |
| 220 return (*h1)->Equals(*h2); | 215 return (*h1)->Equals(*h2); |
| 221 } | 216 } |
| 222 | 217 |
| 223 bool IsEqualSmi(void* first, void* second) { | 218 |
| 224 Handle<Smi> h1(reinterpret_cast<Smi**>(first)); | 219 bool IsEqualNumber(void* first, void* second) { |
| 225 Handle<Smi> h2(reinterpret_cast<Smi**>(second)); | 220 ASSERT((*reinterpret_cast<Object**>(first))->IsNumber()); |
| 226 return (*h1)->value() == (*h2)->value(); | 221 ASSERT((*reinterpret_cast<Object**>(second))->IsNumber()); |
| 222 |
| 223 Handle<Object> h1(reinterpret_cast<Object**>(first)); |
| 224 Handle<Object> h2(reinterpret_cast<Object**>(second)); |
| 225 if (h1->IsSmi()) { |
| 226 return h2->IsSmi() && *h1 == *h2; |
| 227 } |
| 228 if (h2->IsSmi()) return false; |
| 229 Handle<HeapNumber> n1 = Handle<HeapNumber>::cast(h1); |
| 230 Handle<HeapNumber> n2 = Handle<HeapNumber>::cast(h2); |
| 231 ASSERT(isfinite(n1->value())); |
| 232 ASSERT(isfinite(n2->value())); |
| 233 return n1->value() == n2->value(); |
| 227 } | 234 } |
| 228 | 235 |
| 236 |
| 229 void ObjectLiteral::CalculateEmitStore() { | 237 void ObjectLiteral::CalculateEmitStore() { |
| 230 HashMap properties(&IsEqualString); | 238 HashMap properties(&IsEqualString); |
| 231 HashMap elements(&IsEqualSmi); | 239 HashMap elements(&IsEqualNumber); |
| 232 for (int i = this->properties()->length() - 1; i >= 0; i--) { | 240 for (int i = this->properties()->length() - 1; i >= 0; i--) { |
| 233 ObjectLiteral::Property* property = this->properties()->at(i); | 241 ObjectLiteral::Property* property = this->properties()->at(i); |
| 234 Literal* literal = property->key(); | 242 Literal* literal = property->key(); |
| 235 Handle<Object> handle = literal->handle(); | 243 Handle<Object> handle = literal->handle(); |
| 236 | 244 |
| 237 if (handle->IsNull()) { | 245 if (handle->IsNull()) { |
| 238 continue; | 246 continue; |
| 239 } | 247 } |
| 240 | 248 |
| 241 uint32_t hash; | 249 uint32_t hash; |
| 242 HashMap* table; | 250 HashMap* table; |
| 243 void* key; | 251 void* key; |
| 244 uint32_t index; | |
| 245 if (handle->IsSymbol()) { | 252 if (handle->IsSymbol()) { |
| 246 Handle<String> name(String::cast(*handle)); | 253 Handle<String> name(String::cast(*handle)); |
| 247 ASSERT(!name->AsArrayIndex(&index)); | 254 if (name->AsArrayIndex(&hash)) { |
| 248 key = name.location(); | 255 Handle<Object> key_handle = Factory::NewNumberFromUint(hash); |
| 249 hash = name->Hash(); | 256 key = key_handle.location(); |
| 250 table = &properties; | 257 table = &elements; |
| 251 } else if (handle->ToArrayIndex(&index)) { | 258 } else { |
| 259 key = name.location(); |
| 260 hash = name->Hash(); |
| 261 table = &properties; |
| 262 } |
| 263 } else if (handle->ToArrayIndex(&hash)) { |
| 252 key = handle.location(); | 264 key = handle.location(); |
| 253 hash = index; | |
| 254 table = &elements; | 265 table = &elements; |
| 255 } else { | 266 } else { |
| 256 ASSERT(handle->IsNumber()); | 267 ASSERT(handle->IsNumber()); |
| 257 double num = handle->Number(); | 268 double num = handle->Number(); |
| 258 char arr[100]; | 269 char arr[100]; |
| 259 Vector<char> buffer(arr, ARRAY_SIZE(arr)); | 270 Vector<char> buffer(arr, ARRAY_SIZE(arr)); |
| 260 const char* str = DoubleToCString(num, buffer); | 271 const char* str = DoubleToCString(num, buffer); |
| 261 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str)); | 272 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str)); |
| 262 key = name.location(); | 273 key = name.location(); |
| 263 hash = name->Hash(); | 274 hash = name->Hash(); |
| 264 table = &properties; | 275 table = &properties; |
| 265 } | 276 } |
| 266 // If the key of a computed property is in the table, do not emit | 277 // If the key of a computed property is in the table, do not emit |
| 267 // a store for the property later. | 278 // a store for the property later. |
| 268 if (property->kind() == ObjectLiteral::Property::COMPUTED) { | 279 if (property->kind() == ObjectLiteral::Property::COMPUTED) { |
| 269 if (table->Lookup(literal, hash, false) != NULL) { | 280 if (table->Lookup(key, hash, false) != NULL) { |
| 270 property->set_emit_store(false); | 281 property->set_emit_store(false); |
| 271 } | 282 } |
| 272 } | 283 } |
| 273 // Add key to the table. | 284 // Add key to the table. |
| 274 table->Lookup(literal, hash, true); | 285 table->Lookup(key, hash, true); |
| 275 } | 286 } |
| 276 } | 287 } |
| 277 | 288 |
| 278 | 289 |
| 279 void TargetCollector::AddTarget(BreakTarget* target) { | 290 void TargetCollector::AddTarget(BreakTarget* target) { |
| 280 // Add the label to the collector, but discard duplicates. | 291 // Add the label to the collector, but discard duplicates. |
| 281 int length = targets_->length(); | 292 int length = targets_->length(); |
| 282 for (int i = 0; i < length; i++) { | 293 for (int i = 0; i < length; i++) { |
| 283 if (targets_->at(i) == target) return; | 294 if (targets_->at(i) == target) return; |
| 284 } | 295 } |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 510 | 521 |
| 511 // ---------------------------------------------------------------------------- | 522 // ---------------------------------------------------------------------------- |
| 512 // Recording of type feedback | 523 // Recording of type feedback |
| 513 | 524 |
| 514 void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) { | 525 void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) { |
| 515 // Record type feedback from the oracle in the AST. | 526 // Record type feedback from the oracle in the AST. |
| 516 is_monomorphic_ = oracle->LoadIsMonomorphic(this); | 527 is_monomorphic_ = oracle->LoadIsMonomorphic(this); |
| 517 if (key()->IsPropertyName()) { | 528 if (key()->IsPropertyName()) { |
| 518 if (oracle->LoadIsBuiltin(this, Builtins::LoadIC_ArrayLength)) { | 529 if (oracle->LoadIsBuiltin(this, Builtins::LoadIC_ArrayLength)) { |
| 519 is_array_length_ = true; | 530 is_array_length_ = true; |
| 531 } else if (oracle->LoadIsBuiltin(this, Builtins::LoadIC_StringLength)) { |
| 532 is_string_length_ = true; |
| 520 } else if (oracle->LoadIsBuiltin(this, | 533 } else if (oracle->LoadIsBuiltin(this, |
| 521 Builtins::LoadIC_FunctionPrototype)) { | 534 Builtins::LoadIC_FunctionPrototype)) { |
| 522 is_function_prototype_ = true; | 535 is_function_prototype_ = true; |
| 523 } else { | 536 } else { |
| 524 Literal* lit_key = key()->AsLiteral(); | 537 Literal* lit_key = key()->AsLiteral(); |
| 525 ASSERT(lit_key != NULL && lit_key->handle()->IsString()); | 538 ASSERT(lit_key != NULL && lit_key->handle()->IsString()); |
| 526 Handle<String> name = Handle<String>::cast(lit_key->handle()); | 539 Handle<String> name = Handle<String>::cast(lit_key->handle()); |
| 527 ZoneMapList* types = oracle->LoadReceiverTypes(this, name); | 540 ZoneMapList* types = oracle->LoadReceiverTypes(this, name); |
| 528 receiver_types_ = types; | 541 receiver_types_ = types; |
| 529 } | 542 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 555 if (info.IsSmi()) { | 568 if (info.IsSmi()) { |
| 556 compare_type_ = SMI_ONLY; | 569 compare_type_ = SMI_ONLY; |
| 557 } else if (info.IsNonPrimitive()) { | 570 } else if (info.IsNonPrimitive()) { |
| 558 compare_type_ = OBJECT_ONLY; | 571 compare_type_ = OBJECT_ONLY; |
| 559 } else { | 572 } else { |
| 560 ASSERT(compare_type_ == NONE); | 573 ASSERT(compare_type_ == NONE); |
| 561 } | 574 } |
| 562 } | 575 } |
| 563 | 576 |
| 564 | 577 |
| 565 static bool CallWithoutIC(Handle<JSFunction> target, int arity) { | 578 static bool CanCallWithoutIC(Handle<JSFunction> target, int arity) { |
| 566 SharedFunctionInfo* info = target->shared(); | 579 SharedFunctionInfo* info = target->shared(); |
| 567 if (target->NeedsArgumentsAdaption()) { | 580 // If the number of formal parameters of the target function does |
| 568 // If the number of formal parameters of the target function | 581 // not match the number of arguments we're passing, we don't want to |
| 569 // does not match the number of arguments we're passing, we | 582 // deal with it. Otherwise, we can call it directly. |
| 570 // don't want to deal with it. | 583 return !target->NeedsArgumentsAdaption() || |
| 571 return info->formal_parameter_count() == arity; | 584 info->formal_parameter_count() == arity; |
| 572 } else { | |
| 573 // If the target doesn't need arguments adaption, we can call | |
| 574 // it directly, but we avoid to do so if it has a custom call | |
| 575 // generator, because that is likely to generate better code. | |
| 576 return !info->HasBuiltinFunctionId() || | |
| 577 !CallStubCompiler::HasCustomCallGenerator(info->builtin_function_id()); | |
| 578 } | |
| 579 } | 585 } |
| 580 | 586 |
| 581 | 587 |
| 582 bool Call::ComputeTarget(Handle<Map> type, Handle<String> name) { | 588 bool Call::ComputeTarget(Handle<Map> type, Handle<String> name) { |
| 583 holder_ = Handle<JSObject>::null(); | 589 if (check_type_ == RECEIVER_MAP_CHECK) { |
| 590 // For primitive checks the holder is set up to point to the |
| 591 // corresponding prototype object, i.e. one step of the algorithm |
| 592 // below has been already performed. |
| 593 // For non-primitive checks we clear it to allow computing targets |
| 594 // for polymorphic calls. |
| 595 holder_ = Handle<JSObject>::null(); |
| 596 } |
| 584 while (true) { | 597 while (true) { |
| 585 LookupResult lookup; | 598 LookupResult lookup; |
| 586 type->LookupInDescriptors(NULL, *name, &lookup); | 599 type->LookupInDescriptors(NULL, *name, &lookup); |
| 587 // If the function wasn't found directly in the map, we start | 600 // If the function wasn't found directly in the map, we start |
| 588 // looking upwards through the prototype chain. | 601 // looking upwards through the prototype chain. |
| 589 if (!lookup.IsFound() && type->prototype()->IsJSObject()) { | 602 if (!lookup.IsFound() && type->prototype()->IsJSObject()) { |
| 590 holder_ = Handle<JSObject>(JSObject::cast(type->prototype())); | 603 holder_ = Handle<JSObject>(JSObject::cast(type->prototype())); |
| 591 type = Handle<Map>(holder()->map()); | 604 type = Handle<Map>(holder()->map()); |
| 592 } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) { | 605 } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) { |
| 593 target_ = Handle<JSFunction>(lookup.GetConstantFunctionFromMap(*type)); | 606 target_ = Handle<JSFunction>(lookup.GetConstantFunctionFromMap(*type)); |
| 594 return CallWithoutIC(target_, arguments()->length()); | 607 return CanCallWithoutIC(target_, arguments()->length()); |
| 595 } else { | 608 } else { |
| 596 return false; | 609 return false; |
| 597 } | 610 } |
| 598 } | 611 } |
| 599 } | 612 } |
| 600 | 613 |
| 601 | 614 |
| 602 bool Call::ComputeGlobalTarget(Handle<GlobalObject> global, | 615 bool Call::ComputeGlobalTarget(Handle<GlobalObject> global, |
| 603 Handle<String> name) { | 616 Handle<String> name) { |
| 604 target_ = Handle<JSFunction>::null(); | 617 target_ = Handle<JSFunction>::null(); |
| 605 cell_ = Handle<JSGlobalPropertyCell>::null(); | 618 cell_ = Handle<JSGlobalPropertyCell>::null(); |
| 606 LookupResult lookup; | 619 LookupResult lookup; |
| 607 global->Lookup(*name, &lookup); | 620 global->Lookup(*name, &lookup); |
| 608 if (lookup.IsProperty() && lookup.type() == NORMAL) { | 621 if (lookup.IsProperty() && |
| 622 lookup.type() == NORMAL && |
| 623 lookup.holder() == *global) { |
| 609 cell_ = Handle<JSGlobalPropertyCell>(global->GetPropertyCell(&lookup)); | 624 cell_ = Handle<JSGlobalPropertyCell>(global->GetPropertyCell(&lookup)); |
| 610 if (cell_->value()->IsJSFunction()) { | 625 if (cell_->value()->IsJSFunction()) { |
| 611 Handle<JSFunction> candidate(JSFunction::cast(cell_->value())); | 626 Handle<JSFunction> candidate(JSFunction::cast(cell_->value())); |
| 612 // If the function is in new space we assume it's more likely to | 627 // If the function is in new space we assume it's more likely to |
| 613 // change and thus prefer the general IC code. | 628 // change and thus prefer the general IC code. |
| 614 if (!Heap::InNewSpace(*candidate) | 629 if (!Heap::InNewSpace(*candidate) && |
| 615 && CallWithoutIC(candidate, arguments()->length())) { | 630 CanCallWithoutIC(candidate, arguments()->length())) { |
| 616 target_ = candidate; | 631 target_ = candidate; |
| 617 return true; | 632 return true; |
| 618 } | 633 } |
| 619 } | 634 } |
| 620 } | 635 } |
| 621 return false; | 636 return false; |
| 622 } | 637 } |
| 623 | 638 |
| 624 | 639 |
| 625 void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle) { | 640 void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle) { |
| 626 Property* property = expression()->AsProperty(); | 641 Property* property = expression()->AsProperty(); |
| 627 ASSERT(property != NULL); | 642 ASSERT(property != NULL); |
| 628 // Specialize for the receiver types seen at runtime. | 643 // Specialize for the receiver types seen at runtime. |
| 629 Literal* key = property->key()->AsLiteral(); | 644 Literal* key = property->key()->AsLiteral(); |
| 630 ASSERT(key != NULL && key->handle()->IsString()); | 645 ASSERT(key != NULL && key->handle()->IsString()); |
| 631 Handle<String> name = Handle<String>::cast(key->handle()); | 646 Handle<String> name = Handle<String>::cast(key->handle()); |
| 632 receiver_types_ = oracle->CallReceiverTypes(this, name); | 647 receiver_types_ = oracle->CallReceiverTypes(this, name); |
| 633 #ifdef DEBUG | 648 #ifdef DEBUG |
| 634 if (FLAG_enable_slow_asserts) { | 649 if (FLAG_enable_slow_asserts) { |
| 635 if (receiver_types_ != NULL) { | 650 if (receiver_types_ != NULL) { |
| 636 int length = receiver_types_->length(); | 651 int length = receiver_types_->length(); |
| 637 for (int i = 0; i < length; i++) { | 652 for (int i = 0; i < length; i++) { |
| 638 Handle<Map> map = receiver_types_->at(i); | 653 Handle<Map> map = receiver_types_->at(i); |
| 639 ASSERT(!map.is_null() && *map != NULL); | 654 ASSERT(!map.is_null() && *map != NULL); |
| 640 } | 655 } |
| 641 } | 656 } |
| 642 } | 657 } |
| 643 #endif | 658 #endif |
| 644 if (receiver_types_ != NULL && receiver_types_->length() > 0) { | 659 is_monomorphic_ = oracle->CallIsMonomorphic(this); |
| 645 Handle<Map> type = receiver_types_->at(0); | 660 check_type_ = oracle->GetCallCheckType(this); |
| 646 is_monomorphic_ = oracle->CallIsMonomorphic(this); | 661 if (is_monomorphic_) { |
| 647 if (is_monomorphic_) is_monomorphic_ = ComputeTarget(type, name); | 662 Handle<Map> map; |
| 663 if (receiver_types_ != NULL && receiver_types_->length() > 0) { |
| 664 ASSERT(check_type_ == RECEIVER_MAP_CHECK); |
| 665 map = receiver_types_->at(0); |
| 666 } else { |
| 667 ASSERT(check_type_ != RECEIVER_MAP_CHECK); |
| 668 holder_ = Handle<JSObject>( |
| 669 oracle->GetPrototypeForPrimitiveCheck(check_type_)); |
| 670 map = Handle<Map>(holder_->map()); |
| 671 } |
| 672 is_monomorphic_ = ComputeTarget(map, name); |
| 648 } | 673 } |
| 649 } | 674 } |
| 650 | 675 |
| 651 | 676 |
| 652 void BinaryOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) { | |
| 653 TypeInfo left = oracle->BinaryType(this, TypeFeedbackOracle::LEFT); | |
| 654 TypeInfo right = oracle->BinaryType(this, TypeFeedbackOracle::RIGHT); | |
| 655 is_smi_only_ = left.IsSmi() && right.IsSmi(); | |
| 656 } | |
| 657 | |
| 658 | |
| 659 void CompareOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) { | 677 void CompareOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) { |
| 660 TypeInfo left = oracle->CompareType(this, TypeFeedbackOracle::LEFT); | 678 TypeInfo info = oracle->CompareType(this); |
| 661 TypeInfo right = oracle->CompareType(this, TypeFeedbackOracle::RIGHT); | 679 if (info.IsSmi()) { |
| 662 if (left.IsSmi() && right.IsSmi()) { | |
| 663 compare_type_ = SMI_ONLY; | 680 compare_type_ = SMI_ONLY; |
| 664 } else if (left.IsNonPrimitive() && right.IsNonPrimitive()) { | 681 } else if (info.IsNonPrimitive()) { |
| 665 compare_type_ = OBJECT_ONLY; | 682 compare_type_ = OBJECT_ONLY; |
| 666 } else { | 683 } else { |
| 667 ASSERT(compare_type_ == NONE); | 684 ASSERT(compare_type_ == NONE); |
| 668 } | 685 } |
| 669 } | 686 } |
| 670 | 687 |
| 671 | 688 |
| 672 // ---------------------------------------------------------------------------- | 689 // ---------------------------------------------------------------------------- |
| 673 // Implementation of AstVisitor | 690 // Implementation of AstVisitor |
| 674 | 691 |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1041 | 1058 |
| 1042 CaseClause::CaseClause(Expression* label, | 1059 CaseClause::CaseClause(Expression* label, |
| 1043 ZoneList<Statement*>* statements, | 1060 ZoneList<Statement*>* statements, |
| 1044 int pos) | 1061 int pos) |
| 1045 : label_(label), | 1062 : label_(label), |
| 1046 statements_(statements), | 1063 statements_(statements), |
| 1047 position_(pos), | 1064 position_(pos), |
| 1048 compare_type_(NONE) {} | 1065 compare_type_(NONE) {} |
| 1049 | 1066 |
| 1050 } } // namespace v8::internal | 1067 } } // namespace v8::internal |
| OLD | NEW |