| 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) { |
| 52 BuildDictionary(code); | 50 BuildDictionary(code); |
| 53 ASSERT(dictionary_->IsDictionary()); | 51 ASSERT(dictionary_->IsDictionary()); |
| 54 } | 52 } |
| 55 | 53 |
| 56 | 54 |
| 57 static uint32_t IdToKey(TypeFeedbackId ast_id) { | 55 static uint32_t IdToKey(TypeFeedbackId ast_id) { |
| 58 return static_cast<uint32_t>(ast_id.ToInt()); | 56 return static_cast<uint32_t>(ast_id.ToInt()); |
| 59 } | 57 } |
| 60 | 58 |
| 61 | 59 |
| 62 Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) { | 60 Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) { |
| 63 int entry = dictionary_->FindEntry(IdToKey(ast_id)); | 61 int entry = dictionary_->FindEntry(IdToKey(ast_id)); |
| 64 if (entry != UnseededNumberDictionary::kNotFound) { | 62 if (entry != UnseededNumberDictionary::kNotFound) { |
| 65 Object* value = dictionary_->ValueAt(entry); | 63 Object* value = dictionary_->ValueAt(entry); |
| 66 if (value->IsCell()) { | 64 if (value->IsCell()) { |
| 67 Cell* cell = Cell::cast(value); | 65 Cell* cell = Cell::cast(value); |
| 68 return Handle<Object>(cell->value(), isolate_); | 66 return Handle<Object>(cell->value(), isolate()); |
| 69 } else { | 67 } else { |
| 70 return Handle<Object>(value, isolate_); | 68 return Handle<Object>(value, isolate()); |
| 71 } | 69 } |
| 72 } | 70 } |
| 73 return Handle<Object>::cast(isolate_->factory()->undefined_value()); | 71 return Handle<Object>::cast(isolate()->factory()->undefined_value()); |
| 74 } | 72 } |
| 75 | 73 |
| 76 | 74 |
| 77 Handle<Cell> TypeFeedbackOracle::GetInfoCell( | |
| 78 TypeFeedbackId ast_id) { | |
| 79 int entry = dictionary_->FindEntry(IdToKey(ast_id)); | |
| 80 if (entry != UnseededNumberDictionary::kNotFound) { | |
| 81 Cell* cell = Cell::cast(dictionary_->ValueAt(entry)); | |
| 82 return Handle<Cell>(cell, isolate_); | |
| 83 } | |
| 84 return Handle<Cell>::null(); | |
| 85 } | |
| 86 | |
| 87 | |
| 88 bool TypeFeedbackOracle::LoadIsUninitialized(TypeFeedbackId id) { | 75 bool TypeFeedbackOracle::LoadIsUninitialized(TypeFeedbackId id) { |
| 89 Handle<Object> maybe_code = GetInfo(id); | 76 Handle<Object> maybe_code = GetInfo(id); |
| 90 if (maybe_code->IsCode()) { | 77 if (maybe_code->IsCode()) { |
| 91 Handle<Code> code = Handle<Code>::cast(maybe_code); | 78 Handle<Code> code = Handle<Code>::cast(maybe_code); |
| 92 return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; | 79 return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; |
| 93 } | 80 } |
| 94 return false; | 81 return false; |
| 95 } | 82 } |
| 96 | 83 |
| 97 | 84 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 } | 159 } |
| 173 } | 160 } |
| 174 return STANDARD_STORE; | 161 return STANDARD_STORE; |
| 175 } | 162 } |
| 176 | 163 |
| 177 | 164 |
| 178 void TypeFeedbackOracle::CallReceiverTypes(TypeFeedbackId id, | 165 void TypeFeedbackOracle::CallReceiverTypes(TypeFeedbackId id, |
| 179 Handle<String> name, | 166 Handle<String> name, |
| 180 int arity, | 167 int arity, |
| 181 SmallMapList* types) { | 168 SmallMapList* types) { |
| 182 // Note: Currently we do not take string extra ic data into account | |
| 183 // here. | |
| 184 Code::Flags flags = Code::ComputeMonomorphicFlags( | 169 Code::Flags flags = Code::ComputeMonomorphicFlags( |
| 185 Code::CALL_IC, kNoExtraICState, OWN_MAP, Code::NORMAL, arity); | 170 Code::CALL_IC, kNoExtraICState, OWN_MAP, Code::NORMAL, arity); |
| 186 CollectReceiverTypes(id, name, flags, types); | 171 CollectReceiverTypes(id, name, flags, types); |
| 187 } | 172 } |
| 188 | 173 |
| 189 | 174 |
| 190 CheckType TypeFeedbackOracle::GetCallCheckType(TypeFeedbackId id) { | 175 CheckType TypeFeedbackOracle::GetCallCheckType(TypeFeedbackId id) { |
| 191 Handle<Object> value = GetInfo(id); | 176 Handle<Object> value = GetInfo(id); |
| 192 if (!value->IsSmi()) return RECEIVER_MAP_CHECK; | 177 if (!value->IsSmi()) return RECEIVER_MAP_CHECK; |
| 193 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value()); | 178 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value()); |
| 194 ASSERT(check != RECEIVER_MAP_CHECK); | 179 ASSERT(check != RECEIVER_MAP_CHECK); |
| 195 return check; | 180 return check; |
| 196 } | 181 } |
| 197 | 182 |
| 198 | 183 |
| 199 Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(TypeFeedbackId id) { | 184 Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(TypeFeedbackId id) { |
| 200 Handle<Object> info = GetInfo(id); | 185 Handle<Object> info = GetInfo(id); |
| 201 if (info->IsAllocationSite()) { | 186 if (info->IsAllocationSite()) { |
| 202 return Handle<JSFunction>(isolate_->global_context()->array_function()); | 187 return Handle<JSFunction>(isolate()->global_context()->array_function()); |
| 203 } else { | 188 } else { |
| 204 return Handle<JSFunction>::cast(info); | 189 return Handle<JSFunction>::cast(info); |
| 205 } | 190 } |
| 206 } | 191 } |
| 207 | 192 |
| 208 | 193 |
| 209 Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(TypeFeedbackId id) { | 194 Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(TypeFeedbackId id) { |
| 210 Handle<Object> info = GetInfo(id); | 195 Handle<Object> info = GetInfo(id); |
| 211 if (info->IsAllocationSite()) { | 196 if (info->IsAllocationSite()) { |
| 212 return Handle<JSFunction>(isolate_->global_context()->array_function()); | 197 return Handle<JSFunction>(isolate()->global_context()->array_function()); |
| 213 } else { | 198 } else { |
| 214 return Handle<JSFunction>::cast(info); | 199 return Handle<JSFunction>::cast(info); |
| 215 } | 200 } |
| 216 } | 201 } |
| 217 | 202 |
| 218 | 203 |
| 219 Handle<Cell> TypeFeedbackOracle::GetCallNewAllocationInfoCell( | 204 Handle<AllocationSite> TypeFeedbackOracle::GetCallNewAllocationSite( |
| 220 TypeFeedbackId id) { | 205 TypeFeedbackId id) { |
| 221 return GetInfoCell(id); | 206 Handle<Object> info = GetInfo(id); |
| 207 if (info->IsAllocationSite()) { |
| 208 return Handle<AllocationSite>::cast(info); |
| 209 } |
| 210 return Handle<AllocationSite>::null(); |
| 222 } | 211 } |
| 223 | 212 |
| 224 | 213 |
| 225 bool TypeFeedbackOracle::LoadIsBuiltin( | 214 bool TypeFeedbackOracle::LoadIsBuiltin( |
| 226 TypeFeedbackId id, Builtins::Name builtin) { | 215 TypeFeedbackId id, Builtins::Name builtin) { |
| 227 return *GetInfo(id) == isolate_->builtins()->builtin(builtin); | 216 return *GetInfo(id) == isolate()->builtins()->builtin(builtin); |
| 228 } | 217 } |
| 229 | 218 |
| 230 | 219 |
| 231 bool TypeFeedbackOracle::LoadIsStub(TypeFeedbackId id, ICStub* stub) { | 220 bool TypeFeedbackOracle::LoadIsStub(TypeFeedbackId id, ICStub* stub) { |
| 232 Handle<Object> object = GetInfo(id); | 221 Handle<Object> object = GetInfo(id); |
| 233 if (!object->IsCode()) return false; | 222 if (!object->IsCode()) return false; |
| 234 Handle<Code> code = Handle<Code>::cast(object); | 223 Handle<Code> code = Handle<Code>::cast(object); |
| 235 if (!code->is_load_stub()) return false; | 224 if (!code->is_load_stub()) return false; |
| 236 if (code->ic_state() != MONOMORPHIC) return false; | 225 if (code->ic_state() != MONOMORPHIC) return false; |
| 237 return stub->Describes(*code); | 226 return stub->Describes(*code); |
| 238 } | 227 } |
| 239 | 228 |
| 240 | 229 |
| 241 void TypeFeedbackOracle::CompareType(TypeFeedbackId id, | 230 void TypeFeedbackOracle::CompareType(TypeFeedbackId id, |
| 242 Handle<Type>* left_type, | 231 Type** left_type, |
| 243 Handle<Type>* right_type, | 232 Type** right_type, |
| 244 Handle<Type>* combined_type) { | 233 Type** combined_type) { |
| 245 Handle<Object> info = GetInfo(id); | 234 Handle<Object> info = GetInfo(id); |
| 246 if (!info->IsCode()) { | 235 if (!info->IsCode()) { |
| 247 // For some comparisons we don't have ICs, e.g. LiteralCompareTypeof. | 236 // For some comparisons we don't have ICs, e.g. LiteralCompareTypeof. |
| 248 *left_type = *right_type = *combined_type = Type::None(isolate_); | 237 *left_type = *right_type = *combined_type = Type::None(zone()); |
| 249 return; | 238 return; |
| 250 } | 239 } |
| 251 Handle<Code> code = Handle<Code>::cast(info); | 240 Handle<Code> code = Handle<Code>::cast(info); |
| 252 | 241 |
| 253 Handle<Map> map; | 242 Handle<Map> map; |
| 254 Map* raw_map = code->FindFirstMap(); | 243 Map* raw_map = code->FindFirstMap(); |
| 255 if (raw_map != NULL) { | 244 if (raw_map != NULL) { |
| 256 map = Map::CurrentMapForDeprecated(handle(raw_map)); | 245 map = Map::CurrentMapForDeprecated(handle(raw_map)); |
| 257 if (!map.is_null() && CanRetainOtherContext(*map, *native_context_)) { | 246 if (!map.is_null() && CanRetainOtherContext(*map, *native_context_)) { |
| 258 map = Handle<Map>::null(); | 247 map = Handle<Map>::null(); |
| 259 } | 248 } |
| 260 } | 249 } |
| 261 | 250 |
| 262 if (code->is_compare_ic_stub()) { | 251 if (code->is_compare_ic_stub()) { |
| 263 int stub_minor_key = code->stub_info(); | 252 int stub_minor_key = code->stub_info(); |
| 264 CompareIC::StubInfoToType( | 253 CompareIC::StubInfoToType( |
| 265 stub_minor_key, left_type, right_type, combined_type, map, isolate()); | 254 stub_minor_key, left_type, right_type, combined_type, map, zone()); |
| 266 } else if (code->is_compare_nil_ic_stub()) { | 255 } else if (code->is_compare_nil_ic_stub()) { |
| 267 CompareNilICStub stub(code->extended_extra_ic_state()); | 256 CompareNilICStub stub(code->extended_extra_ic_state()); |
| 268 *combined_type = stub.GetType(isolate_, map); | 257 *combined_type = stub.GetType(zone(), map); |
| 269 *left_type = *right_type = stub.GetInputType(isolate_, map); | 258 *left_type = *right_type = stub.GetInputType(zone(), map); |
| 270 } | 259 } |
| 271 } | 260 } |
| 272 | 261 |
| 273 | 262 |
| 274 void TypeFeedbackOracle::BinaryType(TypeFeedbackId id, | 263 void TypeFeedbackOracle::BinaryType(TypeFeedbackId id, |
| 275 Handle<Type>* left, | 264 Type** left, |
| 276 Handle<Type>* right, | 265 Type** right, |
| 277 Handle<Type>* result, | 266 Type** result, |
| 278 Maybe<int>* fixed_right_arg, | 267 Maybe<int>* fixed_right_arg, |
| 279 Handle<AllocationSite>* allocation_site, | 268 Handle<AllocationSite>* allocation_site, |
| 280 Token::Value op) { | 269 Token::Value op) { |
| 281 Handle<Object> object = GetInfo(id); | 270 Handle<Object> object = GetInfo(id); |
| 282 if (!object->IsCode()) { | 271 if (!object->IsCode()) { |
| 283 // For some binary ops we don't have ICs, e.g. Token::COMMA, but for the | 272 // For some binary ops we don't have ICs, e.g. Token::COMMA, but for the |
| 284 // operations covered by the BinaryOpIC we should always have them. | 273 // operations covered by the BinaryOpIC we should always have them. |
| 285 ASSERT(op < BinaryOpIC::State::FIRST_TOKEN || | 274 ASSERT(op < BinaryOpIC::State::FIRST_TOKEN || |
| 286 op > BinaryOpIC::State::LAST_TOKEN); | 275 op > BinaryOpIC::State::LAST_TOKEN); |
| 287 *left = *right = *result = Type::None(isolate_); | 276 *left = *right = *result = Type::None(zone()); |
| 288 *fixed_right_arg = Maybe<int>(); | 277 *fixed_right_arg = Maybe<int>(); |
| 289 *allocation_site = Handle<AllocationSite>::null(); | 278 *allocation_site = Handle<AllocationSite>::null(); |
| 290 return; | 279 return; |
| 291 } | 280 } |
| 292 Handle<Code> code = Handle<Code>::cast(object); | 281 Handle<Code> code = Handle<Code>::cast(object); |
| 293 ASSERT_EQ(Code::BINARY_OP_IC, code->kind()); | 282 ASSERT_EQ(Code::BINARY_OP_IC, code->kind()); |
| 294 BinaryOpIC::State state(code->extended_extra_ic_state()); | 283 BinaryOpIC::State state(code->extended_extra_ic_state()); |
| 295 ASSERT_EQ(op, state.op()); | 284 ASSERT_EQ(op, state.op()); |
| 296 | 285 |
| 297 *left = state.GetLeftType(isolate()); | 286 *left = state.GetLeftType(zone()); |
| 298 *right = state.GetRightType(isolate()); | 287 *right = state.GetRightType(zone()); |
| 299 *result = state.GetResultType(isolate()); | 288 *result = state.GetResultType(zone()); |
| 300 *fixed_right_arg = state.fixed_right_arg(); | 289 *fixed_right_arg = state.fixed_right_arg(); |
| 301 | 290 |
| 302 AllocationSite* first_allocation_site = code->FindFirstAllocationSite(); | 291 AllocationSite* first_allocation_site = code->FindFirstAllocationSite(); |
| 303 if (first_allocation_site != NULL) { | 292 if (first_allocation_site != NULL) { |
| 304 *allocation_site = handle(first_allocation_site); | 293 *allocation_site = handle(first_allocation_site); |
| 305 } else { | 294 } else { |
| 306 *allocation_site = Handle<AllocationSite>::null(); | 295 *allocation_site = Handle<AllocationSite>::null(); |
| 307 } | 296 } |
| 308 } | 297 } |
| 309 | 298 |
| 310 | 299 |
| 311 Handle<Type> TypeFeedbackOracle::CountType(TypeFeedbackId id) { | 300 Type* TypeFeedbackOracle::CountType(TypeFeedbackId id) { |
| 312 Handle<Object> object = GetInfo(id); | 301 Handle<Object> object = GetInfo(id); |
| 313 if (!object->IsCode()) return Type::None(isolate_); | 302 if (!object->IsCode()) return Type::None(zone()); |
| 314 Handle<Code> code = Handle<Code>::cast(object); | 303 Handle<Code> code = Handle<Code>::cast(object); |
| 315 ASSERT_EQ(Code::BINARY_OP_IC, code->kind()); | 304 ASSERT_EQ(Code::BINARY_OP_IC, code->kind()); |
| 316 BinaryOpIC::State state(code->extended_extra_ic_state()); | 305 BinaryOpIC::State state(code->extended_extra_ic_state()); |
| 317 return state.GetLeftType(isolate()); | 306 return state.GetLeftType(zone()); |
| 318 } | 307 } |
| 319 | 308 |
| 320 | 309 |
| 321 void TypeFeedbackOracle::PropertyReceiverTypes( | 310 void TypeFeedbackOracle::PropertyReceiverTypes( |
| 322 TypeFeedbackId id, Handle<String> name, | 311 TypeFeedbackId id, Handle<String> name, |
| 323 SmallMapList* receiver_types, bool* is_prototype) { | 312 SmallMapList* receiver_types, bool* is_prototype) { |
| 324 receiver_types->Clear(); | 313 receiver_types->Clear(); |
| 325 FunctionPrototypeStub proto_stub(Code::LOAD_IC); | 314 FunctionPrototypeStub proto_stub(Code::LOAD_IC); |
| 326 *is_prototype = LoadIsStub(id, &proto_stub); | 315 *is_prototype = LoadIsStub(id, &proto_stub); |
| 327 if (!*is_prototype) { | 316 if (!*is_prototype) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 SmallMapList* types) { | 366 SmallMapList* types) { |
| 378 Handle<Object> object = GetInfo(ast_id); | 367 Handle<Object> object = GetInfo(ast_id); |
| 379 if (object->IsUndefined() || object->IsSmi()) return; | 368 if (object->IsUndefined() || object->IsSmi()) return; |
| 380 | 369 |
| 381 ASSERT(object->IsCode()); | 370 ASSERT(object->IsCode()); |
| 382 Handle<Code> code(Handle<Code>::cast(object)); | 371 Handle<Code> code(Handle<Code>::cast(object)); |
| 383 | 372 |
| 384 if (FLAG_collect_megamorphic_maps_from_stub_cache && | 373 if (FLAG_collect_megamorphic_maps_from_stub_cache && |
| 385 code->ic_state() == MEGAMORPHIC) { | 374 code->ic_state() == MEGAMORPHIC) { |
| 386 types->Reserve(4, zone()); | 375 types->Reserve(4, zone()); |
| 387 isolate_->stub_cache()->CollectMatchingMaps( | 376 isolate()->stub_cache()->CollectMatchingMaps( |
| 388 types, name, flags, native_context_, zone()); | 377 types, name, flags, native_context_, zone()); |
| 389 } else { | 378 } else { |
| 390 CollectReceiverTypes(ast_id, types); | 379 CollectReceiverTypes(ast_id, types); |
| 391 } | 380 } |
| 392 } | 381 } |
| 393 | 382 |
| 394 | 383 |
| 395 // Check if a map originates from a given native context. We use this | 384 // Check if a map originates from a given native context. We use this |
| 396 // information to filter out maps from different context to avoid | 385 // information to filter out maps from different context to avoid |
| 397 // retaining objects from different tabs in Chrome via optimized code. | 386 // retaining objects from different tabs in Chrome via optimized code. |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 456 } | 445 } |
| 457 | 446 |
| 458 | 447 |
| 459 // Things are a bit tricky here: The iterator for the RelocInfos and the infos | 448 // Things are a bit tricky here: The iterator for the RelocInfos and the infos |
| 460 // themselves are not GC-safe, so we first get all infos, then we create the | 449 // themselves are not GC-safe, so we first get all infos, then we create the |
| 461 // dictionary (possibly triggering GC), and finally we relocate the collected | 450 // dictionary (possibly triggering GC), and finally we relocate the collected |
| 462 // infos before we process them. | 451 // infos before we process them. |
| 463 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { | 452 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { |
| 464 DisallowHeapAllocation no_allocation; | 453 DisallowHeapAllocation no_allocation; |
| 465 ZoneList<RelocInfo> infos(16, zone()); | 454 ZoneList<RelocInfo> infos(16, zone()); |
| 466 HandleScope scope(isolate_); | 455 HandleScope scope(isolate()); |
| 467 GetRelocInfos(code, &infos); | 456 GetRelocInfos(code, &infos); |
| 468 CreateDictionary(code, &infos); | 457 CreateDictionary(code, &infos); |
| 469 ProcessRelocInfos(&infos); | 458 ProcessRelocInfos(&infos); |
| 470 ProcessTypeFeedbackCells(code); | 459 ProcessTypeFeedbackCells(code); |
| 471 // Allocate handle in the parent scope. | 460 // Allocate handle in the parent scope. |
| 472 dictionary_ = scope.CloseAndEscape(dictionary_); | 461 dictionary_ = scope.CloseAndEscape(dictionary_); |
| 473 } | 462 } |
| 474 | 463 |
| 475 | 464 |
| 476 void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code, | 465 void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code, |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 568 #ifdef DEBUG | 557 #ifdef DEBUG |
| 569 Object* result = NULL; | 558 Object* result = NULL; |
| 570 // Dictionary has been allocated with sufficient size for all elements. | 559 // Dictionary has been allocated with sufficient size for all elements. |
| 571 ASSERT(maybe_result->ToObject(&result)); | 560 ASSERT(maybe_result->ToObject(&result)); |
| 572 ASSERT(*dictionary_ == result); | 561 ASSERT(*dictionary_ == result); |
| 573 #endif | 562 #endif |
| 574 } | 563 } |
| 575 | 564 |
| 576 | 565 |
| 577 } } // namespace v8::internal | 566 } } // namespace v8::internal |
| OLD | NEW |