1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #include "v8.h" 29 30 #include "ast.h" 31 #include "code-stubs.h" 32 #include "compiler.h" 33 #include "ic.h" 34 #include "macro-assembler.h" 35 #include "stub-cache.h" 36 #include "type-info.h" 37 38 #include "ic-inl.h" 39 #include "objects-inl.h" 40 41 namespace v8 { 42 namespace internal { 43 44 45 TypeInfo TypeInfo::FromValue(Handle<Object> value) { 46 if (value->IsSmi()) { 47 return TypeInfo::Smi(); 48 } else if (value->IsHeapNumber()) { 49 return TypeInfo::IsInt32Double(HeapNumber::cast(*value)->value()) 50 ? TypeInfo::Integer32() 51 : TypeInfo::Double(); 52 } else if (value->IsString()) { 53 return TypeInfo::String(); 54 } 55 return TypeInfo::Unknown(); 56 } 57 58 59 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, 60 Handle<Context> native_context, 61 Isolate* isolate, 62 Zone* zone) 63 : native_context_(native_context), 64 isolate_(isolate), 65 zone_(zone) { 66 BuildDictionary(code); 67 ASSERT(dictionary_->IsDictionary()); 68 } 69 70 71 static uint32_t IdToKey(TypeFeedbackId ast_id) { 72 return static_cast<uint32_t>(ast_id.ToInt()); 73 } 74 75 76 Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) { 77 int entry = dictionary_->FindEntry(IdToKey(ast_id)); 78 if (entry != UnseededNumberDictionary::kNotFound) { 79 Object* value = dictionary_->ValueAt(entry); 80 if (value->IsCell()) { 81 Cell* cell = Cell::cast(value); 82 return Handle<Object>(cell->value(), isolate_); 83 } else { 84 return Handle<Object>(value, isolate_); 85 } 86 } 87 return Handle<Object>::cast(isolate_->factory()->undefined_value()); 88 } 89 90 91 Handle<Cell> TypeFeedbackOracle::GetInfoCell( 92 TypeFeedbackId ast_id) { 93 int entry = dictionary_->FindEntry(IdToKey(ast_id)); 94 if (entry != UnseededNumberDictionary::kNotFound) { 95 Cell* cell = Cell::cast(dictionary_->ValueAt(entry)); 96 return Handle<Cell>(cell, isolate_); 97 } 98 return Handle<Cell>::null(); 99 } 100 101 102 bool TypeFeedbackOracle::LoadIsUninitialized(TypeFeedbackId id) { 103 Handle<Object> maybe_code = GetInfo(id); 104 if (maybe_code->IsCode()) { 105 Handle<Code> code = Handle<Code>::cast(maybe_code); 106 return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; 107 } 108 return false; 109 } 110 111 112 bool TypeFeedbackOracle::LoadIsPreMonomorphic(TypeFeedbackId id) { 113 Handle<Object> maybe_code = GetInfo(id); 114 if (maybe_code->IsCode()) { 115 Handle<Code> code = Handle<Code>::cast(maybe_code); 116 return code->is_inline_cache_stub() && code->ic_state() == PREMONOMORPHIC; 117 } 118 return false; 119 } 120 121 122 bool TypeFeedbackOracle::StoreIsUninitialized(TypeFeedbackId ast_id) { 123 Handle<Object> maybe_code = GetInfo(ast_id); 124 if (!maybe_code->IsCode()) return false; 125 Handle<Code> code = Handle<Code>::cast(maybe_code); 126 return code->ic_state() == UNINITIALIZED; 127 } 128 129 130 bool TypeFeedbackOracle::StoreIsPreMonomorphic(TypeFeedbackId ast_id) { 131 Handle<Object> maybe_code = GetInfo(ast_id); 132 if (maybe_code->IsCode()) { 133 Handle<Code> code = Handle<Code>::cast(maybe_code); 134 return code->ic_state() == PREMONOMORPHIC; 135 } 136 return false; 137 } 138 139 140 bool TypeFeedbackOracle::StoreIsKeyedPolymorphic(TypeFeedbackId ast_id) { 141 Handle<Object> maybe_code = GetInfo(ast_id); 142 if (maybe_code->IsCode()) { 143 Handle<Code> code = Handle<Code>::cast(maybe_code); 144 return code->is_keyed_store_stub() && 145 code->ic_state() == POLYMORPHIC; 146 } 147 return false; 148 } 149 150 151 bool TypeFeedbackOracle::CallIsMonomorphic(TypeFeedbackId id) { 152 Handle<Object> value = GetInfo(id); 153 return value->IsAllocationSite() || value->IsJSFunction() || value->IsSmi() || 154 (value->IsCode() && Handle<Code>::cast(value)->ic_state() == MONOMORPHIC); 155 } 156 157 158 bool TypeFeedbackOracle::KeyedArrayCallIsHoley(TypeFeedbackId id) { 159 Handle<Object> value = GetInfo(id); 160 Handle<Code> code = Handle<Code>::cast(value); 161 return KeyedArrayCallStub::IsHoley(code); 162 } 163 164 165 bool TypeFeedbackOracle::CallNewIsMonomorphic(TypeFeedbackId id) { 166 Handle<Object> info = GetInfo(id); 167 return info->IsAllocationSite() || info->IsJSFunction(); 168 } 169 170 171 byte TypeFeedbackOracle::ForInType(TypeFeedbackId id) { 172 Handle<Object> value = GetInfo(id); 173 return value->IsSmi() && 174 Smi::cast(*value)->value() == TypeFeedbackCells::kForInFastCaseMarker 175 ? ForInStatement::FAST_FOR_IN : ForInStatement::SLOW_FOR_IN; 176 } 177 178 179 KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode( 180 TypeFeedbackId ast_id) { 181 Handle<Object> maybe_code = GetInfo(ast_id); 182 if (maybe_code->IsCode()) { 183 Handle<Code> code = Handle<Code>::cast(maybe_code); 184 if (code->kind() == Code::KEYED_STORE_IC) { 185 return KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()); 186 } 187 } 188 return STANDARD_STORE; 189 } 190 191 192 void TypeFeedbackOracle::CallReceiverTypes(TypeFeedbackId id, 193 Handle<String> name, 194 int arity, 195 CallKind call_kind, 196 SmallMapList* types) { 197 // Note: Currently we do not take string extra ic data into account 198 // here. 199 ContextualMode contextual_mode = call_kind == CALL_AS_FUNCTION 200 ? CONTEXTUAL 201 : NOT_CONTEXTUAL; 202 ExtraICState extra_ic_state = 203 CallIC::Contextual::encode(contextual_mode); 204 205 Code::Flags flags = Code::ComputeMonomorphicFlags( 206 Code::CALL_IC, extra_ic_state, OWN_MAP, Code::NORMAL, arity); 207 CollectReceiverTypes(id, name, flags, types); 208 } 209 210 211 CheckType TypeFeedbackOracle::GetCallCheckType(TypeFeedbackId id) { 212 Handle<Object> value = GetInfo(id); 213 if (!value->IsSmi()) return RECEIVER_MAP_CHECK; 214 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value()); 215 ASSERT(check != RECEIVER_MAP_CHECK); 216 return check; 217 } 218 219 220 Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(TypeFeedbackId id) { 221 Handle<Object> info = GetInfo(id); 222 if (info->IsAllocationSite()) { 223 return Handle<JSFunction>(isolate_->global_context()->array_function()); 224 } else { 225 return Handle<JSFunction>::cast(info); 226 } 227 } 228 229 230 Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(TypeFeedbackId id) { 231 Handle<Object> info = GetInfo(id); 232 if (info->IsAllocationSite()) { 233 return Handle<JSFunction>(isolate_->global_context()->array_function()); 234 } else { 235 return Handle<JSFunction>::cast(info); 236 } 237 } 238 239 240 Handle<Cell> TypeFeedbackOracle::GetCallNewAllocationInfoCell( 241 TypeFeedbackId id) { 242 return GetInfoCell(id); 243 } 244 245 246 bool TypeFeedbackOracle::LoadIsBuiltin( 247 TypeFeedbackId id, Builtins::Name builtin) { 248 return *GetInfo(id) == isolate_->builtins()->builtin(builtin); 249 } 250 251 252 bool TypeFeedbackOracle::LoadIsStub(TypeFeedbackId id, ICStub* stub) { 253 Handle<Object> object = GetInfo(id); 254 if (!object->IsCode()) return false; 255 Handle<Code> code = Handle<Code>::cast(object); 256 if (!code->is_load_stub()) return false; 257 if (code->ic_state() != MONOMORPHIC) return false; 258 return stub->Describes(*code); 259 } 260 261 262 void TypeFeedbackOracle::CompareType(TypeFeedbackId id, 263 Handle<Type>* left_type, 264 Handle<Type>* right_type, 265 Handle<Type>* combined_type) { 266 Handle<Object> info = GetInfo(id); 267 if (!info->IsCode()) { 268 // For some comparisons we don't have ICs, e.g. LiteralCompareTypeof. 269 *left_type = *right_type = *combined_type = handle(Type::None(), isolate_); 270 return; 271 } 272 Handle<Code> code = Handle<Code>::cast(info); 273 274 Handle<Map> map; 275 Map* raw_map = code->FindFirstMap(); 276 if (raw_map != NULL) { 277 map = Map::CurrentMapForDeprecated(handle(raw_map)); 278 if (!map.is_null() && CanRetainOtherContext(*map, *native_context_)) { 279 map = Handle<Map>::null(); 280 } 281 } 282 283 if (code->is_compare_ic_stub()) { 284 int stub_minor_key = code->stub_info(); 285 CompareIC::StubInfoToType( 286 stub_minor_key, left_type, right_type, combined_type, map, isolate()); 287 } else if (code->is_compare_nil_ic_stub()) { 288 CompareNilICStub stub(code->extended_extra_ic_state()); 289 *combined_type = stub.GetType(isolate_, map); 290 *left_type = *right_type = stub.GetInputType(isolate_, map); 291 } 292 } 293 294 295 void TypeFeedbackOracle::BinaryType(TypeFeedbackId id, 296 Handle<Type>* left, 297 Handle<Type>* right, 298 Handle<Type>* result, 299 Maybe<int>* fixed_right_arg, 300 Token::Value op) { 301 Handle<Object> object = GetInfo(id); 302 if (!object->IsCode()) { 303 // For some binary ops we don't have ICs, e.g. Token::COMMA, but for the 304 // operations covered by the BinaryOpIC we should always have them. 305 ASSERT(op < BinaryOpIC::State::FIRST_TOKEN || 306 op > BinaryOpIC::State::LAST_TOKEN); 307 *left = *right = *result = handle(Type::None(), isolate_); 308 *fixed_right_arg = Maybe<int>(); 309 return; 310 } 311 Handle<Code> code = Handle<Code>::cast(object); 312 ASSERT_EQ(Code::BINARY_OP_IC, code->kind()); 313 BinaryOpIC::State state(code->extended_extra_ic_state()); 314 ASSERT_EQ(op, state.op()); 315 316 *left = state.GetLeftType(isolate()); 317 *right = state.GetRightType(isolate()); 318 *result = state.GetResultType(isolate()); 319 *fixed_right_arg = state.fixed_right_arg(); 320 } 321 322 323 Handle<Type> TypeFeedbackOracle::ClauseType(TypeFeedbackId id) { 324 Handle<Object> info = GetInfo(id); 325 Handle<Type> result(Type::None(), isolate_); 326 if (info->IsCode() && Handle<Code>::cast(info)->is_compare_ic_stub()) { 327 Handle<Code> code = Handle<Code>::cast(info); 328 CompareIC::State state = ICCompareStub::CompareState(code->stub_info()); 329 result = CompareIC::StateToType(isolate_, state); 330 } 331 return result; 332 } 333 334 335 Handle<Type> TypeFeedbackOracle::CountType(TypeFeedbackId id) { 336 Handle<Object> object = GetInfo(id); 337 if (!object->IsCode()) return handle(Type::None(), isolate_); 338 Handle<Code> code = Handle<Code>::cast(object); 339 ASSERT_EQ(Code::BINARY_OP_IC, code->kind()); 340 BinaryOpIC::State state(code->extended_extra_ic_state()); 341 return state.GetLeftType(isolate()); 342 } 343 344 345 void TypeFeedbackOracle::PropertyReceiverTypes( 346 TypeFeedbackId id, Handle<String> name, 347 SmallMapList* receiver_types, bool* is_prototype) { 348 receiver_types->Clear(); 349 FunctionPrototypeStub proto_stub(Code::LOAD_IC); 350 *is_prototype = LoadIsStub(id, &proto_stub); 351 if (!*is_prototype) { 352 Code::Flags flags = Code::ComputeFlags( 353 Code::HANDLER, MONOMORPHIC, kNoExtraICState, 354 Code::NORMAL, Code::LOAD_IC); 355 CollectReceiverTypes(id, name, flags, receiver_types); 356 } 357 } 358 359 360 void TypeFeedbackOracle::KeyedPropertyReceiverTypes( 361 TypeFeedbackId id, SmallMapList* receiver_types, bool* is_string) { 362 receiver_types->Clear(); 363 *is_string = false; 364 if (LoadIsBuiltin(id, Builtins::kKeyedLoadIC_String)) { 365 *is_string = true; 366 } else { 367 CollectReceiverTypes(id, receiver_types); 368 } 369 } 370 371 372 void TypeFeedbackOracle::AssignmentReceiverTypes( 373 TypeFeedbackId id, Handle<String> name, SmallMapList* receiver_types) { 374 receiver_types->Clear(); 375 Code::Flags flags = Code::ComputeFlags( 376 Code::HANDLER, MONOMORPHIC, kNoExtraICState, 377 Code::NORMAL, Code::STORE_IC); 378 CollectReceiverTypes(id, name, flags, receiver_types); 379 } 380 381 382 void TypeFeedbackOracle::KeyedAssignmentReceiverTypes( 383 TypeFeedbackId id, SmallMapList* receiver_types, 384 KeyedAccessStoreMode* store_mode) { 385 receiver_types->Clear(); 386 CollectReceiverTypes(id, receiver_types); 387 *store_mode = GetStoreMode(id); 388 } 389 390 391 void TypeFeedbackOracle::CountReceiverTypes(TypeFeedbackId id, 392 SmallMapList* receiver_types) { 393 receiver_types->Clear(); 394 CollectReceiverTypes(id, receiver_types); 395 } 396 397 398 void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id, 399 Handle<String> name, 400 Code::Flags flags, 401 SmallMapList* types) { 402 Handle<Object> object = GetInfo(ast_id); 403 if (object->IsUndefined() || object->IsSmi()) return; 404 405 ASSERT(object->IsCode()); 406 Handle<Code> code(Handle<Code>::cast(object)); 407 408 if (FLAG_collect_megamorphic_maps_from_stub_cache && 409 code->ic_state() == MEGAMORPHIC) { 410 types->Reserve(4, zone()); 411 isolate_->stub_cache()->CollectMatchingMaps( 412 types, name, flags, native_context_, zone()); 413 } else { 414 CollectReceiverTypes(ast_id, types); 415 } 416 } 417 418 419 // Check if a map originates from a given native context. We use this 420 // information to filter out maps from different context to avoid 421 // retaining objects from different tabs in Chrome via optimized code. 422 bool TypeFeedbackOracle::CanRetainOtherContext(Map* map, 423 Context* native_context) { 424 Object* constructor = NULL; 425 while (!map->prototype()->IsNull()) { 426 constructor = map->constructor(); 427 if (!constructor->IsNull()) { 428 // If the constructor is not null or a JSFunction, we have to 429 // conservatively assume that it may retain a native context. 430 if (!constructor->IsJSFunction()) return true; 431 // Check if the constructor directly references a foreign context. 432 if (CanRetainOtherContext(JSFunction::cast(constructor), 433 native_context)) { 434 return true; 435 } 436 } 437 map = HeapObject::cast(map->prototype())->map(); 438 } 439 constructor = map->constructor(); 440 if (constructor->IsNull()) return false; 441 JSFunction* function = JSFunction::cast(constructor); 442 return CanRetainOtherContext(function, native_context); 443 } 444 445 446 bool TypeFeedbackOracle::CanRetainOtherContext(JSFunction* function, 447 Context* native_context) { 448 return function->context()->global_object() != native_context->global_object() 449 && function->context()->global_object() != native_context->builtins(); 450 } 451 452 453 void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id, 454 SmallMapList* types) { 455 Handle<Object> object = GetInfo(ast_id); 456 if (!object->IsCode()) return; 457 Handle<Code> code = Handle<Code>::cast(object); 458 MapHandleList maps; 459 if (code->ic_state() == MONOMORPHIC) { 460 Map* map = code->FindFirstMap(); 461 if (map != NULL) maps.Add(handle(map)); 462 } else if (code->ic_state() == POLYMORPHIC) { 463 code->FindAllMaps(&maps); 464 } else { 465 return; 466 } 467 types->Reserve(maps.length(), zone()); 468 for (int i = 0; i < maps.length(); i++) { 469 Handle<Map> map(maps.at(i)); 470 if (!CanRetainOtherContext(*map, *native_context_)) { 471 types->AddMapIfMissing(map, zone()); 472 } 473 } 474 } 475 476 477 byte TypeFeedbackOracle::ToBooleanTypes(TypeFeedbackId id) { 478 Handle<Object> object = GetInfo(id); 479 return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0; 480 } 481 482 483 // Things are a bit tricky here: The iterator for the RelocInfos and the infos 484 // themselves are not GC-safe, so we first get all infos, then we create the 485 // dictionary (possibly triggering GC), and finally we relocate the collected 486 // infos before we process them. 487 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { 488 DisallowHeapAllocation no_allocation; 489 ZoneList<RelocInfo> infos(16, zone()); 490 HandleScope scope(isolate_); 491 GetRelocInfos(code, &infos); 492 CreateDictionary(code, &infos); 493 ProcessRelocInfos(&infos); 494 ProcessTypeFeedbackCells(code); 495 // Allocate handle in the parent scope. 496 dictionary_ = scope.CloseAndEscape(dictionary_); 497 } 498 499 500 void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code, 501 ZoneList<RelocInfo>* infos) { 502 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); 503 for (RelocIterator it(*code, mask); !it.done(); it.next()) { 504 infos->Add(*it.rinfo(), zone()); 505 } 506 } 507 508 509 void TypeFeedbackOracle::CreateDictionary(Handle<Code> code, 510 ZoneList<RelocInfo>* infos) { 511 AllowHeapAllocation allocation_allowed; 512 int cell_count = code->type_feedback_info()->IsTypeFeedbackInfo() 513 ? TypeFeedbackInfo::cast(code->type_feedback_info())-> 514 type_feedback_cells()->CellCount() 515 : 0; 516 int length = infos->length() + cell_count; 517 byte* old_start = code->instruction_start(); 518 dictionary_ = isolate()->factory()->NewUnseededNumberDictionary(length); 519 byte* new_start = code->instruction_start(); 520 RelocateRelocInfos(infos, old_start, new_start); 521 } 522 523 524 void TypeFeedbackOracle::RelocateRelocInfos(ZoneList<RelocInfo>* infos, 525 byte* old_start, 526 byte* new_start) { 527 for (int i = 0; i < infos->length(); i++) { 528 RelocInfo* info = &(*infos)[i]; 529 info->set_pc(new_start + (info->pc() - old_start)); 530 } 531 } 532 533 534 void TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) { 535 for (int i = 0; i < infos->length(); i++) { 536 RelocInfo reloc_entry = (*infos)[i]; 537 Address target_address = reloc_entry.target_address(); 538 TypeFeedbackId ast_id = 539 TypeFeedbackId(static_cast<unsigned>((*infos)[i].data())); 540 Code* target = Code::GetCodeFromTargetAddress(target_address); 541 switch (target->kind()) { 542 case Code::CALL_IC: 543 if (target->ic_state() == MONOMORPHIC && 544 target->check_type() != RECEIVER_MAP_CHECK) { 545 SetInfo(ast_id, Smi::FromInt(target->check_type())); 546 break; 547 } 548 case Code::LOAD_IC: 549 case Code::STORE_IC: 550 case Code::KEYED_CALL_IC: 551 case Code::KEYED_LOAD_IC: 552 case Code::KEYED_STORE_IC: 553 case Code::BINARY_OP_IC: 554 case Code::COMPARE_IC: 555 case Code::TO_BOOLEAN_IC: 556 case Code::COMPARE_NIL_IC: 557 SetInfo(ast_id, target); 558 break; 559 560 default: 561 break; 562 } 563 } 564 } 565 566 567 void TypeFeedbackOracle::ProcessTypeFeedbackCells(Handle<Code> code) { 568 Object* raw_info = code->type_feedback_info(); 569 if (!raw_info->IsTypeFeedbackInfo()) return; 570 Handle<TypeFeedbackCells> cache( 571 TypeFeedbackInfo::cast(raw_info)->type_feedback_cells()); 572 for (int i = 0; i < cache->CellCount(); i++) { 573 TypeFeedbackId ast_id = cache->AstId(i); 574 Cell* cell = cache->GetCell(i); 575 Object* value = cell->value(); 576 if (value->IsSmi() || 577 value->IsAllocationSite() || 578 (value->IsJSFunction() && 579 !CanRetainOtherContext(JSFunction::cast(value), 580 *native_context_))) { 581 SetInfo(ast_id, cell); 582 } 583 } 584 } 585 586 587 void TypeFeedbackOracle::SetInfo(TypeFeedbackId ast_id, Object* target) { 588 ASSERT(dictionary_->FindEntry(IdToKey(ast_id)) == 589 UnseededNumberDictionary::kNotFound); 590 MaybeObject* maybe_result = dictionary_->AtNumberPut(IdToKey(ast_id), target); 591 USE(maybe_result); 592 #ifdef DEBUG 593 Object* result = NULL; 594 // Dictionary has been allocated with sufficient size for all elements. 595 ASSERT(maybe_result->ToObject(&result)); 596 ASSERT(*dictionary_ == result); 597 #endif 598 } 599 600 601 Representation Representation::FromType(TypeInfo info) { 602 if (info.IsUninitialized()) return Representation::None(); 603 if (info.IsSmi()) return Representation::Smi(); 604 if (info.IsInteger32()) return Representation::Integer32(); 605 if (info.IsDouble()) return Representation::Double(); 606 if (info.IsNumber()) return Representation::Double(); 607 return Representation::Tagged(); 608 } 609 610 611 } } // namespace v8::internal 612