| 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 29 matching lines...) Expand all Loading... |
| 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 Zone* zone) | 47 Zone* zone) |
| 48 : native_context_(native_context), | 48 : native_context_(native_context), |
| 49 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 | |
| 56 BuildDictionary(code); | 50 BuildDictionary(code); |
| 57 ASSERT(dictionary_->IsDictionary()); | 51 ASSERT(dictionary_->IsDictionary()); |
| 58 } | 52 } |
| 59 | 53 |
| 60 | 54 |
| 61 static uint32_t IdToKey(TypeFeedbackId ast_id) { | 55 static uint32_t IdToKey(TypeFeedbackId ast_id) { |
| 62 return static_cast<uint32_t>(ast_id.ToInt()); | 56 return static_cast<uint32_t>(ast_id.ToInt()); |
| 63 } | 57 } |
| 64 | 58 |
| 65 | 59 |
| 66 Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) { | 60 Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) { |
| 67 int entry = dictionary_->FindEntry(IdToKey(ast_id)); | 61 int entry = dictionary_->FindEntry(IdToKey(ast_id)); |
| 68 if (entry != UnseededNumberDictionary::kNotFound) { | 62 if (entry != UnseededNumberDictionary::kNotFound) { |
| 69 Object* value = dictionary_->ValueAt(entry); | 63 Object* value = dictionary_->ValueAt(entry); |
| 70 if (value->IsCell()) { | 64 if (value->IsCell()) { |
| 71 Cell* cell = Cell::cast(value); | 65 Cell* cell = Cell::cast(value); |
| 72 return Handle<Object>(cell->value(), isolate()); | 66 return Handle<Object>(cell->value(), isolate()); |
| 73 } else { | 67 } else { |
| 74 return Handle<Object>(value, isolate()); | 68 return Handle<Object>(value, isolate()); |
| 75 } | 69 } |
| 76 } | 70 } |
| 77 return Handle<Object>::cast(isolate()->factory()->undefined_value()); | 71 return Handle<Object>::cast(isolate()->factory()->undefined_value()); |
| 78 } | 72 } |
| 79 | 73 |
| 80 | 74 |
| 81 Handle<Object> TypeFeedbackOracle::GetInfo(int slot) { | |
| 82 ASSERT(slot >= 0 && slot < feedback_vector_->length()); | |
| 83 Object* obj = feedback_vector_->get(slot); | |
| 84 if (!obj->IsJSFunction() || | |
| 85 !CanRetainOtherContext(JSFunction::cast(obj), *native_context_)) { | |
| 86 return Handle<Object>(obj, isolate()); | |
| 87 } | |
| 88 return Handle<Object>::cast(isolate()->factory()->undefined_value()); | |
| 89 } | |
| 90 | |
| 91 | |
| 92 bool TypeFeedbackOracle::LoadIsUninitialized(TypeFeedbackId id) { | 75 bool TypeFeedbackOracle::LoadIsUninitialized(TypeFeedbackId id) { |
| 93 Handle<Object> maybe_code = GetInfo(id); | 76 Handle<Object> maybe_code = GetInfo(id); |
| 94 if (maybe_code->IsCode()) { | 77 if (maybe_code->IsCode()) { |
| 95 Handle<Code> code = Handle<Code>::cast(maybe_code); | 78 Handle<Code> code = Handle<Code>::cast(maybe_code); |
| 96 return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; | 79 return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; |
| 97 } | 80 } |
| 98 return false; | 81 return false; |
| 99 } | 82 } |
| 100 | 83 |
| 101 | 84 |
| 102 bool TypeFeedbackOracle::StoreIsUninitialized(TypeFeedbackId ast_id) { | 85 bool TypeFeedbackOracle::StoreIsUninitialized(TypeFeedbackId ast_id) { |
| 103 Handle<Object> maybe_code = GetInfo(ast_id); | 86 Handle<Object> maybe_code = GetInfo(ast_id); |
| 104 if (!maybe_code->IsCode()) return false; | 87 if (!maybe_code->IsCode()) return false; |
| 105 Handle<Code> code = Handle<Code>::cast(maybe_code); | 88 Handle<Code> code = Handle<Code>::cast(maybe_code); |
| 106 return code->ic_state() == UNINITIALIZED; | 89 return code->ic_state() == UNINITIALIZED; |
| 107 } | 90 } |
| 108 | 91 |
| 109 | 92 |
| 110 bool TypeFeedbackOracle::StoreIsKeyedPolymorphic(TypeFeedbackId ast_id) { | 93 bool TypeFeedbackOracle::StoreIsKeyedPolymorphic(TypeFeedbackId ast_id) { |
| 111 Handle<Object> maybe_code = GetInfo(ast_id); | 94 Handle<Object> maybe_code = GetInfo(ast_id); |
| 112 if (maybe_code->IsCode()) { | 95 if (maybe_code->IsCode()) { |
| 113 Handle<Code> code = Handle<Code>::cast(maybe_code); | 96 Handle<Code> code = Handle<Code>::cast(maybe_code); |
| 114 return code->is_keyed_store_stub() && | 97 return code->is_keyed_store_stub() && |
| 115 code->ic_state() == POLYMORPHIC; | 98 code->ic_state() == POLYMORPHIC; |
| 116 } | 99 } |
| 117 return false; | 100 return false; |
| 118 } | 101 } |
| 119 | 102 |
| 120 | 103 |
| 121 bool TypeFeedbackOracle::CallIsMonomorphic(int slot) { | 104 bool TypeFeedbackOracle::CallIsMonomorphic(TypeFeedbackId id) { |
| 122 Handle<Object> value = GetInfo(slot); | 105 Handle<Object> value = GetInfo(id); |
| 123 return value->IsAllocationSite() || value->IsJSFunction(); | 106 return value->IsAllocationSite() || value->IsJSFunction(); |
| 124 } | 107 } |
| 125 | 108 |
| 126 | 109 |
| 127 bool TypeFeedbackOracle::CallNewIsMonomorphic(int slot) { | 110 bool TypeFeedbackOracle::CallNewIsMonomorphic(TypeFeedbackId id) { |
| 128 Handle<Object> info = GetInfo(slot); | 111 Handle<Object> info = GetInfo(id); |
| 129 return info->IsAllocationSite() || info->IsJSFunction(); | 112 return info->IsAllocationSite() || info->IsJSFunction(); |
| 130 } | 113 } |
| 131 | 114 |
| 132 | 115 |
| 133 byte TypeFeedbackOracle::ForInType(int feedback_vector_slot) { | 116 byte TypeFeedbackOracle::ForInType(TypeFeedbackId id) { |
| 134 Handle<Object> value = GetInfo(feedback_vector_slot); | 117 Handle<Object> value = GetInfo(id); |
| 135 return value->IsSmi() && | 118 return value->IsSmi() && |
| 136 Smi::cast(*value)->value() == TypeFeedbackInfo::kForInFastCaseMarker | 119 Smi::cast(*value)->value() == TypeFeedbackCells::kForInFastCaseMarker |
| 137 ? ForInStatement::FAST_FOR_IN : ForInStatement::SLOW_FOR_IN; | 120 ? ForInStatement::FAST_FOR_IN : ForInStatement::SLOW_FOR_IN; |
| 138 } | 121 } |
| 139 | 122 |
| 140 | 123 |
| 141 KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode( | 124 KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode( |
| 142 TypeFeedbackId ast_id) { | 125 TypeFeedbackId ast_id) { |
| 143 Handle<Object> maybe_code = GetInfo(ast_id); | 126 Handle<Object> maybe_code = GetInfo(ast_id); |
| 144 if (maybe_code->IsCode()) { | 127 if (maybe_code->IsCode()) { |
| 145 Handle<Code> code = Handle<Code>::cast(maybe_code); | 128 Handle<Code> code = Handle<Code>::cast(maybe_code); |
| 146 if (code->kind() == Code::KEYED_STORE_IC) { | 129 if (code->kind() == Code::KEYED_STORE_IC) { |
| 147 return KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()); | 130 return KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()); |
| 148 } | 131 } |
| 149 } | 132 } |
| 150 return STANDARD_STORE; | 133 return STANDARD_STORE; |
| 151 } | 134 } |
| 152 | 135 |
| 153 | 136 |
| 154 Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(int slot) { | 137 Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(TypeFeedbackId id) { |
| 155 Handle<Object> info = GetInfo(slot); | 138 Handle<Object> info = GetInfo(id); |
| 156 if (info->IsAllocationSite()) { | 139 if (info->IsAllocationSite()) { |
| 157 return Handle<JSFunction>(isolate()->global_context()->array_function()); | 140 return Handle<JSFunction>(isolate()->global_context()->array_function()); |
| 158 } else { | 141 } else { |
| 159 return Handle<JSFunction>::cast(info); | 142 return Handle<JSFunction>::cast(info); |
| 160 } | 143 } |
| 161 } | 144 } |
| 162 | 145 |
| 163 | 146 |
| 164 Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(int slot) { | 147 Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(TypeFeedbackId id) { |
| 165 Handle<Object> info = GetInfo(slot); | 148 Handle<Object> info = GetInfo(id); |
| 166 if (info->IsAllocationSite()) { | 149 if (info->IsAllocationSite()) { |
| 167 return Handle<JSFunction>(isolate()->global_context()->array_function()); | 150 return Handle<JSFunction>(isolate()->global_context()->array_function()); |
| 168 } else { | 151 } else { |
| 169 return Handle<JSFunction>::cast(info); | 152 return Handle<JSFunction>::cast(info); |
| 170 } | 153 } |
| 171 } | 154 } |
| 172 | 155 |
| 173 | 156 |
| 174 Handle<AllocationSite> TypeFeedbackOracle::GetCallNewAllocationSite(int slot) { | 157 Handle<AllocationSite> TypeFeedbackOracle::GetCallNewAllocationSite( |
| 175 Handle<Object> info = GetInfo(slot); | 158 TypeFeedbackId id) { |
| 159 Handle<Object> info = GetInfo(id); |
| 176 if (info->IsAllocationSite()) { | 160 if (info->IsAllocationSite()) { |
| 177 return Handle<AllocationSite>::cast(info); | 161 return Handle<AllocationSite>::cast(info); |
| 178 } | 162 } |
| 179 return Handle<AllocationSite>::null(); | 163 return Handle<AllocationSite>::null(); |
| 180 } | 164 } |
| 181 | 165 |
| 182 | 166 |
| 183 bool TypeFeedbackOracle::LoadIsBuiltin( | 167 bool TypeFeedbackOracle::LoadIsBuiltin( |
| 184 TypeFeedbackId id, Builtins::Name builtin) { | 168 TypeFeedbackId id, Builtins::Name builtin) { |
| 185 return *GetInfo(id) == isolate()->builtins()->builtin(builtin); | 169 return *GetInfo(id) == isolate()->builtins()->builtin(builtin); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 215 if (!map.is_null() && CanRetainOtherContext(*map, *native_context_)) { | 199 if (!map.is_null() && CanRetainOtherContext(*map, *native_context_)) { |
| 216 map = Handle<Map>::null(); | 200 map = Handle<Map>::null(); |
| 217 } | 201 } |
| 218 } | 202 } |
| 219 | 203 |
| 220 if (code->is_compare_ic_stub()) { | 204 if (code->is_compare_ic_stub()) { |
| 221 int stub_minor_key = code->stub_info(); | 205 int stub_minor_key = code->stub_info(); |
| 222 CompareIC::StubInfoToType( | 206 CompareIC::StubInfoToType( |
| 223 stub_minor_key, left_type, right_type, combined_type, map, zone()); | 207 stub_minor_key, left_type, right_type, combined_type, map, zone()); |
| 224 } else if (code->is_compare_nil_ic_stub()) { | 208 } else if (code->is_compare_nil_ic_stub()) { |
| 225 CompareNilICStub stub(code->extra_ic_state()); | 209 CompareNilICStub stub(code->extended_extra_ic_state()); |
| 226 *combined_type = stub.GetType(zone(), map); | 210 *combined_type = stub.GetType(zone(), map); |
| 227 *left_type = *right_type = stub.GetInputType(zone(), map); | 211 *left_type = *right_type = stub.GetInputType(zone(), map); |
| 228 } | 212 } |
| 229 } | 213 } |
| 230 | 214 |
| 231 | 215 |
| 232 void TypeFeedbackOracle::BinaryType(TypeFeedbackId id, | 216 void TypeFeedbackOracle::BinaryType(TypeFeedbackId id, |
| 233 Type** left, | 217 Type** left, |
| 234 Type** right, | 218 Type** right, |
| 235 Type** result, | 219 Type** result, |
| 236 Maybe<int>* fixed_right_arg, | 220 Maybe<int>* fixed_right_arg, |
| 237 Handle<AllocationSite>* allocation_site, | 221 Handle<AllocationSite>* allocation_site, |
| 238 Token::Value op) { | 222 Token::Value op) { |
| 239 Handle<Object> object = GetInfo(id); | 223 Handle<Object> object = GetInfo(id); |
| 240 if (!object->IsCode()) { | 224 if (!object->IsCode()) { |
| 241 // For some binary ops we don't have ICs, e.g. Token::COMMA, but for the | 225 // For some binary ops we don't have ICs, e.g. Token::COMMA, but for the |
| 242 // operations covered by the BinaryOpIC we should always have them. | 226 // operations covered by the BinaryOpIC we should always have them. |
| 243 ASSERT(op < BinaryOpIC::State::FIRST_TOKEN || | 227 ASSERT(op < BinaryOpIC::State::FIRST_TOKEN || |
| 244 op > BinaryOpIC::State::LAST_TOKEN); | 228 op > BinaryOpIC::State::LAST_TOKEN); |
| 245 *left = *right = *result = Type::None(zone()); | 229 *left = *right = *result = Type::None(zone()); |
| 246 *fixed_right_arg = Maybe<int>(); | 230 *fixed_right_arg = Maybe<int>(); |
| 247 *allocation_site = Handle<AllocationSite>::null(); | 231 *allocation_site = Handle<AllocationSite>::null(); |
| 248 return; | 232 return; |
| 249 } | 233 } |
| 250 Handle<Code> code = Handle<Code>::cast(object); | 234 Handle<Code> code = Handle<Code>::cast(object); |
| 251 ASSERT_EQ(Code::BINARY_OP_IC, code->kind()); | 235 ASSERT_EQ(Code::BINARY_OP_IC, code->kind()); |
| 252 BinaryOpIC::State state(code->extra_ic_state()); | 236 BinaryOpIC::State state(code->extended_extra_ic_state()); |
| 253 ASSERT_EQ(op, state.op()); | 237 ASSERT_EQ(op, state.op()); |
| 254 | 238 |
| 255 *left = state.GetLeftType(zone()); | 239 *left = state.GetLeftType(zone()); |
| 256 *right = state.GetRightType(zone()); | 240 *right = state.GetRightType(zone()); |
| 257 *result = state.GetResultType(zone()); | 241 *result = state.GetResultType(zone()); |
| 258 *fixed_right_arg = state.fixed_right_arg(); | 242 *fixed_right_arg = state.fixed_right_arg(); |
| 259 | 243 |
| 260 AllocationSite* first_allocation_site = code->FindFirstAllocationSite(); | 244 AllocationSite* first_allocation_site = code->FindFirstAllocationSite(); |
| 261 if (first_allocation_site != NULL) { | 245 if (first_allocation_site != NULL) { |
| 262 *allocation_site = handle(first_allocation_site); | 246 *allocation_site = handle(first_allocation_site); |
| 263 } else { | 247 } else { |
| 264 *allocation_site = Handle<AllocationSite>::null(); | 248 *allocation_site = Handle<AllocationSite>::null(); |
| 265 } | 249 } |
| 266 } | 250 } |
| 267 | 251 |
| 268 | 252 |
| 269 Type* TypeFeedbackOracle::CountType(TypeFeedbackId id) { | 253 Type* TypeFeedbackOracle::CountType(TypeFeedbackId id) { |
| 270 Handle<Object> object = GetInfo(id); | 254 Handle<Object> object = GetInfo(id); |
| 271 if (!object->IsCode()) return Type::None(zone()); | 255 if (!object->IsCode()) return Type::None(zone()); |
| 272 Handle<Code> code = Handle<Code>::cast(object); | 256 Handle<Code> code = Handle<Code>::cast(object); |
| 273 ASSERT_EQ(Code::BINARY_OP_IC, code->kind()); | 257 ASSERT_EQ(Code::BINARY_OP_IC, code->kind()); |
| 274 BinaryOpIC::State state(code->extra_ic_state()); | 258 BinaryOpIC::State state(code->extended_extra_ic_state()); |
| 275 return state.GetLeftType(zone()); | 259 return state.GetLeftType(zone()); |
| 276 } | 260 } |
| 277 | 261 |
| 278 | 262 |
| 279 void TypeFeedbackOracle::PropertyReceiverTypes( | 263 void TypeFeedbackOracle::PropertyReceiverTypes( |
| 280 TypeFeedbackId id, Handle<String> name, | 264 TypeFeedbackId id, Handle<String> name, |
| 281 SmallMapList* receiver_types, bool* is_prototype) { | 265 SmallMapList* receiver_types, bool* is_prototype) { |
| 282 receiver_types->Clear(); | 266 receiver_types->Clear(); |
| 283 FunctionPrototypeStub proto_stub(Code::LOAD_IC); | 267 FunctionPrototypeStub proto_stub(Code::LOAD_IC); |
| 284 *is_prototype = LoadIsStub(id, &proto_stub); | 268 *is_prototype = LoadIsStub(id, &proto_stub); |
| 285 if (!*is_prototype) { | 269 if (!*is_prototype) { |
| 286 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); | 270 Code::Flags flags = Code::ComputeFlags( |
| 271 Code::HANDLER, MONOMORPHIC, kNoExtraICState, |
| 272 Code::NORMAL, Code::LOAD_IC); |
| 287 CollectReceiverTypes(id, name, flags, receiver_types); | 273 CollectReceiverTypes(id, name, flags, receiver_types); |
| 288 } | 274 } |
| 289 } | 275 } |
| 290 | 276 |
| 291 | 277 |
| 292 void TypeFeedbackOracle::KeyedPropertyReceiverTypes( | 278 void TypeFeedbackOracle::KeyedPropertyReceiverTypes( |
| 293 TypeFeedbackId id, SmallMapList* receiver_types, bool* is_string) { | 279 TypeFeedbackId id, SmallMapList* receiver_types, bool* is_string) { |
| 294 receiver_types->Clear(); | 280 receiver_types->Clear(); |
| 295 *is_string = false; | 281 *is_string = false; |
| 296 if (LoadIsBuiltin(id, Builtins::kKeyedLoadIC_String)) { | 282 if (LoadIsBuiltin(id, Builtins::kKeyedLoadIC_String)) { |
| 297 *is_string = true; | 283 *is_string = true; |
| 298 } else { | 284 } else { |
| 299 CollectReceiverTypes(id, receiver_types); | 285 CollectReceiverTypes(id, receiver_types); |
| 300 } | 286 } |
| 301 } | 287 } |
| 302 | 288 |
| 303 | 289 |
| 304 void TypeFeedbackOracle::AssignmentReceiverTypes( | 290 void TypeFeedbackOracle::AssignmentReceiverTypes( |
| 305 TypeFeedbackId id, Handle<String> name, SmallMapList* receiver_types) { | 291 TypeFeedbackId id, Handle<String> name, SmallMapList* receiver_types) { |
| 306 receiver_types->Clear(); | 292 receiver_types->Clear(); |
| 307 Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC); | 293 Code::Flags flags = Code::ComputeFlags( |
| 294 Code::HANDLER, MONOMORPHIC, kNoExtraICState, |
| 295 Code::NORMAL, Code::STORE_IC); |
| 308 CollectReceiverTypes(id, name, flags, receiver_types); | 296 CollectReceiverTypes(id, name, flags, receiver_types); |
| 309 } | 297 } |
| 310 | 298 |
| 311 | 299 |
| 312 void TypeFeedbackOracle::KeyedAssignmentReceiverTypes( | 300 void TypeFeedbackOracle::KeyedAssignmentReceiverTypes( |
| 313 TypeFeedbackId id, SmallMapList* receiver_types, | 301 TypeFeedbackId id, SmallMapList* receiver_types, |
| 314 KeyedAccessStoreMode* store_mode) { | 302 KeyedAccessStoreMode* store_mode) { |
| 315 receiver_types->Clear(); | 303 receiver_types->Clear(); |
| 316 CollectReceiverTypes(id, receiver_types); | 304 CollectReceiverTypes(id, receiver_types); |
| 317 *store_mode = GetStoreMode(id); | 305 *store_mode = GetStoreMode(id); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 // themselves are not GC-safe, so we first get all infos, then we create the | 402 // themselves are not GC-safe, so we first get all infos, then we create the |
| 415 // dictionary (possibly triggering GC), and finally we relocate the collected | 403 // dictionary (possibly triggering GC), and finally we relocate the collected |
| 416 // infos before we process them. | 404 // infos before we process them. |
| 417 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { | 405 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { |
| 418 DisallowHeapAllocation no_allocation; | 406 DisallowHeapAllocation no_allocation; |
| 419 ZoneList<RelocInfo> infos(16, zone()); | 407 ZoneList<RelocInfo> infos(16, zone()); |
| 420 HandleScope scope(isolate()); | 408 HandleScope scope(isolate()); |
| 421 GetRelocInfos(code, &infos); | 409 GetRelocInfos(code, &infos); |
| 422 CreateDictionary(code, &infos); | 410 CreateDictionary(code, &infos); |
| 423 ProcessRelocInfos(&infos); | 411 ProcessRelocInfos(&infos); |
| 412 ProcessTypeFeedbackCells(code); |
| 424 // Allocate handle in the parent scope. | 413 // Allocate handle in the parent scope. |
| 425 dictionary_ = scope.CloseAndEscape(dictionary_); | 414 dictionary_ = scope.CloseAndEscape(dictionary_); |
| 426 } | 415 } |
| 427 | 416 |
| 428 | 417 |
| 429 void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code, | 418 void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code, |
| 430 ZoneList<RelocInfo>* infos) { | 419 ZoneList<RelocInfo>* infos) { |
| 431 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); | 420 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); |
| 432 for (RelocIterator it(*code, mask); !it.done(); it.next()) { | 421 for (RelocIterator it(*code, mask); !it.done(); it.next()) { |
| 433 infos->Add(*it.rinfo(), zone()); | 422 infos->Add(*it.rinfo(), zone()); |
| 434 } | 423 } |
| 435 } | 424 } |
| 436 | 425 |
| 437 | 426 |
| 438 void TypeFeedbackOracle::CreateDictionary(Handle<Code> code, | 427 void TypeFeedbackOracle::CreateDictionary(Handle<Code> code, |
| 439 ZoneList<RelocInfo>* infos) { | 428 ZoneList<RelocInfo>* infos) { |
| 440 AllowHeapAllocation allocation_allowed; | 429 AllowHeapAllocation allocation_allowed; |
| 430 int cell_count = code->type_feedback_info()->IsTypeFeedbackInfo() |
| 431 ? TypeFeedbackInfo::cast(code->type_feedback_info())-> |
| 432 type_feedback_cells()->CellCount() |
| 433 : 0; |
| 434 int length = infos->length() + cell_count; |
| 441 byte* old_start = code->instruction_start(); | 435 byte* old_start = code->instruction_start(); |
| 442 dictionary_ = | 436 dictionary_ = isolate()->factory()->NewUnseededNumberDictionary(length); |
| 443 isolate()->factory()->NewUnseededNumberDictionary(infos->length()); | |
| 444 byte* new_start = code->instruction_start(); | 437 byte* new_start = code->instruction_start(); |
| 445 RelocateRelocInfos(infos, old_start, new_start); | 438 RelocateRelocInfos(infos, old_start, new_start); |
| 446 } | 439 } |
| 447 | 440 |
| 448 | 441 |
| 449 void TypeFeedbackOracle::RelocateRelocInfos(ZoneList<RelocInfo>* infos, | 442 void TypeFeedbackOracle::RelocateRelocInfos(ZoneList<RelocInfo>* infos, |
| 450 byte* old_start, | 443 byte* old_start, |
| 451 byte* new_start) { | 444 byte* new_start) { |
| 452 for (int i = 0; i < infos->length(); i++) { | 445 for (int i = 0; i < infos->length(); i++) { |
| 453 RelocInfo* info = &(*infos)[i]; | 446 RelocInfo* info = &(*infos)[i]; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 475 SetInfo(ast_id, target); | 468 SetInfo(ast_id, target); |
| 476 break; | 469 break; |
| 477 | 470 |
| 478 default: | 471 default: |
| 479 break; | 472 break; |
| 480 } | 473 } |
| 481 } | 474 } |
| 482 } | 475 } |
| 483 | 476 |
| 484 | 477 |
| 478 void TypeFeedbackOracle::ProcessTypeFeedbackCells(Handle<Code> code) { |
| 479 Object* raw_info = code->type_feedback_info(); |
| 480 if (!raw_info->IsTypeFeedbackInfo()) return; |
| 481 Handle<TypeFeedbackCells> cache( |
| 482 TypeFeedbackInfo::cast(raw_info)->type_feedback_cells()); |
| 483 for (int i = 0; i < cache->CellCount(); i++) { |
| 484 TypeFeedbackId ast_id = cache->AstId(i); |
| 485 Cell* cell = cache->GetCell(i); |
| 486 Object* value = cell->value(); |
| 487 if (value->IsSmi() || |
| 488 value->IsAllocationSite() || |
| 489 (value->IsJSFunction() && |
| 490 !CanRetainOtherContext(JSFunction::cast(value), |
| 491 *native_context_))) { |
| 492 SetInfo(ast_id, cell); |
| 493 } |
| 494 } |
| 495 } |
| 496 |
| 497 |
| 485 void TypeFeedbackOracle::SetInfo(TypeFeedbackId ast_id, Object* target) { | 498 void TypeFeedbackOracle::SetInfo(TypeFeedbackId ast_id, Object* target) { |
| 486 ASSERT(dictionary_->FindEntry(IdToKey(ast_id)) == | 499 ASSERT(dictionary_->FindEntry(IdToKey(ast_id)) == |
| 487 UnseededNumberDictionary::kNotFound); | 500 UnseededNumberDictionary::kNotFound); |
| 488 MaybeObject* maybe_result = dictionary_->AtNumberPut(IdToKey(ast_id), target); | 501 MaybeObject* maybe_result = dictionary_->AtNumberPut(IdToKey(ast_id), target); |
| 489 USE(maybe_result); | 502 USE(maybe_result); |
| 490 #ifdef DEBUG | 503 #ifdef DEBUG |
| 491 Object* result = NULL; | 504 Object* result = NULL; |
| 492 // Dictionary has been allocated with sufficient size for all elements. | 505 // Dictionary has been allocated with sufficient size for all elements. |
| 493 ASSERT(maybe_result->ToObject(&result)); | 506 ASSERT(maybe_result->ToObject(&result)); |
| 494 ASSERT(*dictionary_ == result); | 507 ASSERT(*dictionary_ == result); |
| 495 #endif | 508 #endif |
| 496 } | 509 } |
| 497 | 510 |
| 498 | 511 |
| 499 } } // namespace v8::internal | 512 } } // namespace v8::internal |
| OLD | NEW |