| 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 26 matching lines...) Expand all Loading... |
| 37 | 37 |
| 38 #include "ic-inl.h" | 38 #include "ic-inl.h" |
| 39 #include "objects-inl.h" | 39 #include "objects-inl.h" |
| 40 | 40 |
| 41 namespace v8 { | 41 namespace v8 { |
| 42 namespace internal { | 42 namespace internal { |
| 43 | 43 |
| 44 | 44 |
| 45 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, | 45 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, |
| 46 Handle<Context> native_context, | 46 Handle<Context> native_context, |
| 47 Isolate* isolate, | |
| 48 Zone* zone) | 47 Zone* zone) |
| 49 : native_context_(native_context), | 48 : native_context_(native_context), |
| 50 isolate_(isolate), | |
| 51 zone_(zone) { | 49 zone_(zone) { |
| 50 Object* raw_info = code->type_feedback_info(); |
| 51 if (raw_info->IsTypeFeedbackInfo()) { |
| 52 feedback_vector_ = Handle<FixedArray>(TypeFeedbackInfo::cast(raw_info)-> |
| 53 feedback_vector()); |
| 54 } |
| 55 |
| 52 BuildDictionary(code); | 56 BuildDictionary(code); |
| 53 ASSERT(dictionary_->IsDictionary()); | 57 ASSERT(dictionary_->IsDictionary()); |
| 54 } | 58 } |
| 55 | 59 |
| 56 | 60 |
| 57 static uint32_t IdToKey(TypeFeedbackId ast_id) { | 61 static uint32_t IdToKey(TypeFeedbackId ast_id) { |
| 58 return static_cast<uint32_t>(ast_id.ToInt()); | 62 return static_cast<uint32_t>(ast_id.ToInt()); |
| 59 } | 63 } |
| 60 | 64 |
| 61 | 65 |
| 62 Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) { | 66 Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) { |
| 63 int entry = dictionary_->FindEntry(IdToKey(ast_id)); | 67 int entry = dictionary_->FindEntry(IdToKey(ast_id)); |
| 64 if (entry != UnseededNumberDictionary::kNotFound) { | 68 if (entry != UnseededNumberDictionary::kNotFound) { |
| 65 Object* value = dictionary_->ValueAt(entry); | 69 Object* value = dictionary_->ValueAt(entry); |
| 66 if (value->IsCell()) { | 70 if (value->IsCell()) { |
| 67 Cell* cell = Cell::cast(value); | 71 Cell* cell = Cell::cast(value); |
| 68 return Handle<Object>(cell->value(), isolate_); | 72 return Handle<Object>(cell->value(), isolate()); |
| 69 } else { | 73 } else { |
| 70 return Handle<Object>(value, isolate_); | 74 return Handle<Object>(value, isolate()); |
| 71 } | 75 } |
| 72 } | 76 } |
| 73 return Handle<Object>::cast(isolate_->factory()->undefined_value()); | 77 return Handle<Object>::cast(isolate()->factory()->undefined_value()); |
| 74 } | 78 } |
| 75 | 79 |
| 76 | 80 |
| 77 Handle<Cell> TypeFeedbackOracle::GetInfoCell( | 81 Handle<Object> TypeFeedbackOracle::GetInfo(int slot) { |
| 78 TypeFeedbackId ast_id) { | 82 ASSERT(slot >= 0 && slot < feedback_vector_->length()); |
| 79 int entry = dictionary_->FindEntry(IdToKey(ast_id)); | 83 Object* obj = feedback_vector_->get(slot); |
| 80 if (entry != UnseededNumberDictionary::kNotFound) { | 84 if (!obj->IsJSFunction() || |
| 81 Cell* cell = Cell::cast(dictionary_->ValueAt(entry)); | 85 !CanRetainOtherContext(JSFunction::cast(obj), *native_context_)) { |
| 82 return Handle<Cell>(cell, isolate_); | 86 return Handle<Object>(obj, isolate()); |
| 83 } | 87 } |
| 84 return Handle<Cell>::null(); | 88 return Handle<Object>::cast(isolate()->factory()->undefined_value()); |
| 85 } | 89 } |
| 86 | 90 |
| 87 | 91 |
| 88 bool TypeFeedbackOracle::LoadIsUninitialized(TypeFeedbackId id) { | 92 bool TypeFeedbackOracle::LoadIsUninitialized(TypeFeedbackId id) { |
| 89 Handle<Object> maybe_code = GetInfo(id); | 93 Handle<Object> maybe_code = GetInfo(id); |
| 90 if (maybe_code->IsCode()) { | 94 if (maybe_code->IsCode()) { |
| 91 Handle<Code> code = Handle<Code>::cast(maybe_code); | 95 Handle<Code> code = Handle<Code>::cast(maybe_code); |
| 92 return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; | 96 return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; |
| 93 } | 97 } |
| 94 return false; | 98 return false; |
| 95 } | 99 } |
| 96 | 100 |
| 97 | 101 |
| 98 bool TypeFeedbackOracle::LoadIsPreMonomorphic(TypeFeedbackId id) { | |
| 99 Handle<Object> maybe_code = GetInfo(id); | |
| 100 if (maybe_code->IsCode()) { | |
| 101 Handle<Code> code = Handle<Code>::cast(maybe_code); | |
| 102 return code->is_inline_cache_stub() && code->ic_state() == PREMONOMORPHIC; | |
| 103 } | |
| 104 return false; | |
| 105 } | |
| 106 | |
| 107 | |
| 108 bool TypeFeedbackOracle::StoreIsUninitialized(TypeFeedbackId ast_id) { | 102 bool TypeFeedbackOracle::StoreIsUninitialized(TypeFeedbackId ast_id) { |
| 109 Handle<Object> maybe_code = GetInfo(ast_id); | 103 Handle<Object> maybe_code = GetInfo(ast_id); |
| 110 if (!maybe_code->IsCode()) return false; | 104 if (!maybe_code->IsCode()) return false; |
| 111 Handle<Code> code = Handle<Code>::cast(maybe_code); | 105 Handle<Code> code = Handle<Code>::cast(maybe_code); |
| 112 return code->ic_state() == UNINITIALIZED; | 106 return code->ic_state() == UNINITIALIZED; |
| 113 } | 107 } |
| 114 | 108 |
| 115 | 109 |
| 116 bool TypeFeedbackOracle::StoreIsPreMonomorphic(TypeFeedbackId ast_id) { | |
| 117 Handle<Object> maybe_code = GetInfo(ast_id); | |
| 118 if (maybe_code->IsCode()) { | |
| 119 Handle<Code> code = Handle<Code>::cast(maybe_code); | |
| 120 return code->ic_state() == PREMONOMORPHIC; | |
| 121 } | |
| 122 return false; | |
| 123 } | |
| 124 | |
| 125 | |
| 126 bool TypeFeedbackOracle::StoreIsKeyedPolymorphic(TypeFeedbackId ast_id) { | 110 bool TypeFeedbackOracle::StoreIsKeyedPolymorphic(TypeFeedbackId ast_id) { |
| 127 Handle<Object> maybe_code = GetInfo(ast_id); | 111 Handle<Object> maybe_code = GetInfo(ast_id); |
| 128 if (maybe_code->IsCode()) { | 112 if (maybe_code->IsCode()) { |
| 129 Handle<Code> code = Handle<Code>::cast(maybe_code); | 113 Handle<Code> code = Handle<Code>::cast(maybe_code); |
| 130 return code->is_keyed_store_stub() && | 114 return code->is_keyed_store_stub() && |
| 131 code->ic_state() == POLYMORPHIC; | 115 code->ic_state() == POLYMORPHIC; |
| 132 } | 116 } |
| 133 return false; | 117 return false; |
| 134 } | 118 } |
| 135 | 119 |
| 136 | 120 |
| 137 bool TypeFeedbackOracle::CallIsMonomorphic(TypeFeedbackId id) { | 121 bool TypeFeedbackOracle::CallIsMonomorphic(int slot) { |
| 138 Handle<Object> value = GetInfo(id); | 122 Handle<Object> value = GetInfo(slot); |
| 139 return value->IsAllocationSite() || value->IsJSFunction() || value->IsSmi() || | 123 return value->IsAllocationSite() || value->IsJSFunction(); |
| 140 (value->IsCode() && Handle<Code>::cast(value)->ic_state() == MONOMORPHIC); | |
| 141 } | 124 } |
| 142 | 125 |
| 143 | 126 |
| 144 bool TypeFeedbackOracle::KeyedArrayCallIsHoley(TypeFeedbackId id) { | 127 bool TypeFeedbackOracle::CallNewIsMonomorphic(int slot) { |
| 145 Handle<Object> value = GetInfo(id); | 128 Handle<Object> info = GetInfo(slot); |
| 146 Handle<Code> code = Handle<Code>::cast(value); | |
| 147 return KeyedArrayCallStub::IsHoley(code); | |
| 148 } | |
| 149 | |
| 150 | |
| 151 bool TypeFeedbackOracle::CallNewIsMonomorphic(TypeFeedbackId id) { | |
| 152 Handle<Object> info = GetInfo(id); | |
| 153 return info->IsAllocationSite() || info->IsJSFunction(); | 129 return info->IsAllocationSite() || info->IsJSFunction(); |
| 154 } | 130 } |
| 155 | 131 |
| 156 | 132 |
| 157 byte TypeFeedbackOracle::ForInType(TypeFeedbackId id) { | 133 byte TypeFeedbackOracle::ForInType(int feedback_vector_slot) { |
| 158 Handle<Object> value = GetInfo(id); | 134 Handle<Object> value = GetInfo(feedback_vector_slot); |
| 159 return value->IsSmi() && | 135 return value->IsSmi() && |
| 160 Smi::cast(*value)->value() == TypeFeedbackCells::kForInFastCaseMarker | 136 Smi::cast(*value)->value() == TypeFeedbackInfo::kForInFastCaseMarker |
| 161 ? ForInStatement::FAST_FOR_IN : ForInStatement::SLOW_FOR_IN; | 137 ? ForInStatement::FAST_FOR_IN : ForInStatement::SLOW_FOR_IN; |
| 162 } | 138 } |
| 163 | 139 |
| 164 | 140 |
| 165 KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode( | 141 KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode( |
| 166 TypeFeedbackId ast_id) { | 142 TypeFeedbackId ast_id) { |
| 167 Handle<Object> maybe_code = GetInfo(ast_id); | 143 Handle<Object> maybe_code = GetInfo(ast_id); |
| 168 if (maybe_code->IsCode()) { | 144 if (maybe_code->IsCode()) { |
| 169 Handle<Code> code = Handle<Code>::cast(maybe_code); | 145 Handle<Code> code = Handle<Code>::cast(maybe_code); |
| 170 if (code->kind() == Code::KEYED_STORE_IC) { | 146 if (code->kind() == Code::KEYED_STORE_IC) { |
| 171 return KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()); | 147 return KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()); |
| 172 } | 148 } |
| 173 } | 149 } |
| 174 return STANDARD_STORE; | 150 return STANDARD_STORE; |
| 175 } | 151 } |
| 176 | 152 |
| 177 | 153 |
| 178 void TypeFeedbackOracle::CallReceiverTypes(TypeFeedbackId id, | 154 Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(int slot) { |
| 179 Handle<String> name, | 155 Handle<Object> info = GetInfo(slot); |
| 180 int arity, | |
| 181 SmallMapList* types) { | |
| 182 Code::Flags flags = Code::ComputeMonomorphicFlags( | |
| 183 Code::CALL_IC, kNoExtraICState, OWN_MAP, Code::NORMAL, arity); | |
| 184 CollectReceiverTypes(id, name, flags, types); | |
| 185 } | |
| 186 | |
| 187 | |
| 188 CheckType TypeFeedbackOracle::GetCallCheckType(TypeFeedbackId id) { | |
| 189 Handle<Object> value = GetInfo(id); | |
| 190 if (!value->IsSmi()) return RECEIVER_MAP_CHECK; | |
| 191 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value()); | |
| 192 ASSERT(check != RECEIVER_MAP_CHECK); | |
| 193 return check; | |
| 194 } | |
| 195 | |
| 196 | |
| 197 Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(TypeFeedbackId id) { | |
| 198 Handle<Object> info = GetInfo(id); | |
| 199 if (info->IsAllocationSite()) { | 156 if (info->IsAllocationSite()) { |
| 200 return Handle<JSFunction>(isolate_->global_context()->array_function()); | 157 return Handle<JSFunction>(isolate()->native_context()->array_function()); |
| 201 } else { | 158 } else { |
| 202 return Handle<JSFunction>::cast(info); | 159 return Handle<JSFunction>::cast(info); |
| 203 } | 160 } |
| 204 } | 161 } |
| 205 | 162 |
| 206 | 163 |
| 207 Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(TypeFeedbackId id) { | 164 Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(int slot) { |
| 208 Handle<Object> info = GetInfo(id); | 165 Handle<Object> info = GetInfo(slot); |
| 209 if (info->IsAllocationSite()) { | 166 if (info->IsAllocationSite()) { |
| 210 return Handle<JSFunction>(isolate_->global_context()->array_function()); | 167 return Handle<JSFunction>(isolate()->native_context()->array_function()); |
| 211 } else { | 168 } else { |
| 212 return Handle<JSFunction>::cast(info); | 169 return Handle<JSFunction>::cast(info); |
| 213 } | 170 } |
| 214 } | 171 } |
| 215 | 172 |
| 216 | 173 |
| 217 Handle<Cell> TypeFeedbackOracle::GetCallNewAllocationInfoCell( | 174 Handle<AllocationSite> TypeFeedbackOracle::GetCallNewAllocationSite(int slot) { |
| 218 TypeFeedbackId id) { | 175 Handle<Object> info = GetInfo(slot); |
| 219 return GetInfoCell(id); | 176 if (info->IsAllocationSite()) { |
| 177 return Handle<AllocationSite>::cast(info); |
| 178 } |
| 179 return Handle<AllocationSite>::null(); |
| 220 } | 180 } |
| 221 | 181 |
| 222 | 182 |
| 223 bool TypeFeedbackOracle::LoadIsBuiltin( | 183 bool TypeFeedbackOracle::LoadIsBuiltin( |
| 224 TypeFeedbackId id, Builtins::Name builtin) { | 184 TypeFeedbackId id, Builtins::Name builtin) { |
| 225 return *GetInfo(id) == isolate_->builtins()->builtin(builtin); | 185 return *GetInfo(id) == isolate()->builtins()->builtin(builtin); |
| 226 } | 186 } |
| 227 | 187 |
| 228 | 188 |
| 229 bool TypeFeedbackOracle::LoadIsStub(TypeFeedbackId id, ICStub* stub) { | 189 bool TypeFeedbackOracle::LoadIsStub(TypeFeedbackId id, ICStub* stub) { |
| 230 Handle<Object> object = GetInfo(id); | 190 Handle<Object> object = GetInfo(id); |
| 231 if (!object->IsCode()) return false; | 191 if (!object->IsCode()) return false; |
| 232 Handle<Code> code = Handle<Code>::cast(object); | 192 Handle<Code> code = Handle<Code>::cast(object); |
| 233 if (!code->is_load_stub()) return false; | 193 if (!code->is_load_stub()) return false; |
| 234 if (code->ic_state() != MONOMORPHIC) return false; | 194 if (code->ic_state() != MONOMORPHIC) return false; |
| 235 return stub->Describes(*code); | 195 return stub->Describes(*code); |
| 236 } | 196 } |
| 237 | 197 |
| 238 | 198 |
| 239 void TypeFeedbackOracle::CompareType(TypeFeedbackId id, | 199 void TypeFeedbackOracle::CompareType(TypeFeedbackId id, |
| 240 Handle<Type>* left_type, | 200 Type** left_type, |
| 241 Handle<Type>* right_type, | 201 Type** right_type, |
| 242 Handle<Type>* combined_type) { | 202 Type** combined_type) { |
| 243 Handle<Object> info = GetInfo(id); | 203 Handle<Object> info = GetInfo(id); |
| 244 if (!info->IsCode()) { | 204 if (!info->IsCode()) { |
| 245 // For some comparisons we don't have ICs, e.g. LiteralCompareTypeof. | 205 // For some comparisons we don't have ICs, e.g. LiteralCompareTypeof. |
| 246 *left_type = *right_type = *combined_type = Type::None(isolate_); | 206 *left_type = *right_type = *combined_type = Type::None(zone()); |
| 247 return; | 207 return; |
| 248 } | 208 } |
| 249 Handle<Code> code = Handle<Code>::cast(info); | 209 Handle<Code> code = Handle<Code>::cast(info); |
| 250 | 210 |
| 251 Handle<Map> map; | 211 Handle<Map> map; |
| 252 Map* raw_map = code->FindFirstMap(); | 212 Map* raw_map = code->FindFirstMap(); |
| 253 if (raw_map != NULL) { | 213 if (raw_map != NULL) { |
| 254 map = Map::CurrentMapForDeprecated(handle(raw_map)); | 214 map = Map::CurrentMapForDeprecated(handle(raw_map)); |
| 255 if (!map.is_null() && CanRetainOtherContext(*map, *native_context_)) { | 215 if (!map.is_null() && CanRetainOtherContext(*map, *native_context_)) { |
| 256 map = Handle<Map>::null(); | 216 map = Handle<Map>::null(); |
| 257 } | 217 } |
| 258 } | 218 } |
| 259 | 219 |
| 260 if (code->is_compare_ic_stub()) { | 220 if (code->is_compare_ic_stub()) { |
| 261 int stub_minor_key = code->stub_info(); | 221 int stub_minor_key = code->stub_info(); |
| 262 CompareIC::StubInfoToType( | 222 CompareIC::StubInfoToType( |
| 263 stub_minor_key, left_type, right_type, combined_type, map, isolate()); | 223 stub_minor_key, left_type, right_type, combined_type, map, zone()); |
| 264 } else if (code->is_compare_nil_ic_stub()) { | 224 } else if (code->is_compare_nil_ic_stub()) { |
| 265 CompareNilICStub stub(code->extended_extra_ic_state()); | 225 CompareNilICStub stub(code->extra_ic_state()); |
| 266 *combined_type = stub.GetType(isolate_, map); | 226 *combined_type = stub.GetType(zone(), map); |
| 267 *left_type = *right_type = stub.GetInputType(isolate_, map); | 227 *left_type = *right_type = stub.GetInputType(zone(), map); |
| 268 } | 228 } |
| 269 } | 229 } |
| 270 | 230 |
| 271 | 231 |
| 272 void TypeFeedbackOracle::BinaryType(TypeFeedbackId id, | 232 void TypeFeedbackOracle::BinaryType(TypeFeedbackId id, |
| 273 Handle<Type>* left, | 233 Type** left, |
| 274 Handle<Type>* right, | 234 Type** right, |
| 275 Handle<Type>* result, | 235 Type** result, |
| 276 Maybe<int>* fixed_right_arg, | 236 Maybe<int>* fixed_right_arg, |
| 277 Handle<AllocationSite>* allocation_site, | 237 Handle<AllocationSite>* allocation_site, |
| 278 Token::Value op) { | 238 Token::Value op) { |
| 279 Handle<Object> object = GetInfo(id); | 239 Handle<Object> object = GetInfo(id); |
| 280 if (!object->IsCode()) { | 240 if (!object->IsCode()) { |
| 281 // For some binary ops we don't have ICs, e.g. Token::COMMA, but for the | 241 // For some binary ops we don't have ICs, e.g. Token::COMMA, but for the |
| 282 // operations covered by the BinaryOpIC we should always have them. | 242 // operations covered by the BinaryOpIC we should always have them. |
| 283 ASSERT(op < BinaryOpIC::State::FIRST_TOKEN || | 243 ASSERT(op < BinaryOpIC::State::FIRST_TOKEN || |
| 284 op > BinaryOpIC::State::LAST_TOKEN); | 244 op > BinaryOpIC::State::LAST_TOKEN); |
| 285 *left = *right = *result = Type::None(isolate_); | 245 *left = *right = *result = Type::None(zone()); |
| 286 *fixed_right_arg = Maybe<int>(); | 246 *fixed_right_arg = Maybe<int>(); |
| 287 *allocation_site = Handle<AllocationSite>::null(); | 247 *allocation_site = Handle<AllocationSite>::null(); |
| 288 return; | 248 return; |
| 289 } | 249 } |
| 290 Handle<Code> code = Handle<Code>::cast(object); | 250 Handle<Code> code = Handle<Code>::cast(object); |
| 291 ASSERT_EQ(Code::BINARY_OP_IC, code->kind()); | 251 ASSERT_EQ(Code::BINARY_OP_IC, code->kind()); |
| 292 BinaryOpIC::State state(code->extended_extra_ic_state()); | 252 BinaryOpIC::State state(code->extra_ic_state()); |
| 293 ASSERT_EQ(op, state.op()); | 253 ASSERT_EQ(op, state.op()); |
| 294 | 254 |
| 295 *left = state.GetLeftType(isolate()); | 255 *left = state.GetLeftType(zone()); |
| 296 *right = state.GetRightType(isolate()); | 256 *right = state.GetRightType(zone()); |
| 297 *result = state.GetResultType(isolate()); | 257 *result = state.GetResultType(zone()); |
| 298 *fixed_right_arg = state.fixed_right_arg(); | 258 *fixed_right_arg = state.fixed_right_arg(); |
| 299 | 259 |
| 300 AllocationSite* first_allocation_site = code->FindFirstAllocationSite(); | 260 AllocationSite* first_allocation_site = code->FindFirstAllocationSite(); |
| 301 if (first_allocation_site != NULL) { | 261 if (first_allocation_site != NULL) { |
| 302 *allocation_site = handle(first_allocation_site); | 262 *allocation_site = handle(first_allocation_site); |
| 303 } else { | 263 } else { |
| 304 *allocation_site = Handle<AllocationSite>::null(); | 264 *allocation_site = Handle<AllocationSite>::null(); |
| 305 } | 265 } |
| 306 } | 266 } |
| 307 | 267 |
| 308 | 268 |
| 309 Handle<Type> TypeFeedbackOracle::CountType(TypeFeedbackId id) { | 269 Type* TypeFeedbackOracle::CountType(TypeFeedbackId id) { |
| 310 Handle<Object> object = GetInfo(id); | 270 Handle<Object> object = GetInfo(id); |
| 311 if (!object->IsCode()) return Type::None(isolate_); | 271 if (!object->IsCode()) return Type::None(zone()); |
| 312 Handle<Code> code = Handle<Code>::cast(object); | 272 Handle<Code> code = Handle<Code>::cast(object); |
| 313 ASSERT_EQ(Code::BINARY_OP_IC, code->kind()); | 273 ASSERT_EQ(Code::BINARY_OP_IC, code->kind()); |
| 314 BinaryOpIC::State state(code->extended_extra_ic_state()); | 274 BinaryOpIC::State state(code->extra_ic_state()); |
| 315 return state.GetLeftType(isolate()); | 275 return state.GetLeftType(zone()); |
| 316 } | 276 } |
| 317 | 277 |
| 318 | 278 |
| 319 void TypeFeedbackOracle::PropertyReceiverTypes( | 279 void TypeFeedbackOracle::PropertyReceiverTypes( |
| 320 TypeFeedbackId id, Handle<String> name, | 280 TypeFeedbackId id, Handle<String> name, |
| 321 SmallMapList* receiver_types, bool* is_prototype) { | 281 SmallMapList* receiver_types, bool* is_prototype) { |
| 322 receiver_types->Clear(); | 282 receiver_types->Clear(); |
| 323 FunctionPrototypeStub proto_stub(Code::LOAD_IC); | 283 FunctionPrototypeStub proto_stub(Code::LOAD_IC); |
| 324 *is_prototype = LoadIsStub(id, &proto_stub); | 284 *is_prototype = LoadIsStub(id, &proto_stub); |
| 325 if (!*is_prototype) { | 285 if (!*is_prototype) { |
| 326 Code::Flags flags = Code::ComputeFlags( | 286 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); |
| 327 Code::HANDLER, MONOMORPHIC, kNoExtraICState, | |
| 328 Code::NORMAL, Code::LOAD_IC); | |
| 329 CollectReceiverTypes(id, name, flags, receiver_types); | 287 CollectReceiverTypes(id, name, flags, receiver_types); |
| 330 } | 288 } |
| 331 } | 289 } |
| 332 | 290 |
| 333 | 291 |
| 334 void TypeFeedbackOracle::KeyedPropertyReceiverTypes( | 292 void TypeFeedbackOracle::KeyedPropertyReceiverTypes( |
| 335 TypeFeedbackId id, SmallMapList* receiver_types, bool* is_string) { | 293 TypeFeedbackId id, SmallMapList* receiver_types, bool* is_string) { |
| 336 receiver_types->Clear(); | 294 receiver_types->Clear(); |
| 337 *is_string = false; | 295 *is_string = false; |
| 338 if (LoadIsBuiltin(id, Builtins::kKeyedLoadIC_String)) { | 296 if (LoadIsBuiltin(id, Builtins::kKeyedLoadIC_String)) { |
| 339 *is_string = true; | 297 *is_string = true; |
| 340 } else { | 298 } else { |
| 341 CollectReceiverTypes(id, receiver_types); | 299 CollectReceiverTypes(id, receiver_types); |
| 342 } | 300 } |
| 343 } | 301 } |
| 344 | 302 |
| 345 | 303 |
| 346 void TypeFeedbackOracle::AssignmentReceiverTypes( | 304 void TypeFeedbackOracle::AssignmentReceiverTypes( |
| 347 TypeFeedbackId id, Handle<String> name, SmallMapList* receiver_types) { | 305 TypeFeedbackId id, Handle<String> name, SmallMapList* receiver_types) { |
| 348 receiver_types->Clear(); | 306 receiver_types->Clear(); |
| 349 Code::Flags flags = Code::ComputeFlags( | 307 Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC); |
| 350 Code::HANDLER, MONOMORPHIC, kNoExtraICState, | |
| 351 Code::NORMAL, Code::STORE_IC); | |
| 352 CollectReceiverTypes(id, name, flags, receiver_types); | 308 CollectReceiverTypes(id, name, flags, receiver_types); |
| 353 } | 309 } |
| 354 | 310 |
| 355 | 311 |
| 356 void TypeFeedbackOracle::KeyedAssignmentReceiverTypes( | 312 void TypeFeedbackOracle::KeyedAssignmentReceiverTypes( |
| 357 TypeFeedbackId id, SmallMapList* receiver_types, | 313 TypeFeedbackId id, SmallMapList* receiver_types, |
| 358 KeyedAccessStoreMode* store_mode) { | 314 KeyedAccessStoreMode* store_mode) { |
| 359 receiver_types->Clear(); | 315 receiver_types->Clear(); |
| 360 CollectReceiverTypes(id, receiver_types); | 316 CollectReceiverTypes(id, receiver_types); |
| 361 *store_mode = GetStoreMode(id); | 317 *store_mode = GetStoreMode(id); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 375 SmallMapList* types) { | 331 SmallMapList* types) { |
| 376 Handle<Object> object = GetInfo(ast_id); | 332 Handle<Object> object = GetInfo(ast_id); |
| 377 if (object->IsUndefined() || object->IsSmi()) return; | 333 if (object->IsUndefined() || object->IsSmi()) return; |
| 378 | 334 |
| 379 ASSERT(object->IsCode()); | 335 ASSERT(object->IsCode()); |
| 380 Handle<Code> code(Handle<Code>::cast(object)); | 336 Handle<Code> code(Handle<Code>::cast(object)); |
| 381 | 337 |
| 382 if (FLAG_collect_megamorphic_maps_from_stub_cache && | 338 if (FLAG_collect_megamorphic_maps_from_stub_cache && |
| 383 code->ic_state() == MEGAMORPHIC) { | 339 code->ic_state() == MEGAMORPHIC) { |
| 384 types->Reserve(4, zone()); | 340 types->Reserve(4, zone()); |
| 385 isolate_->stub_cache()->CollectMatchingMaps( | 341 isolate()->stub_cache()->CollectMatchingMaps( |
| 386 types, name, flags, native_context_, zone()); | 342 types, name, flags, native_context_, zone()); |
| 387 } else { | 343 } else { |
| 388 CollectReceiverTypes(ast_id, types); | 344 CollectReceiverTypes(ast_id, types); |
| 389 } | 345 } |
| 390 } | 346 } |
| 391 | 347 |
| 392 | 348 |
| 393 // Check if a map originates from a given native context. We use this | 349 // Check if a map originates from a given native context. We use this |
| 394 // information to filter out maps from different context to avoid | 350 // information to filter out maps from different context to avoid |
| 395 // retaining objects from different tabs in Chrome via optimized code. | 351 // retaining objects from different tabs in Chrome via optimized code. |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 } | 410 } |
| 455 | 411 |
| 456 | 412 |
| 457 // Things are a bit tricky here: The iterator for the RelocInfos and the infos | 413 // Things are a bit tricky here: The iterator for the RelocInfos and the infos |
| 458 // themselves are not GC-safe, so we first get all infos, then we create the | 414 // themselves are not GC-safe, so we first get all infos, then we create the |
| 459 // dictionary (possibly triggering GC), and finally we relocate the collected | 415 // dictionary (possibly triggering GC), and finally we relocate the collected |
| 460 // infos before we process them. | 416 // infos before we process them. |
| 461 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { | 417 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { |
| 462 DisallowHeapAllocation no_allocation; | 418 DisallowHeapAllocation no_allocation; |
| 463 ZoneList<RelocInfo> infos(16, zone()); | 419 ZoneList<RelocInfo> infos(16, zone()); |
| 464 HandleScope scope(isolate_); | 420 HandleScope scope(isolate()); |
| 465 GetRelocInfos(code, &infos); | 421 GetRelocInfos(code, &infos); |
| 466 CreateDictionary(code, &infos); | 422 CreateDictionary(code, &infos); |
| 467 ProcessRelocInfos(&infos); | 423 ProcessRelocInfos(&infos); |
| 468 ProcessTypeFeedbackCells(code); | |
| 469 // Allocate handle in the parent scope. | 424 // Allocate handle in the parent scope. |
| 470 dictionary_ = scope.CloseAndEscape(dictionary_); | 425 dictionary_ = scope.CloseAndEscape(dictionary_); |
| 471 } | 426 } |
| 472 | 427 |
| 473 | 428 |
| 474 void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code, | 429 void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code, |
| 475 ZoneList<RelocInfo>* infos) { | 430 ZoneList<RelocInfo>* infos) { |
| 476 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); | 431 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); |
| 477 for (RelocIterator it(*code, mask); !it.done(); it.next()) { | 432 for (RelocIterator it(*code, mask); !it.done(); it.next()) { |
| 478 infos->Add(*it.rinfo(), zone()); | 433 infos->Add(*it.rinfo(), zone()); |
| 479 } | 434 } |
| 480 } | 435 } |
| 481 | 436 |
| 482 | 437 |
| 483 void TypeFeedbackOracle::CreateDictionary(Handle<Code> code, | 438 void TypeFeedbackOracle::CreateDictionary(Handle<Code> code, |
| 484 ZoneList<RelocInfo>* infos) { | 439 ZoneList<RelocInfo>* infos) { |
| 485 AllowHeapAllocation allocation_allowed; | 440 AllowHeapAllocation allocation_allowed; |
| 486 int cell_count = code->type_feedback_info()->IsTypeFeedbackInfo() | |
| 487 ? TypeFeedbackInfo::cast(code->type_feedback_info())-> | |
| 488 type_feedback_cells()->CellCount() | |
| 489 : 0; | |
| 490 int length = infos->length() + cell_count; | |
| 491 byte* old_start = code->instruction_start(); | 441 byte* old_start = code->instruction_start(); |
| 492 dictionary_ = isolate()->factory()->NewUnseededNumberDictionary(length); | 442 dictionary_ = |
| 443 isolate()->factory()->NewUnseededNumberDictionary(infos->length()); |
| 493 byte* new_start = code->instruction_start(); | 444 byte* new_start = code->instruction_start(); |
| 494 RelocateRelocInfos(infos, old_start, new_start); | 445 RelocateRelocInfos(infos, old_start, new_start); |
| 495 } | 446 } |
| 496 | 447 |
| 497 | 448 |
| 498 void TypeFeedbackOracle::RelocateRelocInfos(ZoneList<RelocInfo>* infos, | 449 void TypeFeedbackOracle::RelocateRelocInfos(ZoneList<RelocInfo>* infos, |
| 499 byte* old_start, | 450 byte* old_start, |
| 500 byte* new_start) { | 451 byte* new_start) { |
| 501 for (int i = 0; i < infos->length(); i++) { | 452 for (int i = 0; i < infos->length(); i++) { |
| 502 RelocInfo* info = &(*infos)[i]; | 453 RelocInfo* info = &(*infos)[i]; |
| 503 info->set_pc(new_start + (info->pc() - old_start)); | 454 info->set_pc(new_start + (info->pc() - old_start)); |
| 504 } | 455 } |
| 505 } | 456 } |
| 506 | 457 |
| 507 | 458 |
| 508 void TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) { | 459 void TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) { |
| 509 for (int i = 0; i < infos->length(); i++) { | 460 for (int i = 0; i < infos->length(); i++) { |
| 510 RelocInfo reloc_entry = (*infos)[i]; | 461 RelocInfo reloc_entry = (*infos)[i]; |
| 511 Address target_address = reloc_entry.target_address(); | 462 Address target_address = reloc_entry.target_address(); |
| 512 TypeFeedbackId ast_id = | 463 TypeFeedbackId ast_id = |
| 513 TypeFeedbackId(static_cast<unsigned>((*infos)[i].data())); | 464 TypeFeedbackId(static_cast<unsigned>((*infos)[i].data())); |
| 514 Code* target = Code::GetCodeFromTargetAddress(target_address); | 465 Code* target = Code::GetCodeFromTargetAddress(target_address); |
| 515 switch (target->kind()) { | 466 switch (target->kind()) { |
| 516 case Code::CALL_IC: | |
| 517 if (target->ic_state() == MONOMORPHIC && | |
| 518 target->check_type() != RECEIVER_MAP_CHECK) { | |
| 519 SetInfo(ast_id, Smi::FromInt(target->check_type())); | |
| 520 break; | |
| 521 } | |
| 522 case Code::LOAD_IC: | 467 case Code::LOAD_IC: |
| 523 case Code::STORE_IC: | 468 case Code::STORE_IC: |
| 524 case Code::KEYED_CALL_IC: | |
| 525 case Code::KEYED_LOAD_IC: | 469 case Code::KEYED_LOAD_IC: |
| 526 case Code::KEYED_STORE_IC: | 470 case Code::KEYED_STORE_IC: |
| 527 case Code::BINARY_OP_IC: | 471 case Code::BINARY_OP_IC: |
| 528 case Code::COMPARE_IC: | 472 case Code::COMPARE_IC: |
| 529 case Code::TO_BOOLEAN_IC: | 473 case Code::TO_BOOLEAN_IC: |
| 530 case Code::COMPARE_NIL_IC: | 474 case Code::COMPARE_NIL_IC: |
| 531 SetInfo(ast_id, target); | 475 SetInfo(ast_id, target); |
| 532 break; | 476 break; |
| 533 | 477 |
| 534 default: | 478 default: |
| 535 break; | 479 break; |
| 536 } | 480 } |
| 537 } | 481 } |
| 538 } | 482 } |
| 539 | 483 |
| 540 | 484 |
| 541 void TypeFeedbackOracle::ProcessTypeFeedbackCells(Handle<Code> code) { | |
| 542 Object* raw_info = code->type_feedback_info(); | |
| 543 if (!raw_info->IsTypeFeedbackInfo()) return; | |
| 544 Handle<TypeFeedbackCells> cache( | |
| 545 TypeFeedbackInfo::cast(raw_info)->type_feedback_cells()); | |
| 546 for (int i = 0; i < cache->CellCount(); i++) { | |
| 547 TypeFeedbackId ast_id = cache->AstId(i); | |
| 548 Cell* cell = cache->GetCell(i); | |
| 549 Object* value = cell->value(); | |
| 550 if (value->IsSmi() || | |
| 551 value->IsAllocationSite() || | |
| 552 (value->IsJSFunction() && | |
| 553 !CanRetainOtherContext(JSFunction::cast(value), | |
| 554 *native_context_))) { | |
| 555 SetInfo(ast_id, cell); | |
| 556 } | |
| 557 } | |
| 558 } | |
| 559 | |
| 560 | |
| 561 void TypeFeedbackOracle::SetInfo(TypeFeedbackId ast_id, Object* target) { | 485 void TypeFeedbackOracle::SetInfo(TypeFeedbackId ast_id, Object* target) { |
| 562 ASSERT(dictionary_->FindEntry(IdToKey(ast_id)) == | 486 ASSERT(dictionary_->FindEntry(IdToKey(ast_id)) == |
| 563 UnseededNumberDictionary::kNotFound); | 487 UnseededNumberDictionary::kNotFound); |
| 564 MaybeObject* maybe_result = dictionary_->AtNumberPut(IdToKey(ast_id), target); | 488 MaybeObject* maybe_result = dictionary_->AtNumberPut(IdToKey(ast_id), target); |
| 565 USE(maybe_result); | 489 USE(maybe_result); |
| 566 #ifdef DEBUG | 490 #ifdef DEBUG |
| 567 Object* result = NULL; | 491 Object* result = NULL; |
| 568 // Dictionary has been allocated with sufficient size for all elements. | 492 // Dictionary has been allocated with sufficient size for all elements. |
| 569 ASSERT(maybe_result->ToObject(&result)); | 493 ASSERT(maybe_result->ToObject(&result)); |
| 570 ASSERT(*dictionary_ == result); | 494 ASSERT(*dictionary_ == result); |
| 571 #endif | 495 #endif |
| 572 } | 496 } |
| 573 | 497 |
| 574 | 498 |
| 575 } } // namespace v8::internal | 499 } } // namespace v8::internal |
| OLD | NEW |