Changeset 201456 in webkit
- Timestamp:
- May 27, 2016, 11:36:30 AM (10 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 12 edited
-
ChangeLog (modified) (1 diff)
-
bytecode/BytecodeList.json (modified) (1 diff)
-
bytecode/BytecodeUseDef.h (modified) (2 diffs)
-
bytecode/CodeBlock.cpp (modified) (3 diffs)
-
bytecode/GetByIdStatus.cpp (modified) (1 diff)
-
dfg/DFGByteCodeParser.cpp (modified) (1 diff)
-
dfg/DFGCapabilities.cpp (modified) (1 diff)
-
jit/JIT.cpp (modified) (2 diffs)
-
llint/LLIntSlowPaths.cpp (modified) (4 diffs)
-
llint/LLIntSlowPaths.h (modified) (1 diff)
-
llint/LowLevelInterpreter32_64.asm (modified) (3 diffs)
-
llint/LowLevelInterpreter64.asm (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r201451 r201456 1 2016-05-27 Keith Miller <keith_miller@apple.com> 2 3 get_by_id should support caching unset properties in the LLInt 4 https://bugs.webkit.org/show_bug.cgi?id=158136 5 6 Reviewed by Benjamin Poulain. 7 8 Recently, we started supporting prototype load caching for get_by_id 9 in the LLInt. This patch extends that to caching unset properties. 10 While it is uncommon in general for a program to see a single structure 11 without a given property, the Array.prototype.concat function needs to 12 lookup the Symbol.isConcatSpreadable property. For any existing code 13 That property will never be set as it did not exist prior to ES6. 14 15 Similarly to the get_by_id_proto_load bytecode, this patch adds a new 16 bytecode, get_by_id_unset that checks the structureID of the base and 17 assigns undefined to the result. 18 19 There are no new tests here since we already have many tests that 20 incidentally cover this change. 21 22 * bytecode/BytecodeList.json: 23 * bytecode/BytecodeUseDef.h: 24 (JSC::computeUsesForBytecodeOffset): 25 (JSC::computeDefsForBytecodeOffset): 26 * bytecode/CodeBlock.cpp: 27 (JSC::CodeBlock::printGetByIdOp): 28 (JSC::CodeBlock::dumpBytecode): 29 (JSC::CodeBlock::finalizeLLIntInlineCaches): 30 * bytecode/GetByIdStatus.cpp: 31 (JSC::GetByIdStatus::computeFromLLInt): 32 * dfg/DFGByteCodeParser.cpp: 33 (JSC::DFG::ByteCodeParser::parseBlock): 34 * dfg/DFGCapabilities.cpp: 35 (JSC::DFG::capabilityLevel): 36 * jit/JIT.cpp: 37 (JSC::JIT::privateCompileMainPass): 38 (JSC::JIT::privateCompileSlowCases): 39 * llint/LLIntSlowPaths.cpp: 40 (JSC::LLInt::setupGetByIdPrototypeCache): 41 (JSC::LLInt::LLINT_SLOW_PATH_DECL): 42 * llint/LLIntSlowPaths.h: 43 * llint/LowLevelInterpreter32_64.asm: 44 * llint/LowLevelInterpreter64.asm: 45 1 46 2016-05-26 Filip Pizlo <fpizlo@apple.com> 2 47 -
trunk/Source/JavaScriptCore/bytecode/BytecodeList.json
r201363 r201456 62 62 { "name" : "op_get_by_id", "length" : 9 }, 63 63 { "name" : "op_get_by_id_proto_load", "length" : 9 }, 64 { "name" : "op_get_by_id_unset", "length" : 9 }, 64 65 { "name" : "op_get_by_id_with_this", "length" : 5 }, 65 66 { "name" : "op_get_by_val_with_this", "length" : 5 }, -
trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h
r201363 r201456 160 160 case op_get_by_id: 161 161 case op_get_by_id_proto_load: 162 case op_get_by_id_unset: 162 163 case op_get_array_length: 163 164 case op_typeof: … … 395 396 case op_get_by_id: 396 397 case op_get_by_id_proto_load: 398 case op_get_by_id_unset: 397 399 case op_get_by_id_with_this: 398 400 case op_get_by_val_with_this: -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r201363 r201456 350 350 op = "get_by_id_proto_load"; 351 351 break; 352 case op_get_by_id_unset: 353 op = "get_by_id_unset"; 354 break; 352 355 case op_get_array_length: 353 356 op = "array_length"; … … 1120 1123 case op_get_by_id: 1121 1124 case op_get_by_id_proto_load: 1125 case op_get_by_id_unset: 1122 1126 case op_get_array_length: { 1123 1127 printGetByIdOp(out, exec, location, it); … … 2807 2811 switch (interpreter->getOpcodeID(curInstruction[0].u.opcode)) { 2808 2812 case op_get_by_id: 2809 case op_get_by_id_proto_load: { 2813 case op_get_by_id_proto_load: 2814 case op_get_by_id_unset: { 2810 2815 StructureID oldStructureID = curInstruction[4].u.structureID; 2811 2816 if (!oldStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(oldStructureID))) -
trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
r201363 r201456 79 79 Opcode opcode = instruction[0].u.opcode; 80 80 81 ASSERT(opcode == LLInt::getOpcode(op_get_array_length) || opcode == LLInt::getOpcode(op_try_get_by_id) || opcode == LLInt::getOpcode(op_get_by_id_proto_load) || opcode == LLInt::getOpcode(op_get_by_id) || opcode == LLInt::getOpcode(op_get_by_id_unset)); 82 81 83 // FIXME: We should not just bail if we see a try_get_by_id or a get_by_id_proto_load. 82 84 // https://bugs.webkit.org/show_bug.cgi?id=158039 83 if (opcode == LLInt::getOpcode(op_get_array_length) || opcode == LLInt::getOpcode(op_try_get_by_id) || opcode == LLInt::getOpcode(op_get_by_id_proto_load))85 if (opcode != LLInt::getOpcode(op_get_by_id)) 84 86 return GetByIdStatus(NoInformation, false); 85 87 -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r201363 r201456 4083 4083 case op_get_by_id: 4084 4084 case op_get_by_id_proto_load: 4085 case op_get_by_id_unset: 4085 4086 case op_get_array_length: { 4086 4087 SpeculatedType prediction = getPrediction(); -
trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
r201363 r201456 156 156 case op_get_by_id: 157 157 case op_get_by_id_proto_load: 158 case op_get_by_id_unset: 158 159 case op_get_by_id_with_this: 159 160 case op_get_by_val_with_this: -
trunk/Source/JavaScriptCore/jit/JIT.cpp
r201363 r201456 242 242 case op_get_array_length: 243 243 case op_get_by_id_proto_load: 244 case op_get_by_id_unset: 244 245 DEFINE_OP(op_get_by_id) 245 246 DEFINE_OP(op_get_by_id_with_this) … … 425 426 case op_get_array_length: 426 427 case op_get_by_id_proto_load: 428 case op_get_by_id_unset: 427 429 DEFINE_SLOWCASE_OP(op_get_by_id) 428 430 DEFINE_SLOWCASE_OP(op_get_by_val) -
trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
r201363 r201456 590 590 return; 591 591 592 ObjectPropertyConditionSet conditions = generateConditionsForPrototypePropertyHit(vm, codeBlock, exec, structure, slot.slotBase(), ident.impl()); 592 ObjectPropertyConditionSet conditions; 593 if (slot.isUnset()) 594 conditions = generateConditionsForPropertyMiss(vm, codeBlock, exec, structure, ident.impl()); 595 else 596 conditions = generateConditionsForPrototypePropertyHit(vm, codeBlock, exec, structure, slot.slotBase(), ident.impl()); 593 597 594 598 if (!conditions.isValid()) … … 605 609 result.iterator->value.add(condition, pc)->install(); 606 610 } 607 ASSERT( offset != invalidOffset);611 ASSERT((offset == invalidOffset) == slot.isUnset()); 608 612 609 613 ConcurrentJITLocker locker(codeBlock->m_lock); 614 615 if (slot.isUnset()) { 616 pc[0].u.opcode = LLInt::getOpcode(op_get_by_id_unset); 617 pc[4].u.structureID = structure->id(); 618 return; 619 } 620 ASSERT(slot.isValue()); 610 621 611 622 pc[0].u.opcode = LLInt::getOpcode(op_get_by_id_proto_load); 612 623 pc[4].u.structureID = structure->id(); 613 624 pc[5].u.operand = offset; 614 // We know that this pointer will remain valid because it is the prototype of some structure, s, 615 // watchpointed above. If any object with structure s were to change prototypes then the conditions 616 // for this cache would fail and this value will never be used again. 625 // We know that this pointer will remain valid because it will be cleared by either a watchpoint fire or 626 // during GC when we clear the LLInt caches. 617 627 pc[6].u.pointer = slot.slotBase(); 618 628 } … … 633 643 if (!LLINT_ALWAYS_ACCESS_SLOW 634 644 && baseValue.isCell() 635 && slot.isCacheable Value()) {645 && slot.isCacheable()) { 636 646 637 647 JSCell* baseCell = baseValue.asCell(); 638 648 Structure* structure = baseCell->structure(); 639 if (slot. slotBase() == baseValue) {649 if (slot.isValue() && slot.slotBase() == baseValue) { 640 650 // Start out by clearing out the old cache. 641 651 pc[0].u.opcode = LLInt::getOpcode(op_get_by_id); … … 654 664 pc[5].u.operand = slot.cachedOffset(); 655 665 } 656 } else if (UNLIKELY(pc[7].u.operand )) {666 } else if (UNLIKELY(pc[7].u.operand && (slot.isValue() || slot.isUnset()))) { 657 667 ASSERT(slot.slotBase() != baseValue); 658 668 -
trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.h
r201363 r201456 72 72 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_try_get_by_id); 73 73 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_by_id); 74 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_by_id_proto_load);75 74 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_arguments_length); 76 75 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_by_id); -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
r201363 r201456 1338 1338 # since ping-ponging is free. At best we get lucky and the get_by_id will continue 1339 1339 # to take fast path on the new cache. At worst we take slow path, which is what 1340 # we would have been doing anyway. For prototype properties, we will attempt to 1341 # convert opcode into a get_by_id_proto_load after a execution counter hits zero. 1340 # we would have been doing anyway. For prototype/unset properties, we will attempt to 1341 # convert opcode into a get_by_id_proto_load/get_by_id_unset, respectively, after an 1342 # execution counter hits zero. 1342 1343 1343 1344 _llint_op_get_by_id: … … 1358 1359 callSlowPath(_llint_slow_path_get_by_id) 1359 1360 dispatch(9) 1360 1361 1361 1362 1362 … … 1377 1377 1378 1378 .opGetByIdProtoSlow: 1379 callSlowPath(_llint_slow_path_get_by_id) 1380 dispatch(9) 1381 1382 1383 _llint_op_get_by_id_unset: 1384 traceExecution() 1385 loadi 8[PC], t0 1386 loadi 16[PC], t1 1387 loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdUnsetSlow) 1388 bineq JSCell::m_structureID[t3], t1, .opGetByIdUnsetSlow 1389 loadi 4[PC], t2 1390 storei UndefinedTag, TagOffset[cfr, t2, 8] 1391 storei 0, PayloadOffset[cfr, t2, 8] 1392 valueProfile(UndefinedTag, 0, 32, t2) 1393 dispatch(9) 1394 1395 .opGetByIdUnsetSlow: 1379 1396 callSlowPath(_llint_slow_path_get_by_id) 1380 1397 dispatch(9) -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r201363 r201456 1253 1253 1254 1254 1255 _llint_op_get_by_id_unset: 1256 traceExecution() 1257 loadisFromInstruction(2, t0) 1258 loadConstantOrVariableCell(t0, t3, .opGetByIdUnsetSlow) 1259 loadi JSCell::m_structureID[t3], t1 1260 loadisFromInstruction(4, t2) 1261 bineq t2, t1, .opGetByIdUnsetSlow 1262 loadisFromInstruction(1, t2) 1263 storeq ValueUndefined, [cfr, t2, 8] 1264 valueProfile(ValueUndefined, 8, t1) 1265 dispatch(9) 1266 1267 .opGetByIdUnsetSlow: 1268 callSlowPath(_llint_slow_path_get_by_id) 1269 dispatch(9) 1270 1271 1255 1272 _llint_op_get_array_length: 1256 1273 traceExecution()
Note:
See TracChangeset
for help on using the changeset viewer.