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 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 StoreStubCompiler compiler(isolate_, strict_mode); | 364 StoreStubCompiler compiler(isolate_, strict_mode); |
365 Handle<Code> code = | 365 Handle<Code> code = |
366 compiler.CompileStoreField(receiver, field_index, transition, name); | 366 compiler.CompileStoreField(receiver, field_index, transition, name); |
367 PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name)); | 367 PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name)); |
368 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code)); | 368 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code)); |
369 JSObject::UpdateMapCodeCache(receiver, name, code); | 369 JSObject::UpdateMapCodeCache(receiver, name, code); |
370 return code; | 370 return code; |
371 } | 371 } |
372 | 372 |
373 | 373 |
374 Handle<Code> StubCache::ComputeKeyedLoadOrStoreElement( | 374 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) { |
375 Handle<Map> receiver_map, | |
376 KeyedIC::StubKind stub_kind, | |
377 StrictModeFlag strict_mode) { | |
378 KeyedAccessGrowMode grow_mode = | |
379 KeyedIC::GetGrowModeFromStubKind(stub_kind); | |
380 Code::ExtraICState extra_state = | |
381 Code::ComputeExtraICState(grow_mode, strict_mode); | |
382 Code::Flags flags = | 375 Code::Flags flags = |
383 Code::ComputeMonomorphicFlags( | 376 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, Code::NORMAL); |
384 stub_kind == KeyedIC::LOAD ? Code::KEYED_LOAD_IC | 377 Handle<String> name = |
385 : Code::KEYED_STORE_IC, | 378 isolate()->factory()->KeyedLoadElementMonomorphic_symbol(); |
386 Code::NORMAL, | 379 |
387 extra_state); | |
388 Handle<String> name; | |
389 switch (stub_kind) { | |
390 case KeyedIC::LOAD: | |
391 name = isolate()->factory()->KeyedLoadElementMonomorphic_symbol(); | |
392 break; | |
393 case KeyedIC::STORE_NO_TRANSITION: | |
394 name = isolate()->factory()->KeyedStoreElementMonomorphic_symbol(); | |
395 break; | |
396 case KeyedIC::STORE_AND_GROW_NO_TRANSITION: | |
397 name = isolate()->factory()->KeyedStoreAndGrowElementMonomorphic_symbol(); | |
398 break; | |
399 default: | |
400 UNREACHABLE(); | |
401 break; | |
402 } | |
403 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); | 380 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); |
404 if (probe->IsCode()) return Handle<Code>::cast(probe); | 381 if (probe->IsCode()) return Handle<Code>::cast(probe); |
405 | 382 |
406 Handle<Code> code; | 383 KeyedLoadStubCompiler compiler(isolate()); |
407 switch (stub_kind) { | 384 Handle<Code> code = compiler.CompileLoadElement(receiver_map); |
408 case KeyedIC::LOAD: { | |
409 KeyedLoadStubCompiler compiler(isolate_); | |
410 code = compiler.CompileLoadElement(receiver_map); | |
411 break; | |
412 } | |
413 case KeyedIC::STORE_AND_GROW_NO_TRANSITION: { | |
414 KeyedStoreStubCompiler compiler(isolate_, strict_mode, | |
415 ALLOW_JSARRAY_GROWTH); | |
416 code = compiler.CompileStoreElement(receiver_map); | |
417 break; | |
418 } | |
419 case KeyedIC::STORE_NO_TRANSITION: { | |
420 KeyedStoreStubCompiler compiler(isolate_, strict_mode, | |
421 DO_NOT_ALLOW_JSARRAY_GROWTH); | |
422 code = compiler.CompileStoreElement(receiver_map); | |
423 break; | |
424 } | |
425 default: | |
426 UNREACHABLE(); | |
427 break; | |
428 } | |
429 | 385 |
430 ASSERT(!code.is_null()); | 386 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, 0)); |
431 | |
432 if (stub_kind == KeyedIC::LOAD) { | |
433 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, 0)); | |
434 } else { | |
435 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, 0)); | |
436 } | |
437 Map::UpdateCodeCache(receiver_map, name, code); | 387 Map::UpdateCodeCache(receiver_map, name, code); |
438 return code; | 388 return code; |
439 } | 389 } |
| 390 |
| 391 |
| 392 Handle<Code> StubCache::ComputeKeyedStoreElement( |
| 393 Handle<Map> receiver_map, |
| 394 KeyedStoreIC::StubKind stub_kind, |
| 395 StrictModeFlag strict_mode, |
| 396 KeyedAccessGrowMode grow_mode) { |
| 397 Code::ExtraICState extra_state = |
| 398 Code::ComputeExtraICState(grow_mode, strict_mode); |
| 399 Code::Flags flags = Code::ComputeMonomorphicFlags( |
| 400 Code::KEYED_STORE_IC, Code::NORMAL, extra_state); |
| 401 |
| 402 ASSERT(stub_kind == KeyedStoreIC::STORE_NO_TRANSITION || |
| 403 stub_kind == KeyedStoreIC::STORE_AND_GROW_NO_TRANSITION); |
| 404 |
| 405 Handle<String> name = stub_kind == KeyedStoreIC::STORE_NO_TRANSITION |
| 406 ? isolate()->factory()->KeyedStoreElementMonomorphic_symbol() |
| 407 : isolate()->factory()->KeyedStoreAndGrowElementMonomorphic_symbol(); |
| 408 |
| 409 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); |
| 410 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 411 |
| 412 KeyedStoreStubCompiler compiler(isolate(), strict_mode, grow_mode); |
| 413 Handle<Code> code = compiler.CompileStoreElement(receiver_map); |
| 414 |
| 415 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, 0)); |
| 416 Map::UpdateCodeCache(receiver_map, name, code); |
| 417 return code; |
| 418 } |
440 | 419 |
441 | 420 |
442 Handle<Code> StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) { | 421 Handle<Code> StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) { |
443 return (strict_mode == kStrictMode) | 422 return (strict_mode == kStrictMode) |
444 ? isolate_->builtins()->Builtins::StoreIC_Normal_Strict() | 423 ? isolate_->builtins()->Builtins::StoreIC_Normal_Strict() |
445 : isolate_->builtins()->Builtins::StoreIC_Normal(); | 424 : isolate_->builtins()->Builtins::StoreIC_Normal(); |
446 } | 425 } |
447 | 426 |
448 | 427 |
449 Handle<Code> StubCache::ComputeStoreGlobal(Handle<String> name, | 428 Handle<Code> StubCache::ComputeStoreGlobal(Handle<String> name, |
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
844 int entry = cache->FindEntry(isolate_, flags); | 823 int entry = cache->FindEntry(isolate_, flags); |
845 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | 824 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
846 | 825 |
847 StubCompiler compiler(isolate_); | 826 StubCompiler compiler(isolate_); |
848 Handle<Code> code = compiler.CompileCallMiss(flags); | 827 Handle<Code> code = compiler.CompileCallMiss(flags); |
849 FillCache(isolate_, code); | 828 FillCache(isolate_, code); |
850 return code; | 829 return code; |
851 } | 830 } |
852 | 831 |
853 | 832 |
| 833 Handle<Code> StubCache::ComputeLoadElementPolymorphic( |
| 834 MapHandleList* receiver_maps) { |
| 835 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); |
| 836 Handle<PolymorphicCodeCache> cache = |
| 837 isolate_->factory()->polymorphic_code_cache(); |
| 838 Handle<Object> probe = cache->Lookup(receiver_maps, flags); |
| 839 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 840 |
| 841 KeyedLoadStubCompiler compiler(isolate_); |
| 842 Handle<Code> code = compiler.CompileLoadElementPolymorphic(receiver_maps); |
| 843 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); |
| 844 return code; |
| 845 } |
| 846 |
| 847 |
| 848 Handle<Code> StubCache::ComputeStoreElementPolymorphic( |
| 849 MapHandleList* receiver_maps, |
| 850 KeyedAccessGrowMode grow_mode, |
| 851 StrictModeFlag strict_mode) { |
| 852 Handle<PolymorphicCodeCache> cache = |
| 853 isolate_->factory()->polymorphic_code_cache(); |
| 854 Code::ExtraICState extra_state = Code::ComputeExtraICState(grow_mode, |
| 855 strict_mode); |
| 856 Code::Flags flags = |
| 857 Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state); |
| 858 Handle<Object> probe = cache->Lookup(receiver_maps, flags); |
| 859 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 860 |
| 861 KeyedStoreStubCompiler compiler(isolate_, strict_mode, grow_mode); |
| 862 Handle<Code> code = compiler.CompileStoreElementPolymorphic(receiver_maps); |
| 863 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); |
| 864 return code; |
| 865 } |
| 866 |
| 867 |
854 #ifdef ENABLE_DEBUGGER_SUPPORT | 868 #ifdef ENABLE_DEBUGGER_SUPPORT |
855 Handle<Code> StubCache::ComputeCallDebugBreak(int argc, | 869 Handle<Code> StubCache::ComputeCallDebugBreak(int argc, |
856 Code::Kind kind) { | 870 Code::Kind kind) { |
857 // Extra IC state is irrelevant for debug break ICs. They jump to | 871 // Extra IC state is irrelevant for debug break ICs. They jump to |
858 // the actual call ic to carry out the work. | 872 // the actual call ic to carry out the work. |
859 Code::Flags flags = | 873 Code::Flags flags = |
860 Code::ComputeFlags(kind, DEBUG_STUB, DEBUG_BREAK, | 874 Code::ComputeFlags(kind, DEBUG_STUB, DEBUG_BREAK, |
861 Code::NORMAL, argc); | 875 Code::NORMAL, argc); |
862 Handle<UnseededNumberDictionary> cache = | 876 Handle<UnseededNumberDictionary> cache = |
863 isolate_->factory()->non_monomorphic_cache(); | 877 isolate_->factory()->non_monomorphic_cache(); |
(...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1359 InlineCacheState state) { | 1373 InlineCacheState state) { |
1360 Code::Flags flags = Code::ComputeFlags( | 1374 Code::Flags flags = Code::ComputeFlags( |
1361 Code::KEYED_LOAD_IC, state, Code::kNoExtraICState, type); | 1375 Code::KEYED_LOAD_IC, state, Code::kNoExtraICState, type); |
1362 Handle<Code> code = GetCodeWithFlags(flags, name); | 1376 Handle<Code> code = GetCodeWithFlags(flags, name); |
1363 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); | 1377 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); |
1364 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); | 1378 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); |
1365 return code; | 1379 return code; |
1366 } | 1380 } |
1367 | 1381 |
1368 | 1382 |
| 1383 Handle<Code> KeyedLoadStubCompiler::CompileLoadElementPolymorphic( |
| 1384 MapHandleList* receiver_maps) { |
| 1385 CodeHandleList handler_ics(receiver_maps->length()); |
| 1386 for (int i = 0; i < receiver_maps->length(); ++i) { |
| 1387 Handle<Map> receiver_map = receiver_maps->at(i); |
| 1388 Handle<Code> cached_stub; |
| 1389 |
| 1390 if ((receiver_map->instance_type() & kNotStringTag) == 0) { |
| 1391 cached_stub = isolate()->builtins()->KeyedLoadIC_String(); |
| 1392 } else { |
| 1393 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
| 1394 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 1395 |
| 1396 if (IsFastElementsKind(elements_kind) || |
| 1397 IsExternalArrayElementsKind(elements_kind)) { |
| 1398 cached_stub = |
| 1399 KeyedLoadFastElementStub(is_js_array, elements_kind).GetCode(); |
| 1400 } else { |
| 1401 ASSERT(elements_kind == DICTIONARY_ELEMENTS); |
| 1402 cached_stub = KeyedLoadDictionaryElementStub().GetCode(); |
| 1403 } |
| 1404 } |
| 1405 |
| 1406 handler_ics.Add(cached_stub); |
| 1407 } |
| 1408 Handle<Code> code = CompileLoadPolymorphic(receiver_maps, &handler_ics); |
| 1409 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); |
| 1410 PROFILE(isolate(), |
| 1411 CodeCreateEvent(Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG, *code, 0)); |
| 1412 return code; |
| 1413 } |
| 1414 |
| 1415 |
| 1416 |
1369 Handle<Code> StoreStubCompiler::GetCode(Code::StubType type, | 1417 Handle<Code> StoreStubCompiler::GetCode(Code::StubType type, |
1370 Handle<String> name) { | 1418 Handle<String> name) { |
1371 Code::Flags flags = | 1419 Code::Flags flags = |
1372 Code::ComputeMonomorphicFlags(Code::STORE_IC, type, strict_mode_); | 1420 Code::ComputeMonomorphicFlags(Code::STORE_IC, type, strict_mode_); |
1373 Handle<Code> code = GetCodeWithFlags(flags, name); | 1421 Handle<Code> code = GetCodeWithFlags(flags, name); |
1374 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name)); | 1422 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name)); |
1375 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code)); | 1423 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code)); |
1376 return code; | 1424 return code; |
1377 } | 1425 } |
1378 | 1426 |
1379 | 1427 |
1380 Handle<Code> KeyedStoreStubCompiler::GetCode(Code::StubType type, | 1428 Handle<Code> KeyedStoreStubCompiler::GetCode(Code::StubType type, |
1381 Handle<String> name, | 1429 Handle<String> name, |
1382 InlineCacheState state) { | 1430 InlineCacheState state) { |
1383 Code::ExtraICState extra_state = | 1431 Code::ExtraICState extra_state = |
1384 Code::ComputeExtraICState(grow_mode_, strict_mode_); | 1432 Code::ComputeExtraICState(grow_mode_, strict_mode_); |
1385 Code::Flags flags = | 1433 Code::Flags flags = |
1386 Code::ComputeFlags(Code::KEYED_STORE_IC, state, extra_state, type); | 1434 Code::ComputeFlags(Code::KEYED_STORE_IC, state, extra_state, type); |
1387 Handle<Code> code = GetCodeWithFlags(flags, name); | 1435 Handle<Code> code = GetCodeWithFlags(flags, name); |
1388 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name)); | 1436 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name)); |
1389 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code)); | 1437 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code)); |
1390 return code; | 1438 return code; |
1391 } | 1439 } |
1392 | 1440 |
1393 | 1441 |
| 1442 Handle<Code> KeyedStoreStubCompiler::CompileStoreElementPolymorphic( |
| 1443 MapHandleList* receiver_maps) { |
| 1444 // Collect MONOMORPHIC stubs for all |receiver_maps|. |
| 1445 CodeHandleList handler_ics(receiver_maps->length()); |
| 1446 MapHandleList transitioned_maps(receiver_maps->length()); |
| 1447 for (int i = 0; i < receiver_maps->length(); ++i) { |
| 1448 Handle<Map> receiver_map(receiver_maps->at(i)); |
| 1449 Handle<Code> cached_stub; |
| 1450 Handle<Map> transitioned_map = |
| 1451 receiver_map->FindTransitionedMap(receiver_maps); |
| 1452 |
| 1453 // TODO(mvstanton): The code below is doing pessimistic elements |
| 1454 // transitions. I would like to stop doing that and rely on Allocation Site |
| 1455 // Tracking to do a better job of ensuring the data types are what they need |
| 1456 // to be. Not all the elements are in place yet, pessimistic elements |
| 1457 // transitions are still important for performance. |
| 1458 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
| 1459 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 1460 if (!transitioned_map.is_null()) { |
| 1461 cached_stub = ElementsTransitionAndStoreStub( |
| 1462 elements_kind, |
| 1463 transitioned_map->elements_kind(), |
| 1464 is_js_array, |
| 1465 strict_mode_, |
| 1466 grow_mode_).GetCode(); |
| 1467 } else { |
| 1468 cached_stub = KeyedStoreElementStub( |
| 1469 is_js_array, |
| 1470 elements_kind, |
| 1471 grow_mode_).GetCode(); |
| 1472 } |
| 1473 ASSERT(!cached_stub.is_null()); |
| 1474 handler_ics.Add(cached_stub); |
| 1475 transitioned_maps.Add(transitioned_map); |
| 1476 } |
| 1477 Handle<Code> code = |
| 1478 CompileStorePolymorphic(receiver_maps, &handler_ics, &transitioned_maps); |
| 1479 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment(); |
| 1480 PROFILE(isolate(), |
| 1481 CodeCreateEvent(Logger::KEYED_STORE_POLYMORPHIC_IC_TAG, *code, 0)); |
| 1482 return code; |
| 1483 } |
| 1484 |
| 1485 |
1394 void KeyedStoreStubCompiler::GenerateStoreDictionaryElement( | 1486 void KeyedStoreStubCompiler::GenerateStoreDictionaryElement( |
1395 MacroAssembler* masm) { | 1487 MacroAssembler* masm) { |
1396 KeyedStoreIC::GenerateSlow(masm); | 1488 KeyedStoreIC::GenerateSlow(masm); |
1397 } | 1489 } |
1398 | 1490 |
1399 | 1491 |
1400 CallStubCompiler::CallStubCompiler(Isolate* isolate, | 1492 CallStubCompiler::CallStubCompiler(Isolate* isolate, |
1401 int argc, | 1493 int argc, |
1402 Code::Kind kind, | 1494 Code::Kind kind, |
1403 Code::ExtraICState extra_state, | 1495 Code::ExtraICState extra_state, |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1551 Handle<FunctionTemplateInfo>( | 1643 Handle<FunctionTemplateInfo>( |
1552 FunctionTemplateInfo::cast(signature->receiver())); | 1644 FunctionTemplateInfo::cast(signature->receiver())); |
1553 } | 1645 } |
1554 } | 1646 } |
1555 | 1647 |
1556 is_simple_api_call_ = true; | 1648 is_simple_api_call_ = true; |
1557 } | 1649 } |
1558 | 1650 |
1559 | 1651 |
1560 } } // namespace v8::internal | 1652 } } // namespace v8::internal |
OLD | NEW |