| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 #ifdef DEBUG | 141 #ifdef DEBUG |
| 142 StackFrameIterator it(isolate); | 142 StackFrameIterator it(isolate); |
| 143 for (int i = 0; i < depth + 1; i++) it.Advance(); | 143 for (int i = 0; i < depth + 1; i++) it.Advance(); |
| 144 StackFrame* frame = it.frame(); | 144 StackFrame* frame = it.frame(); |
| 145 ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); | 145 ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); |
| 146 #endif | 146 #endif |
| 147 fp_ = fp; | 147 fp_ = fp; |
| 148 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); | 148 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); |
| 149 target_ = handle(raw_target(), isolate); | 149 target_ = handle(raw_target(), isolate); |
| 150 state_ = target_->ic_state(); | 150 state_ = target_->ic_state(); |
| 151 extra_ic_state_ = target_->needs_extended_extra_ic_state(target_->kind()) |
| 152 ? target_->extended_extra_ic_state() |
| 153 : target_->extra_ic_state(); |
| 151 } | 154 } |
| 152 | 155 |
| 153 | 156 |
| 154 #ifdef ENABLE_DEBUGGER_SUPPORT | 157 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 155 Address IC::OriginalCodeAddress() const { | 158 Address IC::OriginalCodeAddress() const { |
| 156 HandleScope scope(isolate()); | 159 HandleScope scope(isolate()); |
| 157 // Compute the JavaScript frame for the frame pointer of this IC | 160 // Compute the JavaScript frame for the frame pointer of this IC |
| 158 // structure. We need this to be able to find the function | 161 // structure. We need this to be able to find the function |
| 159 // corresponding to the frame. | 162 // corresponding to the frame. |
| 160 StackFrameIterator it(isolate()); | 163 StackFrameIterator it(isolate()); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 if (object->IsString()) { | 251 if (object->IsString()) { |
| 249 String* string = String::cast(*object); | 252 String* string = String::cast(*object); |
| 250 // Check there's the right string value or wrapper in the receiver slot. | 253 // Check there's the right string value or wrapper in the receiver slot. |
| 251 ASSERT(string == args[0] || string == JSValue::cast(args[0])->value()); | 254 ASSERT(string == args[0] || string == JSValue::cast(args[0])->value()); |
| 252 // If we're in the default (fastest) state and the index is | 255 // If we're in the default (fastest) state and the index is |
| 253 // out of bounds, update the state to record this fact. | 256 // out of bounds, update the state to record this fact. |
| 254 if (StringStubState::decode(extra_ic_state()) == DEFAULT_STRING_STUB && | 257 if (StringStubState::decode(extra_ic_state()) == DEFAULT_STRING_STUB && |
| 255 argc >= 1 && args[1]->IsNumber()) { | 258 argc >= 1 && args[1]->IsNumber()) { |
| 256 double index = DoubleToInteger(args.number_at(1)); | 259 double index = DoubleToInteger(args.number_at(1)); |
| 257 if (index < 0 || index >= string->length()) { | 260 if (index < 0 || index >= string->length()) { |
| 258 extra_ic_state_ = | 261 set_extra_ic_state(StringStubState::update(extra_ic_state(), |
| 259 StringStubState::update(extra_ic_state(), | 262 STRING_INDEX_OUT_OF_BOUNDS)); |
| 260 STRING_INDEX_OUT_OF_BOUNDS); | |
| 261 return true; | 263 return true; |
| 262 } | 264 } |
| 263 } | 265 } |
| 264 } | 266 } |
| 265 break; | 267 break; |
| 266 default: | 268 default: |
| 267 return false; | 269 return false; |
| 268 } | 270 } |
| 269 return false; | 271 return false; |
| 270 } | 272 } |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 // The builtins object is special. It only changes when JavaScript | 393 // The builtins object is special. It only changes when JavaScript |
| 392 // builtins are loaded lazily. It is important to keep inline | 394 // builtins are loaded lazily. It is important to keep inline |
| 393 // caches for the builtins object monomorphic. Therefore, if we get | 395 // caches for the builtins object monomorphic. Therefore, if we get |
| 394 // an inline cache miss for the builtins object after lazily loading | 396 // an inline cache miss for the builtins object after lazily loading |
| 395 // JavaScript builtins, we return uninitialized as the state to | 397 // JavaScript builtins, we return uninitialized as the state to |
| 396 // force the inline cache back to monomorphic state. | 398 // force the inline cache back to monomorphic state. |
| 397 if (receiver->IsJSBuiltinsObject()) state_ = UNINITIALIZED; | 399 if (receiver->IsJSBuiltinsObject()) state_ = UNINITIALIZED; |
| 398 } | 400 } |
| 399 | 401 |
| 400 | 402 |
| 401 RelocInfo::Mode IC::ComputeMode() { | |
| 402 Address addr = address(); | |
| 403 Code* code = Code::cast(isolate()->FindCodeObject(addr)); | |
| 404 for (RelocIterator it(code, RelocInfo::kCodeTargetMask); | |
| 405 !it.done(); it.next()) { | |
| 406 RelocInfo* info = it.rinfo(); | |
| 407 if (info->pc() == addr) return info->rmode(); | |
| 408 } | |
| 409 UNREACHABLE(); | |
| 410 return RelocInfo::NONE32; | |
| 411 } | |
| 412 | |
| 413 | |
| 414 Failure* IC::TypeError(const char* type, | 403 Failure* IC::TypeError(const char* type, |
| 415 Handle<Object> object, | 404 Handle<Object> object, |
| 416 Handle<Object> key) { | 405 Handle<Object> key) { |
| 417 HandleScope scope(isolate()); | 406 HandleScope scope(isolate()); |
| 418 Handle<Object> args[2] = { key, object }; | 407 Handle<Object> args[2] = { key, object }; |
| 419 Handle<Object> error = isolate()->factory()->NewTypeError( | 408 Handle<Object> error = isolate()->factory()->NewTypeError( |
| 420 type, HandleVector(args, 2)); | 409 type, HandleVector(args, 2)); |
| 421 return isolate()->Throw(*error); | 410 return isolate()->Throw(*error); |
| 422 } | 411 } |
| 423 | 412 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 // Clearing these is tricky and does not | 482 // Clearing these is tricky and does not |
| 494 // make any performance difference. | 483 // make any performance difference. |
| 495 return; | 484 return; |
| 496 default: UNREACHABLE(); | 485 default: UNREACHABLE(); |
| 497 } | 486 } |
| 498 } | 487 } |
| 499 | 488 |
| 500 | 489 |
| 501 void CallICBase::Clear(Address address, Code* target) { | 490 void CallICBase::Clear(Address address, Code* target) { |
| 502 if (IsCleared(target)) return; | 491 if (IsCleared(target)) return; |
| 503 bool contextual = CallICBase::Contextual::decode(target->extra_ic_state()); | 492 ContextualMode mode = IC::GetContextualMode(target->extra_ic_state()); |
| 504 Code* code = | 493 Code* code = target->GetIsolate()->stub_cache()->FindCallInitialize( |
| 505 target->GetIsolate()->stub_cache()->FindCallInitialize( | 494 target->arguments_count(), mode, target->kind()); |
| 506 target->arguments_count(), | |
| 507 contextual ? RelocInfo::CODE_TARGET_CONTEXT : RelocInfo::CODE_TARGET, | |
| 508 target->kind()); | |
| 509 SetTargetAtAddress(address, code); | 495 SetTargetAtAddress(address, code); |
| 510 } | 496 } |
| 511 | 497 |
| 512 | 498 |
| 513 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) { | 499 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) { |
| 514 if (IsCleared(target)) return; | 500 if (IsCleared(target)) return; |
| 515 // Make sure to also clear the map used in inline fast cases. If we | 501 // Make sure to also clear the map used in inline fast cases. If we |
| 516 // do not clear these maps, cached code can keep objects alive | 502 // do not clear these maps, cached code can keep objects alive |
| 517 // through the embedded maps. | 503 // through the embedded maps. |
| 518 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); | 504 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); |
| 519 } | 505 } |
| 520 | 506 |
| 521 | 507 |
| 522 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) { | 508 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) { |
| 523 if (IsCleared(target)) return; | 509 if (IsCleared(target)) return; |
| 524 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); | 510 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( |
| 511 Code::LOAD_IC, target->extra_ic_state()); |
| 512 SetTargetAtAddress(address, code); |
| 525 } | 513 } |
| 526 | 514 |
| 527 | 515 |
| 528 void StoreIC::Clear(Isolate* isolate, Address address, Code* target) { | 516 void StoreIC::Clear(Isolate* isolate, Address address, Code* target) { |
| 529 if (IsCleared(target)) return; | 517 if (IsCleared(target)) return; |
| 530 SetTargetAtAddress(address, | 518 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( |
| 531 *pre_monomorphic_stub( | 519 Code::STORE_IC, target->extra_ic_state()); |
| 532 isolate, StoreIC::GetStrictMode(target->extra_ic_state()))); | 520 SetTargetAtAddress(address, code); |
| 533 } | 521 } |
| 534 | 522 |
| 535 | 523 |
| 536 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target) { | 524 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target) { |
| 537 if (IsCleared(target)) return; | 525 if (IsCleared(target)) return; |
| 538 SetTargetAtAddress(address, | 526 SetTargetAtAddress(address, |
| 539 *pre_monomorphic_stub( | 527 *pre_monomorphic_stub( |
| 540 isolate, StoreIC::GetStrictMode(target->extra_ic_state()))); | 528 isolate, StoreIC::GetStrictMode(target->extra_ic_state()))); |
| 541 } | 529 } |
| 542 | 530 |
| (...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1002 } | 990 } |
| 1003 | 991 |
| 1004 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( | 992 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( |
| 1005 &types, &handlers, number_of_valid_types, name, extra_ic_state()); | 993 &types, &handlers, number_of_valid_types, name, extra_ic_state()); |
| 1006 set_target(*ic); | 994 set_target(*ic); |
| 1007 return true; | 995 return true; |
| 1008 } | 996 } |
| 1009 | 997 |
| 1010 | 998 |
| 1011 Handle<Type> IC::CurrentTypeOf(Handle<Object> object, Isolate* isolate) { | 999 Handle<Type> IC::CurrentTypeOf(Handle<Object> object, Isolate* isolate) { |
| 1012 Type* type = object->IsJSGlobalObject() | 1000 return object->IsJSGlobalObject() |
| 1013 ? Type::Constant(Handle<JSGlobalObject>::cast(object)) | 1001 ? Type::Constant(Handle<JSGlobalObject>::cast(object), isolate) |
| 1014 : Type::OfCurrently(object); | 1002 : Type::OfCurrently(object, isolate); |
| 1015 return handle(type, isolate); | |
| 1016 } | 1003 } |
| 1017 | 1004 |
| 1018 | 1005 |
| 1019 Handle<Map> IC::TypeToMap(Type* type, Isolate* isolate) { | 1006 Handle<Map> IC::TypeToMap(Type* type, Isolate* isolate) { |
| 1020 if (type->Is(Type::Number())) return isolate->factory()->heap_number_map(); | 1007 if (type->Is(Type::Number())) return isolate->factory()->heap_number_map(); |
| 1021 if (type->Is(Type::Boolean())) return isolate->factory()->oddball_map(); | 1008 if (type->Is(Type::Boolean())) return isolate->factory()->oddball_map(); |
| 1022 if (type->IsConstant()) { | 1009 if (type->IsConstant()) { |
| 1023 return handle(Handle<JSGlobalObject>::cast(type->AsConstant())->map()); | 1010 return handle(Handle<JSGlobalObject>::cast(type->AsConstant())->map()); |
| 1024 } | 1011 } |
| 1025 ASSERT(type->IsClass()); | 1012 ASSERT(type->IsClass()); |
| 1026 return type->AsClass(); | 1013 return type->AsClass(); |
| 1027 } | 1014 } |
| 1028 | 1015 |
| 1029 | 1016 |
| 1030 Type* IC::MapToType(Handle<Map> map) { | 1017 Handle<Type> IC::MapToType(Handle<Map> map) { |
| 1031 if (map->instance_type() == HEAP_NUMBER_TYPE) return Type::Number(); | 1018 Isolate* isolate = map->GetIsolate(); |
| 1019 if (map->instance_type() == HEAP_NUMBER_TYPE) return Type::Number(isolate); |
| 1032 // The only oddballs that can be recorded in ICs are booleans. | 1020 // The only oddballs that can be recorded in ICs are booleans. |
| 1033 if (map->instance_type() == ODDBALL_TYPE) return Type::Boolean(); | 1021 if (map->instance_type() == ODDBALL_TYPE) return Type::Boolean(isolate); |
| 1034 return Type::Class(map); | 1022 return Type::Class(map, isolate); |
| 1035 } | 1023 } |
| 1036 | 1024 |
| 1037 | 1025 |
| 1038 void IC::UpdateMonomorphicIC(Handle<Type> type, | 1026 void IC::UpdateMonomorphicIC(Handle<Type> type, |
| 1039 Handle<Code> handler, | 1027 Handle<Code> handler, |
| 1040 Handle<String> name) { | 1028 Handle<String> name) { |
| 1041 if (!handler->is_handler()) return set_target(*handler); | 1029 if (!handler->is_handler()) return set_target(*handler); |
| 1042 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( | 1030 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( |
| 1043 name, type, handler, extra_ic_state()); | 1031 name, type, handler, extra_ic_state()); |
| 1044 set_target(*ic); | 1032 set_target(*ic); |
| 1045 } | 1033 } |
| 1046 | 1034 |
| 1047 | 1035 |
| 1048 void IC::CopyICToMegamorphicCache(Handle<String> name) { | 1036 void IC::CopyICToMegamorphicCache(Handle<String> name) { |
| 1049 TypeHandleList types; | 1037 TypeHandleList types; |
| 1050 CodeHandleList handlers; | 1038 CodeHandleList handlers; |
| 1051 target()->FindAllTypes(&types); | 1039 target()->FindAllTypes(&types); |
| 1052 if (!target()->FindHandlers(&handlers, types.length())) return; | 1040 if (!target()->FindHandlers(&handlers, types.length())) return; |
| 1053 for (int i = 0; i < types.length(); i++) { | 1041 for (int i = 0; i < types.length(); i++) { |
| 1054 UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i)); | 1042 UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i)); |
| 1055 } | 1043 } |
| 1056 } | 1044 } |
| 1057 | 1045 |
| 1058 | 1046 |
| 1059 bool IC::IsTransitionOfMonomorphicTarget(Type* type) { | 1047 bool IC::IsTransitionOfMonomorphicTarget(Handle<Type> type) { |
| 1060 if (!type->IsClass()) return false; | 1048 if (!type->IsClass()) return false; |
| 1061 Map* receiver_map = *type->AsClass(); | 1049 Map* receiver_map = *type->AsClass(); |
| 1062 Map* current_map = target()->FindFirstMap(); | 1050 Map* current_map = target()->FindFirstMap(); |
| 1063 ElementsKind receiver_elements_kind = receiver_map->elements_kind(); | 1051 ElementsKind receiver_elements_kind = receiver_map->elements_kind(); |
| 1064 bool more_general_transition = | 1052 bool more_general_transition = |
| 1065 IsMoreGeneralElementsKindTransition( | 1053 IsMoreGeneralElementsKindTransition( |
| 1066 current_map->elements_kind(), receiver_elements_kind); | 1054 current_map->elements_kind(), receiver_elements_kind); |
| 1067 Map* transitioned_map = more_general_transition | 1055 Map* transitioned_map = more_general_transition |
| 1068 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) | 1056 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) |
| 1069 : NULL; | 1057 : NULL; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1081 case MONOMORPHIC_PROTOTYPE_FAILURE: | 1069 case MONOMORPHIC_PROTOTYPE_FAILURE: |
| 1082 UpdateMonomorphicIC(type, code, name); | 1070 UpdateMonomorphicIC(type, code, name); |
| 1083 break; | 1071 break; |
| 1084 case MONOMORPHIC: { | 1072 case MONOMORPHIC: { |
| 1085 // For now, call stubs are allowed to rewrite to the same stub. This | 1073 // For now, call stubs are allowed to rewrite to the same stub. This |
| 1086 // happens e.g., when the field does not contain a function. | 1074 // happens e.g., when the field does not contain a function. |
| 1087 ASSERT(target()->is_call_stub() || | 1075 ASSERT(target()->is_call_stub() || |
| 1088 target()->is_keyed_call_stub() || | 1076 target()->is_keyed_call_stub() || |
| 1089 !target().is_identical_to(code)); | 1077 !target().is_identical_to(code)); |
| 1090 Code* old_handler = target()->FindFirstHandler(); | 1078 Code* old_handler = target()->FindFirstHandler(); |
| 1091 if (old_handler == *code && IsTransitionOfMonomorphicTarget(*type)) { | 1079 if (old_handler == *code && IsTransitionOfMonomorphicTarget(type)) { |
| 1092 UpdateMonomorphicIC(type, code, name); | 1080 UpdateMonomorphicIC(type, code, name); |
| 1093 break; | 1081 break; |
| 1094 } | 1082 } |
| 1095 // Fall through. | 1083 // Fall through. |
| 1096 } | 1084 } |
| 1097 case POLYMORPHIC: | 1085 case POLYMORPHIC: |
| 1098 if (!target()->is_keyed_stub()) { | 1086 if (!target()->is_keyed_stub()) { |
| 1099 if (UpdatePolymorphicIC(type, name, code)) break; | 1087 if (UpdatePolymorphicIC(type, name, code)) break; |
| 1100 CopyICToMegamorphicCache(name); | 1088 CopyICToMegamorphicCache(name); |
| 1101 } | 1089 } |
| 1102 set_target(*megamorphic_stub()); | 1090 set_target(*megamorphic_stub()); |
| 1103 // Fall through. | 1091 // Fall through. |
| 1104 case MEGAMORPHIC: | 1092 case MEGAMORPHIC: |
| 1105 UpdateMegamorphicCache(*type, *name, *code); | 1093 UpdateMegamorphicCache(*type, *name, *code); |
| 1106 break; | 1094 break; |
| 1107 case DEBUG_STUB: | 1095 case DEBUG_STUB: |
| 1108 break; | 1096 break; |
| 1109 case GENERIC: | 1097 case GENERIC: |
| 1110 UNREACHABLE(); | 1098 UNREACHABLE(); |
| 1111 break; | 1099 break; |
| 1112 } | 1100 } |
| 1113 } | 1101 } |
| 1114 | 1102 |
| 1115 | 1103 |
| 1104 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, ContextualMode mode) { |
| 1105 Handle<Code> ic = isolate->stub_cache()->ComputeLoad( |
| 1106 UNINITIALIZED, IC::ComputeExtraICState(mode)); |
| 1107 return ic; |
| 1108 } |
| 1109 |
| 1110 |
| 1111 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, |
| 1112 ContextualMode mode) { |
| 1113 return isolate->stub_cache()->ComputeLoad( |
| 1114 PREMONOMORPHIC, IC::ComputeExtraICState(mode)); |
| 1115 } |
| 1116 |
| 1117 |
| 1118 Handle<Code> LoadIC::megamorphic_stub() { |
| 1119 return isolate()->stub_cache()->ComputeLoad( |
| 1120 MEGAMORPHIC, extra_ic_state()); |
| 1121 } |
| 1122 |
| 1123 |
| 1116 Handle<Code> LoadIC::SimpleFieldLoad(int offset, | 1124 Handle<Code> LoadIC::SimpleFieldLoad(int offset, |
| 1117 bool inobject, | 1125 bool inobject, |
| 1118 Representation representation) { | 1126 Representation representation) { |
| 1119 if (kind() == Code::LOAD_IC) { | 1127 if (kind() == Code::LOAD_IC) { |
| 1120 LoadFieldStub stub(inobject, offset, representation); | 1128 LoadFieldStub stub(inobject, offset, representation); |
| 1121 return stub.GetCode(isolate()); | 1129 return stub.GetCode(isolate()); |
| 1122 } else { | 1130 } else { |
| 1123 KeyedLoadFieldStub stub(inobject, offset, representation); | 1131 KeyedLoadFieldStub stub(inobject, offset, representation); |
| 1124 return stub.GetCode(isolate()); | 1132 return stub.GetCode(isolate()); |
| 1125 } | 1133 } |
| (...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1583 } | 1591 } |
| 1584 | 1592 |
| 1585 // Set the property. | 1593 // Set the property. |
| 1586 Handle<Object> result = JSReceiver::SetProperty( | 1594 Handle<Object> result = JSReceiver::SetProperty( |
| 1587 receiver, name, value, NONE, strict_mode(), store_mode); | 1595 receiver, name, value, NONE, strict_mode(), store_mode); |
| 1588 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1596 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1589 return *result; | 1597 return *result; |
| 1590 } | 1598 } |
| 1591 | 1599 |
| 1592 | 1600 |
| 1601 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, |
| 1602 StrictModeFlag strict_mode, |
| 1603 ContextualMode mode) { |
| 1604 ExtraICState extra_state = ComputeExtraICState(strict_mode, mode); |
| 1605 Handle<Code> ic = isolate->stub_cache()->ComputeStore( |
| 1606 UNINITIALIZED, extra_state); |
| 1607 return ic; |
| 1608 } |
| 1609 |
| 1610 |
| 1611 Handle<Code> StoreIC::megamorphic_stub() { |
| 1612 return isolate()->stub_cache()->ComputeStore(MEGAMORPHIC, extra_ic_state()); |
| 1613 } |
| 1614 |
| 1615 |
| 1616 Handle<Code> StoreIC::generic_stub() const { |
| 1617 return isolate()->stub_cache()->ComputeStore(GENERIC, extra_ic_state()); |
| 1618 } |
| 1619 |
| 1620 |
| 1621 Handle<Code> StoreIC::pre_monomorphic_stub(Isolate* isolate, |
| 1622 StrictModeFlag strict_mode, |
| 1623 ContextualMode contextual_mode) { |
| 1624 ExtraICState state = StoreIC::ComputeExtraICState(strict_mode, |
| 1625 contextual_mode); |
| 1626 return isolate->stub_cache()->ComputeStore(PREMONOMORPHIC, state); |
| 1627 } |
| 1628 |
| 1629 |
| 1593 void StoreIC::UpdateCaches(LookupResult* lookup, | 1630 void StoreIC::UpdateCaches(LookupResult* lookup, |
| 1594 Handle<JSObject> receiver, | 1631 Handle<JSObject> receiver, |
| 1595 Handle<String> name, | 1632 Handle<String> name, |
| 1596 Handle<Object> value) { | 1633 Handle<Object> value) { |
| 1597 ASSERT(lookup->IsFound()); | 1634 ASSERT(lookup->IsFound()); |
| 1598 | 1635 |
| 1599 // These are not cacheable, so we never see such LookupResults here. | 1636 // These are not cacheable, so we never see such LookupResults here. |
| 1600 ASSERT(!lookup->IsHandler()); | 1637 ASSERT(!lookup->IsHandler()); |
| 1601 | 1638 |
| 1602 Handle<Code> code = ComputeHandler(lookup, receiver, name, value); | 1639 Handle<Code> code = ComputeHandler(lookup, receiver, name, value); |
| (...skipping 973 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2576 GENERATE(Token::MOD, SMI, 2048, SMI, NO_OVERWRITE); | 2613 GENERATE(Token::MOD, SMI, 2048, SMI, NO_OVERWRITE); |
| 2577 #undef GENERATE | 2614 #undef GENERATE |
| 2578 } | 2615 } |
| 2579 | 2616 |
| 2580 | 2617 |
| 2581 Handle<Type> BinaryOpIC::State::GetResultType(Isolate* isolate) const { | 2618 Handle<Type> BinaryOpIC::State::GetResultType(Isolate* isolate) const { |
| 2582 Kind result_kind = result_kind_; | 2619 Kind result_kind = result_kind_; |
| 2583 if (HasSideEffects()) { | 2620 if (HasSideEffects()) { |
| 2584 result_kind = NONE; | 2621 result_kind = NONE; |
| 2585 } else if (result_kind == GENERIC && op_ == Token::ADD) { | 2622 } else if (result_kind == GENERIC && op_ == Token::ADD) { |
| 2586 return handle(Type::Union(handle(Type::Number(), isolate), | 2623 return Type::Union(Type::Number(isolate), Type::String(isolate), isolate); |
| 2587 handle(Type::String(), isolate)), isolate); | |
| 2588 } else if (result_kind == NUMBER && op_ == Token::SHR) { | 2624 } else if (result_kind == NUMBER && op_ == Token::SHR) { |
| 2589 return handle(Type::Unsigned32(), isolate); | 2625 return Type::Unsigned32(isolate); |
| 2590 } | 2626 } |
| 2591 ASSERT_NE(GENERIC, result_kind); | 2627 ASSERT_NE(GENERIC, result_kind); |
| 2592 return KindToType(result_kind, isolate); | 2628 return KindToType(result_kind, isolate); |
| 2593 } | 2629 } |
| 2594 | 2630 |
| 2595 | 2631 |
| 2596 void BinaryOpIC::State::Print(StringStream* stream) const { | 2632 void BinaryOpIC::State::Print(StringStream* stream) const { |
| 2597 stream->Add("(%s", Token::Name(op_)); | 2633 stream->Add("(%s", Token::Name(op_)); |
| 2598 if (mode_ == OVERWRITE_LEFT) stream->Add("_ReuseLeft"); | 2634 if (mode_ == OVERWRITE_LEFT) stream->Add("_ReuseLeft"); |
| 2599 else if (mode_ == OVERWRITE_RIGHT) stream->Add("_ReuseRight"); | 2635 else if (mode_ == OVERWRITE_RIGHT) stream->Add("_ReuseRight"); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2714 case STRING: return "String"; | 2750 case STRING: return "String"; |
| 2715 case GENERIC: return "Generic"; | 2751 case GENERIC: return "Generic"; |
| 2716 } | 2752 } |
| 2717 UNREACHABLE(); | 2753 UNREACHABLE(); |
| 2718 return NULL; | 2754 return NULL; |
| 2719 } | 2755 } |
| 2720 | 2756 |
| 2721 | 2757 |
| 2722 // static | 2758 // static |
| 2723 Handle<Type> BinaryOpIC::State::KindToType(Kind kind, Isolate* isolate) { | 2759 Handle<Type> BinaryOpIC::State::KindToType(Kind kind, Isolate* isolate) { |
| 2724 Type* type = NULL; | |
| 2725 switch (kind) { | 2760 switch (kind) { |
| 2726 case NONE: type = Type::None(); break; | 2761 case NONE: return Type::None(isolate); |
| 2727 case SMI: type = Type::Smi(); break; | 2762 case SMI: return Type::Smi(isolate); |
| 2728 case INT32: type = Type::Signed32(); break; | 2763 case INT32: return Type::Signed32(isolate); |
| 2729 case NUMBER: type = Type::Number(); break; | 2764 case NUMBER: return Type::Number(isolate); |
| 2730 case STRING: type = Type::String(); break; | 2765 case STRING: return Type::String(isolate); |
| 2731 case GENERIC: type = Type::Any(); break; | 2766 case GENERIC: return Type::Any(isolate); |
| 2732 } | 2767 } |
| 2733 return handle(type, isolate); | 2768 UNREACHABLE(); |
| 2769 return Handle<Type>(); |
| 2734 } | 2770 } |
| 2735 | 2771 |
| 2736 | 2772 |
| 2737 MaybeObject* BinaryOpIC::Transition(Handle<AllocationSite> allocation_site, | 2773 MaybeObject* BinaryOpIC::Transition(Handle<AllocationSite> allocation_site, |
| 2738 Handle<Object> left, | 2774 Handle<Object> left, |
| 2739 Handle<Object> right) { | 2775 Handle<Object> right) { |
| 2740 State state(target()->extended_extra_ic_state()); | 2776 State state(target()->extended_extra_ic_state()); |
| 2741 | 2777 |
| 2742 // Compute the actual result using the builtin for the binary operation. | 2778 // Compute the actual result using the builtin for the binary operation. |
| 2743 Object* builtin = isolate()->js_builtins_object()->javascript_builtin( | 2779 Object* builtin = isolate()->js_builtins_object()->javascript_builtin( |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2858 UNREACHABLE(); | 2894 UNREACHABLE(); |
| 2859 return NULL; | 2895 return NULL; |
| 2860 } | 2896 } |
| 2861 | 2897 |
| 2862 | 2898 |
| 2863 Handle<Type> CompareIC::StateToType( | 2899 Handle<Type> CompareIC::StateToType( |
| 2864 Isolate* isolate, | 2900 Isolate* isolate, |
| 2865 CompareIC::State state, | 2901 CompareIC::State state, |
| 2866 Handle<Map> map) { | 2902 Handle<Map> map) { |
| 2867 switch (state) { | 2903 switch (state) { |
| 2868 case CompareIC::UNINITIALIZED: | 2904 case CompareIC::UNINITIALIZED: return Type::None(isolate); |
| 2869 return handle(Type::None(), isolate); | 2905 case CompareIC::SMI: return Type::Smi(isolate); |
| 2870 case CompareIC::SMI: | 2906 case CompareIC::NUMBER: return Type::Number(isolate); |
| 2871 return handle(Type::Smi(), isolate); | 2907 case CompareIC::STRING: return Type::String(isolate); |
| 2872 case CompareIC::NUMBER: | |
| 2873 return handle(Type::Number(), isolate); | |
| 2874 case CompareIC::STRING: | |
| 2875 return handle(Type::String(), isolate); | |
| 2876 case CompareIC::INTERNALIZED_STRING: | 2908 case CompareIC::INTERNALIZED_STRING: |
| 2877 return handle(Type::InternalizedString(), isolate); | 2909 return Type::InternalizedString(isolate); |
| 2878 case CompareIC::UNIQUE_NAME: | 2910 case CompareIC::UNIQUE_NAME: return Type::UniqueName(isolate); |
| 2879 return handle(Type::UniqueName(), isolate); | 2911 case CompareIC::OBJECT: return Type::Receiver(isolate); |
| 2880 case CompareIC::OBJECT: | |
| 2881 return handle(Type::Receiver(), isolate); | |
| 2882 case CompareIC::KNOWN_OBJECT: | 2912 case CompareIC::KNOWN_OBJECT: |
| 2883 return handle( | 2913 return map.is_null() |
| 2884 map.is_null() ? Type::Receiver() : Type::Class(map), isolate); | 2914 ? Type::Receiver(isolate) : Type::Class(map, isolate); |
| 2885 case CompareIC::GENERIC: | 2915 case CompareIC::GENERIC: return Type::Any(isolate); |
| 2886 return handle(Type::Any(), isolate); | |
| 2887 } | 2916 } |
| 2888 UNREACHABLE(); | 2917 UNREACHABLE(); |
| 2889 return Handle<Type>(); | 2918 return Handle<Type>(); |
| 2890 } | 2919 } |
| 2891 | 2920 |
| 2892 | 2921 |
| 2893 void CompareIC::StubInfoToType(int stub_minor_key, | 2922 void CompareIC::StubInfoToType(int stub_minor_key, |
| 2894 Handle<Type>* left_type, | 2923 Handle<Type>* left_type, |
| 2895 Handle<Type>* right_type, | 2924 Handle<Type>* right_type, |
| 2896 Handle<Type>* overall_type, | 2925 Handle<Type>* overall_type, |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3192 #undef ADDR | 3221 #undef ADDR |
| 3193 }; | 3222 }; |
| 3194 | 3223 |
| 3195 | 3224 |
| 3196 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3225 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 3197 return IC_utilities[id]; | 3226 return IC_utilities[id]; |
| 3198 } | 3227 } |
| 3199 | 3228 |
| 3200 | 3229 |
| 3201 } } // namespace v8::internal | 3230 } } // namespace v8::internal |
| OLD | NEW |