| 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 24 matching lines...) Expand all Loading... |
| 35 #include "stub-cache.h" | 35 #include "stub-cache.h" |
| 36 #include "type-info.h" | 36 #include "type-info.h" |
| 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 TypeInfo TypeInfo::TypeFromValue(Handle<Object> value) { | 45 TypeInfo TypeInfo::FromValue(Handle<Object> value) { |
| 46 TypeInfo info; | |
| 47 if (value->IsSmi()) { | 46 if (value->IsSmi()) { |
| 48 info = TypeInfo::Smi(); | 47 return TypeInfo::Smi(); |
| 49 } else if (value->IsHeapNumber()) { | 48 } else if (value->IsHeapNumber()) { |
| 50 info = TypeInfo::IsInt32Double(HeapNumber::cast(*value)->value()) | 49 return TypeInfo::IsInt32Double(HeapNumber::cast(*value)->value()) |
| 51 ? TypeInfo::Integer32() | 50 ? TypeInfo::Integer32() |
| 52 : TypeInfo::Double(); | 51 : TypeInfo::Double(); |
| 53 } else if (value->IsString()) { | 52 } else if (value->IsString()) { |
| 54 info = TypeInfo::String(); | 53 return TypeInfo::String(); |
| 55 } else { | |
| 56 info = TypeInfo::Unknown(); | |
| 57 } | 54 } |
| 58 return info; | 55 return TypeInfo::Unknown(); |
| 59 } | 56 } |
| 60 | 57 |
| 61 | 58 |
| 62 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, | 59 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, |
| 63 Handle<Context> native_context, | 60 Handle<Context> native_context, |
| 64 Isolate* isolate, | 61 Isolate* isolate, |
| 65 Zone* zone) | 62 Zone* zone) |
| 66 : native_context_(native_context), | 63 : native_context_(native_context), |
| 67 isolate_(isolate), | 64 isolate_(isolate), |
| 68 zone_(zone) { | 65 zone_(zone) { |
| 69 BuildDictionary(code); | 66 BuildDictionary(code); |
| 70 ASSERT(dictionary_->IsDictionary()); | 67 ASSERT(dictionary_->IsDictionary()); |
| 71 } | 68 } |
| 72 | 69 |
| 73 | 70 |
| 74 static uint32_t IdToKey(TypeFeedbackId ast_id) { | 71 static uint32_t IdToKey(TypeFeedbackId ast_id) { |
| 75 return static_cast<uint32_t>(ast_id.ToInt()); | 72 return static_cast<uint32_t>(ast_id.ToInt()); |
| 76 } | 73 } |
| 77 | 74 |
| 78 | 75 |
| 79 Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) { | 76 Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) { |
| 80 int entry = dictionary_->FindEntry(IdToKey(ast_id)); | 77 int entry = dictionary_->FindEntry(IdToKey(ast_id)); |
| 81 if (entry != UnseededNumberDictionary::kNotFound) { | 78 if (entry != UnseededNumberDictionary::kNotFound) { |
| 82 Object* value = dictionary_->ValueAt(entry); | 79 Object* value = dictionary_->ValueAt(entry); |
| 83 if (value->IsJSGlobalPropertyCell()) { | 80 if (value->IsCell()) { |
| 84 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(value); | 81 Cell* cell = Cell::cast(value); |
| 85 return Handle<Object>(cell->value(), isolate_); | 82 return Handle<Object>(cell->value(), isolate_); |
| 86 } else { | 83 } else { |
| 87 return Handle<Object>(value, isolate_); | 84 return Handle<Object>(value, isolate_); |
| 88 } | 85 } |
| 89 } | 86 } |
| 90 return Handle<Object>::cast(isolate_->factory()->undefined_value()); | 87 return Handle<Object>::cast(isolate_->factory()->undefined_value()); |
| 91 } | 88 } |
| 92 | 89 |
| 93 | 90 |
| 94 Handle<JSGlobalPropertyCell> TypeFeedbackOracle::GetInfoCell( | 91 Handle<Cell> TypeFeedbackOracle::GetInfoCell( |
| 95 TypeFeedbackId ast_id) { | 92 TypeFeedbackId ast_id) { |
| 96 int entry = dictionary_->FindEntry(IdToKey(ast_id)); | 93 int entry = dictionary_->FindEntry(IdToKey(ast_id)); |
| 97 if (entry != UnseededNumberDictionary::kNotFound) { | 94 if (entry != UnseededNumberDictionary::kNotFound) { |
| 98 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast( | 95 Cell* cell = Cell::cast(dictionary_->ValueAt(entry)); |
| 99 dictionary_->ValueAt(entry)); | 96 return Handle<Cell>(cell, isolate_); |
| 100 return Handle<JSGlobalPropertyCell>(cell, isolate_); | |
| 101 } | 97 } |
| 102 return Handle<JSGlobalPropertyCell>::null(); | 98 return Handle<Cell>::null(); |
| 103 } | 99 } |
| 104 | 100 |
| 105 | 101 |
| 106 bool TypeFeedbackOracle::LoadIsUninitialized(Property* expr) { | 102 bool TypeFeedbackOracle::LoadIsUninitialized(Property* expr) { |
| 107 Handle<Object> map_or_code = GetInfo(expr->PropertyFeedbackId()); | 103 Handle<Object> map_or_code = GetInfo(expr->PropertyFeedbackId()); |
| 108 if (map_or_code->IsMap()) return false; | 104 if (map_or_code->IsMap()) return false; |
| 109 if (map_or_code->IsCode()) { | 105 if (map_or_code->IsCode()) { |
| 110 Handle<Code> code = Handle<Code>::cast(map_or_code); | 106 Handle<Code> code = Handle<Code>::cast(map_or_code); |
| 111 return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; | 107 return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; |
| 112 } | 108 } |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 Handle<Code> code = Handle<Code>::cast(map_or_code); | 224 Handle<Code> code = Handle<Code>::cast(map_or_code); |
| 229 Map* map = code->FindFirstMap()->CurrentMapForDeprecated(); | 225 Map* map = code->FindFirstMap()->CurrentMapForDeprecated(); |
| 230 return map == NULL || CanRetainOtherContext(map, *native_context_) | 226 return map == NULL || CanRetainOtherContext(map, *native_context_) |
| 231 ? Handle<Map>::null() | 227 ? Handle<Map>::null() |
| 232 : Handle<Map>(map); | 228 : Handle<Map>(map); |
| 233 } | 229 } |
| 234 return Handle<Map>::cast(map_or_code); | 230 return Handle<Map>::cast(map_or_code); |
| 235 } | 231 } |
| 236 | 232 |
| 237 | 233 |
| 238 Handle<Map> TypeFeedbackOracle::CompareNilMonomorphicReceiverType( | |
| 239 CompareOperation* expr) { | |
| 240 Handle<Object> maybe_code = GetInfo(expr->CompareOperationFeedbackId()); | |
| 241 if (maybe_code->IsCode()) { | |
| 242 Map* map = Handle<Code>::cast(maybe_code)->FindFirstMap(); | |
| 243 if (map == NULL) return Handle<Map>(); | |
| 244 map = map->CurrentMapForDeprecated(); | |
| 245 return map == NULL || CanRetainOtherContext(map, *native_context_) | |
| 246 ? Handle<Map>() | |
| 247 : Handle<Map>(map); | |
| 248 } else if (maybe_code->IsMap()) { | |
| 249 ASSERT(!Handle<Map>::cast(maybe_code)->is_deprecated()); | |
| 250 return Handle<Map>::cast(maybe_code); | |
| 251 } | |
| 252 return Handle<Map>(); | |
| 253 } | |
| 254 | |
| 255 | |
| 256 KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode( | 234 KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode( |
| 257 TypeFeedbackId ast_id) { | 235 TypeFeedbackId ast_id) { |
| 258 Handle<Object> map_or_code = GetInfo(ast_id); | 236 Handle<Object> map_or_code = GetInfo(ast_id); |
| 259 if (map_or_code->IsCode()) { | 237 if (map_or_code->IsCode()) { |
| 260 Handle<Code> code = Handle<Code>::cast(map_or_code); | 238 Handle<Code> code = Handle<Code>::cast(map_or_code); |
| 261 if (code->kind() == Code::KEYED_STORE_IC) { | 239 if (code->kind() == Code::KEYED_STORE_IC) { |
| 262 return Code::GetKeyedAccessStoreMode(code->extra_ic_state()); | 240 return Code::GetKeyedAccessStoreMode(code->extra_ic_state()); |
| 263 } | 241 } |
| 264 } | 242 } |
| 265 return STANDARD_STORE; | 243 return STANDARD_STORE; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 if (info->IsSmi()) { | 306 if (info->IsSmi()) { |
| 329 ASSERT(static_cast<ElementsKind>(Smi::cast(*info)->value()) <= | 307 ASSERT(static_cast<ElementsKind>(Smi::cast(*info)->value()) <= |
| 330 LAST_FAST_ELEMENTS_KIND); | 308 LAST_FAST_ELEMENTS_KIND); |
| 331 return Handle<JSFunction>(isolate_->global_context()->array_function()); | 309 return Handle<JSFunction>(isolate_->global_context()->array_function()); |
| 332 } else { | 310 } else { |
| 333 return Handle<JSFunction>::cast(info); | 311 return Handle<JSFunction>::cast(info); |
| 334 } | 312 } |
| 335 } | 313 } |
| 336 | 314 |
| 337 | 315 |
| 338 Handle<JSGlobalPropertyCell> TypeFeedbackOracle::GetCallNewAllocationInfoCell( | 316 Handle<Cell> TypeFeedbackOracle::GetCallNewAllocationInfoCell(CallNew* expr) { |
| 339 CallNew* expr) { | |
| 340 return GetInfoCell(expr->CallNewFeedbackId()); | 317 return GetInfoCell(expr->CallNewFeedbackId()); |
| 341 } | 318 } |
| 342 | 319 |
| 343 | 320 |
| 344 Handle<Map> TypeFeedbackOracle::GetObjectLiteralStoreMap( | 321 Handle<Map> TypeFeedbackOracle::GetObjectLiteralStoreMap( |
| 345 ObjectLiteral::Property* prop) { | 322 ObjectLiteral::Property* prop) { |
| 346 ASSERT(ObjectLiteralStoreIsMonomorphic(prop)); | 323 ASSERT(ObjectLiteralStoreIsMonomorphic(prop)); |
| 347 return Handle<Map>::cast(GetInfo(prop->key()->LiteralFeedbackId())); | 324 return Handle<Map>::cast(GetInfo(prop->key()->LiteralFeedbackId())); |
| 348 } | 325 } |
| 349 | 326 |
| 350 | 327 |
| 351 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) { | 328 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) { |
| 352 return *GetInfo(expr->PropertyFeedbackId()) == | 329 return *GetInfo(expr->PropertyFeedbackId()) == |
| 353 isolate_->builtins()->builtin(id); | 330 isolate_->builtins()->builtin(id); |
| 354 } | 331 } |
| 355 | 332 |
| 356 | 333 |
| 357 bool TypeFeedbackOracle::LoadIsStub(Property* expr, ICStub* stub) { | 334 bool TypeFeedbackOracle::LoadIsStub(Property* expr, ICStub* stub) { |
| 358 Handle<Object> object = GetInfo(expr->PropertyFeedbackId()); | 335 Handle<Object> object = GetInfo(expr->PropertyFeedbackId()); |
| 359 if (!object->IsCode()) return false; | 336 if (!object->IsCode()) return false; |
| 360 Handle<Code> code = Handle<Code>::cast(object); | 337 Handle<Code> code = Handle<Code>::cast(object); |
| 361 if (!code->is_load_stub()) return false; | 338 if (!code->is_load_stub()) return false; |
| 362 if (code->ic_state() != MONOMORPHIC) return false; | 339 if (code->ic_state() != MONOMORPHIC) return false; |
| 363 return stub->Describes(*code); | 340 return stub->Describes(*code); |
| 364 } | 341 } |
| 365 | 342 |
| 366 | 343 |
| 367 static TypeInfo TypeFromCompareType(CompareIC::State state) { | 344 void TypeFeedbackOracle::CompareTypes(TypeFeedbackId id, |
| 368 switch (state) { | 345 Handle<Type>* left_type, |
| 369 case CompareIC::UNINITIALIZED: | 346 Handle<Type>* right_type, |
| 370 // Uninitialized means never executed. | 347 Handle<Type>* overall_type, |
| 371 return TypeInfo::Uninitialized(); | 348 Handle<Type>* compare_nil_type) { |
| 372 case CompareIC::SMI: | 349 *left_type = *right_type = *overall_type = *compare_nil_type = |
| 373 return TypeInfo::Smi(); | 350 handle(Type::Any(), isolate_); |
| 374 case CompareIC::NUMBER: | 351 Handle<Object> info = GetInfo(id); |
| 375 return TypeInfo::Number(); | 352 if (!info->IsCode()) return; |
| 376 case CompareIC::INTERNALIZED_STRING: | 353 Handle<Code> code = Handle<Code>::cast(info); |
| 377 return TypeInfo::InternalizedString(); | 354 |
| 378 case CompareIC::STRING: | 355 Handle<Map> map; |
| 379 return TypeInfo::String(); | 356 Map* raw_map = code->FindFirstMap(); |
| 380 case CompareIC::OBJECT: | 357 if (raw_map != NULL) { |
| 381 case CompareIC::KNOWN_OBJECT: | 358 raw_map = raw_map->CurrentMapForDeprecated(); |
| 382 // TODO(kasperl): We really need a type for JS objects here. | 359 if (raw_map != NULL && !CanRetainOtherContext(raw_map, *native_context_)) { |
| 383 return TypeInfo::NonPrimitive(); | 360 map = handle(raw_map, isolate_); |
| 384 case CompareIC::GENERIC: | 361 } |
| 385 default: | 362 } |
| 386 return TypeInfo::Unknown(); | 363 |
| 364 if (code->is_compare_ic_stub()) { |
| 365 int stub_minor_key = code->stub_info(); |
| 366 CompareIC::StubInfoToType( |
| 367 stub_minor_key, left_type, right_type, overall_type, map, isolate()); |
| 368 } else if (code->is_compare_nil_ic_stub()) { |
| 369 CompareNilICStub::State state(code->compare_nil_state()); |
| 370 *compare_nil_type = CompareNilICStub::StateToType(isolate_, state, map); |
| 387 } | 371 } |
| 388 } | 372 } |
| 389 | 373 |
| 390 | 374 |
| 391 void TypeFeedbackOracle::CompareType(CompareOperation* expr, | 375 Handle<Type> TypeFeedbackOracle::UnaryType(TypeFeedbackId id) { |
| 392 TypeInfo* left_type, | 376 Handle<Object> object = GetInfo(id); |
| 393 TypeInfo* right_type, | 377 if (!object->IsCode()) return handle(Type::Any(), isolate()); |
| 394 TypeInfo* overall_type) { | |
| 395 Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId()); | |
| 396 TypeInfo unknown = TypeInfo::Unknown(); | |
| 397 if (!object->IsCode()) { | |
| 398 *left_type = *right_type = *overall_type = unknown; | |
| 399 return; | |
| 400 } | |
| 401 Handle<Code> code = Handle<Code>::cast(object); | 378 Handle<Code> code = Handle<Code>::cast(object); |
| 402 if (!code->is_compare_ic_stub()) { | 379 ASSERT(code->is_unary_op_stub()); |
| 403 *left_type = *right_type = *overall_type = unknown; | 380 return UnaryOpIC::TypeInfoToType( |
| 404 return; | 381 static_cast<UnaryOpIC::TypeInfo>(code->unary_op_type()), isolate()); |
| 405 } | |
| 406 | |
| 407 int stub_minor_key = code->stub_info(); | |
| 408 CompareIC::State left_state, right_state, handler_state; | |
| 409 ICCompareStub::DecodeMinorKey(stub_minor_key, &left_state, &right_state, | |
| 410 &handler_state, NULL); | |
| 411 *left_type = TypeFromCompareType(left_state); | |
| 412 *right_type = TypeFromCompareType(right_state); | |
| 413 *overall_type = TypeFromCompareType(handler_state); | |
| 414 } | 382 } |
| 415 | 383 |
| 416 | 384 |
| 417 Handle<Map> TypeFeedbackOracle::GetCompareMap(CompareOperation* expr) { | 385 void TypeFeedbackOracle::BinaryType(TypeFeedbackId id, |
| 418 Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId()); | 386 Handle<Type>* left, |
| 419 if (!object->IsCode()) return Handle<Map>::null(); | 387 Handle<Type>* right, |
| 388 Handle<Type>* result, |
| 389 bool* has_fixed_right_arg, |
| 390 int* fixed_right_arg_value) { |
| 391 Handle<Object> object = GetInfo(id); |
| 392 *left = *right = *result = handle(Type::Any(), isolate_); |
| 393 if (!object->IsCode()) return; |
| 420 Handle<Code> code = Handle<Code>::cast(object); | 394 Handle<Code> code = Handle<Code>::cast(object); |
| 421 if (!code->is_compare_ic_stub()) return Handle<Map>::null(); | 395 if (!code->is_binary_op_stub()) return; |
| 422 CompareIC::State state = ICCompareStub::CompareState(code->stub_info()); | 396 |
| 423 if (state != CompareIC::KNOWN_OBJECT) { | 397 int minor_key = code->stub_info(); |
| 424 return Handle<Map>::null(); | 398 BinaryOpIC::StubInfoToType(minor_key, left, right, result, isolate()); |
| 425 } | 399 *has_fixed_right_arg = |
| 426 Map* map = code->FindFirstMap()->CurrentMapForDeprecated(); | 400 BinaryOpStub::decode_has_fixed_right_arg_from_minor_key(minor_key); |
| 427 return map == NULL || CanRetainOtherContext(map, *native_context_) | 401 *fixed_right_arg_value = |
| 428 ? Handle<Map>::null() | 402 BinaryOpStub::decode_fixed_right_arg_value_from_minor_key(minor_key); |
| 429 : Handle<Map>(map); | |
| 430 } | 403 } |
| 431 | 404 |
| 432 | 405 |
| 433 TypeInfo TypeFeedbackOracle::UnaryType(UnaryOperation* expr) { | 406 Handle<Type> TypeFeedbackOracle::ClauseType(TypeFeedbackId id) { |
| 434 Handle<Object> object = GetInfo(expr->UnaryOperationFeedbackId()); | 407 Handle<Object> info = GetInfo(id); |
| 435 TypeInfo unknown = TypeInfo::Unknown(); | 408 Handle<Type> result(Type::None(), isolate_); |
| 436 if (!object->IsCode()) return unknown; | 409 if (info->IsCode() && Handle<Code>::cast(info)->is_compare_ic_stub()) { |
| 437 Handle<Code> code = Handle<Code>::cast(object); | 410 Handle<Code> code = Handle<Code>::cast(info); |
| 438 ASSERT(code->is_unary_op_stub()); | 411 CompareIC::State state = ICCompareStub::CompareState(code->stub_info()); |
| 439 UnaryOpIC::TypeInfo type = static_cast<UnaryOpIC::TypeInfo>( | 412 result = CompareIC::StateToType(isolate_, state); |
| 440 code->unary_op_type()); | |
| 441 switch (type) { | |
| 442 case UnaryOpIC::SMI: | |
| 443 return TypeInfo::Smi(); | |
| 444 case UnaryOpIC::NUMBER: | |
| 445 return TypeInfo::Double(); | |
| 446 default: | |
| 447 return unknown; | |
| 448 } | 413 } |
| 414 return result; |
| 449 } | 415 } |
| 450 | 416 |
| 451 | 417 |
| 452 static TypeInfo TypeFromBinaryOpType(BinaryOpIC::TypeInfo binary_type) { | |
| 453 switch (binary_type) { | |
| 454 // Uninitialized means never executed. | |
| 455 case BinaryOpIC::UNINITIALIZED: return TypeInfo::Uninitialized(); | |
| 456 case BinaryOpIC::SMI: return TypeInfo::Smi(); | |
| 457 case BinaryOpIC::INT32: return TypeInfo::Integer32(); | |
| 458 case BinaryOpIC::NUMBER: return TypeInfo::Double(); | |
| 459 case BinaryOpIC::ODDBALL: return TypeInfo::Unknown(); | |
| 460 case BinaryOpIC::STRING: return TypeInfo::String(); | |
| 461 case BinaryOpIC::GENERIC: return TypeInfo::Unknown(); | |
| 462 } | |
| 463 UNREACHABLE(); | |
| 464 return TypeInfo::Unknown(); | |
| 465 } | |
| 466 | |
| 467 | |
| 468 void TypeFeedbackOracle::BinaryType(BinaryOperation* expr, | |
| 469 TypeInfo* left, | |
| 470 TypeInfo* right, | |
| 471 TypeInfo* result, | |
| 472 bool* has_fixed_right_arg, | |
| 473 int* fixed_right_arg_value) { | |
| 474 Handle<Object> object = GetInfo(expr->BinaryOperationFeedbackId()); | |
| 475 TypeInfo unknown = TypeInfo::Unknown(); | |
| 476 if (!object->IsCode()) { | |
| 477 *left = *right = *result = unknown; | |
| 478 return; | |
| 479 } | |
| 480 Handle<Code> code = Handle<Code>::cast(object); | |
| 481 if (code->is_binary_op_stub()) { | |
| 482 int minor_key = code->stub_info(); | |
| 483 BinaryOpIC::TypeInfo left_type, right_type, result_type; | |
| 484 BinaryOpStub::decode_types_from_minor_key( | |
| 485 minor_key, &left_type, &right_type, &result_type); | |
| 486 *left = TypeFromBinaryOpType(left_type); | |
| 487 *right = TypeFromBinaryOpType(right_type); | |
| 488 *result = TypeFromBinaryOpType(result_type); | |
| 489 *has_fixed_right_arg = | |
| 490 BinaryOpStub::decode_has_fixed_right_arg_from_minor_key(minor_key); | |
| 491 *fixed_right_arg_value = | |
| 492 BinaryOpStub::decode_fixed_right_arg_value_from_minor_key(minor_key); | |
| 493 return; | |
| 494 } | |
| 495 // Not a binary op stub. | |
| 496 *left = *right = *result = unknown; | |
| 497 } | |
| 498 | |
| 499 | |
| 500 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) { | |
| 501 Handle<Object> object = GetInfo(clause->CompareId()); | |
| 502 TypeInfo unknown = TypeInfo::Unknown(); | |
| 503 if (!object->IsCode()) return unknown; | |
| 504 Handle<Code> code = Handle<Code>::cast(object); | |
| 505 if (!code->is_compare_ic_stub()) return unknown; | |
| 506 | |
| 507 CompareIC::State state = ICCompareStub::CompareState(code->stub_info()); | |
| 508 return TypeFromCompareType(state); | |
| 509 } | |
| 510 | |
| 511 | |
| 512 TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) { | 418 TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) { |
| 513 Handle<Object> object = GetInfo(expr->CountBinOpFeedbackId()); | 419 Handle<Object> object = GetInfo(expr->CountBinOpFeedbackId()); |
| 514 TypeInfo unknown = TypeInfo::Unknown(); | 420 TypeInfo unknown = TypeInfo::Unknown(); |
| 515 if (!object->IsCode()) return unknown; | 421 if (!object->IsCode()) return unknown; |
| 516 Handle<Code> code = Handle<Code>::cast(object); | 422 Handle<Code> code = Handle<Code>::cast(object); |
| 517 if (!code->is_binary_op_stub()) return unknown; | 423 if (!code->is_binary_op_stub()) return unknown; |
| 518 | 424 |
| 519 BinaryOpIC::TypeInfo left_type, right_type, unused_result_type; | 425 BinaryOpIC::TypeInfo left_type, right_type, unused_result_type; |
| 520 BinaryOpStub::decode_types_from_minor_key(code->stub_info(), &left_type, | 426 BinaryOpStub::decode_types_from_minor_key(code->stub_info(), &left_type, |
| 521 &right_type, &unused_result_type); | 427 &right_type, &unused_result_type); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 } | 535 } |
| 630 } | 536 } |
| 631 | 537 |
| 632 | 538 |
| 633 byte TypeFeedbackOracle::ToBooleanTypes(TypeFeedbackId id) { | 539 byte TypeFeedbackOracle::ToBooleanTypes(TypeFeedbackId id) { |
| 634 Handle<Object> object = GetInfo(id); | 540 Handle<Object> object = GetInfo(id); |
| 635 return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0; | 541 return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0; |
| 636 } | 542 } |
| 637 | 543 |
| 638 | 544 |
| 639 byte TypeFeedbackOracle::CompareNilTypes(CompareOperation* expr) { | |
| 640 Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId()); | |
| 641 if (object->IsCode() && | |
| 642 Handle<Code>::cast(object)->is_compare_nil_ic_stub()) { | |
| 643 return Handle<Code>::cast(object)->compare_nil_types(); | |
| 644 } else { | |
| 645 return CompareNilICStub::Types::FullCompare().ToIntegral(); | |
| 646 } | |
| 647 } | |
| 648 | |
| 649 | |
| 650 // Things are a bit tricky here: The iterator for the RelocInfos and the infos | 545 // Things are a bit tricky here: The iterator for the RelocInfos and the infos |
| 651 // themselves are not GC-safe, so we first get all infos, then we create the | 546 // themselves are not GC-safe, so we first get all infos, then we create the |
| 652 // dictionary (possibly triggering GC), and finally we relocate the collected | 547 // dictionary (possibly triggering GC), and finally we relocate the collected |
| 653 // infos before we process them. | 548 // infos before we process them. |
| 654 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { | 549 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { |
| 655 DisallowHeapAllocation no_allocation; | 550 DisallowHeapAllocation no_allocation; |
| 656 ZoneList<RelocInfo> infos(16, zone()); | 551 ZoneList<RelocInfo> infos(16, zone()); |
| 657 HandleScope scope(isolate_); | 552 HandleScope scope(isolate_); |
| 658 GetRelocInfos(code, &infos); | 553 GetRelocInfos(code, &infos); |
| 659 CreateDictionary(code, &infos); | 554 CreateDictionary(code, &infos); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 752 } | 647 } |
| 753 | 648 |
| 754 | 649 |
| 755 void TypeFeedbackOracle::ProcessTypeFeedbackCells(Handle<Code> code) { | 650 void TypeFeedbackOracle::ProcessTypeFeedbackCells(Handle<Code> code) { |
| 756 Object* raw_info = code->type_feedback_info(); | 651 Object* raw_info = code->type_feedback_info(); |
| 757 if (!raw_info->IsTypeFeedbackInfo()) return; | 652 if (!raw_info->IsTypeFeedbackInfo()) return; |
| 758 Handle<TypeFeedbackCells> cache( | 653 Handle<TypeFeedbackCells> cache( |
| 759 TypeFeedbackInfo::cast(raw_info)->type_feedback_cells()); | 654 TypeFeedbackInfo::cast(raw_info)->type_feedback_cells()); |
| 760 for (int i = 0; i < cache->CellCount(); i++) { | 655 for (int i = 0; i < cache->CellCount(); i++) { |
| 761 TypeFeedbackId ast_id = cache->AstId(i); | 656 TypeFeedbackId ast_id = cache->AstId(i); |
| 762 JSGlobalPropertyCell* cell = cache->Cell(i); | 657 Cell* cell = cache->GetCell(i); |
| 763 Object* value = cell->value(); | 658 Object* value = cell->value(); |
| 764 if (value->IsSmi() || | 659 if (value->IsSmi() || |
| 765 (value->IsJSFunction() && | 660 (value->IsJSFunction() && |
| 766 !CanRetainOtherContext(JSFunction::cast(value), | 661 !CanRetainOtherContext(JSFunction::cast(value), |
| 767 *native_context_))) { | 662 *native_context_))) { |
| 768 SetInfo(ast_id, cell); | 663 SetInfo(ast_id, cell); |
| 769 } | 664 } |
| 770 } | 665 } |
| 771 } | 666 } |
| 772 | 667 |
| 773 | 668 |
| 774 void TypeFeedbackOracle::SetInfo(TypeFeedbackId ast_id, Object* target) { | 669 void TypeFeedbackOracle::SetInfo(TypeFeedbackId ast_id, Object* target) { |
| 775 ASSERT(dictionary_->FindEntry(IdToKey(ast_id)) == | 670 ASSERT(dictionary_->FindEntry(IdToKey(ast_id)) == |
| 776 UnseededNumberDictionary::kNotFound); | 671 UnseededNumberDictionary::kNotFound); |
| 777 MaybeObject* maybe_result = dictionary_->AtNumberPut(IdToKey(ast_id), target); | 672 MaybeObject* maybe_result = dictionary_->AtNumberPut(IdToKey(ast_id), target); |
| 778 USE(maybe_result); | 673 USE(maybe_result); |
| 779 #ifdef DEBUG | 674 #ifdef DEBUG |
| 780 Object* result = NULL; | 675 Object* result = NULL; |
| 781 // Dictionary has been allocated with sufficient size for all elements. | 676 // Dictionary has been allocated with sufficient size for all elements. |
| 782 ASSERT(maybe_result->ToObject(&result)); | 677 ASSERT(maybe_result->ToObject(&result)); |
| 783 ASSERT(*dictionary_ == result); | 678 ASSERT(*dictionary_ == result); |
| 784 #endif | 679 #endif |
| 785 } | 680 } |
| 786 | 681 |
| 787 } } // namespace v8::internal | 682 } } // namespace v8::internal |
| OLD | NEW |