Changeset 202627 in webkit


Ignore:
Timestamp:
Jun 29, 2016 9:53:25 AM (8 years ago)
Author:
commit-queue@webkit.org
Message:

LLInt should support other types of prototype GetById caching.
https://bugs.webkit.org/show_bug.cgi?id=158083

Recently, we started supporting prototype load caching for get_by_id
in the LLInt. This patch is expading the caching strategy to enable
cache the prototype accessor and custom acessors.

Similarly to the get_by_id_proto_load bytecode, we are adding new
bytecodes called get_by_id_proto_accessor that uses the calculated
offset of a object to call a getter function and get_by_id_proto_custom
that stores the pointer to the custom function and call them directly
from LowLevelInterpreter.

Patch by Caio Lima <Caio Lima> on 2016-06-29
Reviewed by Keith Miller

  • bytecode/BytecodeList.json:
  • bytecode/BytecodeUseDef.h:

(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::printGetByIdOp):
(JSC::CodeBlock::dumpBytecode):
(JSC::CodeBlock::finalizeLLIntInlineCaches):

  • bytecode/GetByIdStatus.cpp:

(JSC::GetByIdStatus::computeFromLLInt):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGCapabilities.cpp:

(JSC::DFG::capabilityLevel):

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):

  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::setupGetByIdPrototypeCache):
(JSC::LLInt::LLINT_SLOW_PATH_DECL):

  • llint/LLIntSlowPaths.h:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
Location:
trunk/Source/JavaScriptCore
Files:
2 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r202611 r202627  
     12016-06-29  Caio Lima  <ticaiolima@gmail.com>
     2
     3        LLInt should support other types of prototype GetById caching.
     4        https://bugs.webkit.org/show_bug.cgi?id=158083
     5
     6        Recently, we started supporting prototype load caching for get_by_id
     7        in the LLInt. This patch is expading the caching strategy to enable
     8        cache the prototype accessor and custom acessors.
     9
     10        Similarly to the get_by_id_proto_load bytecode, we are adding new
     11        bytecodes called get_by_id_proto_accessor that uses the calculated
     12        offset of a object to call a getter function and get_by_id_proto_custom
     13        that stores the pointer to the custom function and call them directly
     14        from LowLevelInterpreter.
     15
     16        Reviewed by Keith Miller
     17
     18        * bytecode/BytecodeList.json:
     19        * bytecode/BytecodeUseDef.h:
     20        (JSC::computeUsesForBytecodeOffset):
     21        (JSC::computeDefsForBytecodeOffset):
     22        * bytecode/CodeBlock.cpp:
     23        (JSC::CodeBlock::printGetByIdOp):
     24        (JSC::CodeBlock::dumpBytecode):
     25        (JSC::CodeBlock::finalizeLLIntInlineCaches):
     26        * bytecode/GetByIdStatus.cpp:
     27        (JSC::GetByIdStatus::computeFromLLInt):
     28        * dfg/DFGByteCodeParser.cpp:
     29        (JSC::DFG::ByteCodeParser::parseBlock):
     30        * dfg/DFGCapabilities.cpp:
     31        (JSC::DFG::capabilityLevel):
     32        * jit/JIT.cpp:
     33        (JSC::JIT::privateCompileMainPass):
     34        (JSC::JIT::privateCompileSlowCases):
     35        * llint/LLIntSlowPaths.cpp:
     36        (JSC::LLInt::setupGetByIdPrototypeCache):
     37        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
     38        * llint/LLIntSlowPaths.h:
     39        * llint/LowLevelInterpreter32_64.asm:
     40        * llint/LowLevelInterpreter64.asm:
     41
    1422016-06-28  Commit Queue  <commit-queue@webkit.org>
    243
  • trunk/Source/JavaScriptCore/bytecode/BytecodeList.json

    r202435 r202627  
    6565            { "name" : "op_get_by_id_proto_load", "length" : 9 },
    6666            { "name" : "op_get_by_id_unset", "length" : 9 },
     67            { "name" : "op_get_by_id_proto_accessor", "length" : 9 },
     68            { "name" : "op_get_by_id_proto_custom", "length" : 9 },
    6769            { "name" : "op_get_by_id_with_this", "length" : 5 },
    6870            { "name" : "op_get_by_val_with_this", "length" : 5 },
  • trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h

    r202125 r202627  
    165165    case op_get_by_id_proto_load:
    166166    case op_get_by_id_unset:
     167    case op_get_by_id_proto_accessor:
     168    case op_get_by_id_proto_custom:
    167169    case op_get_array_length:
    168170    case op_typeof:
     
    404406    case op_get_by_id_proto_load:
    405407    case op_get_by_id_unset:
     408    case op_get_by_id_proto_accessor:
     409    case op_get_by_id_proto_custom:
    406410    case op_get_by_id_with_this:
    407411    case op_get_by_val_with_this:
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r202588 r202627  
    355355        op = "get_by_id_unset";
    356356        break;
     357    case op_get_by_id_proto_accessor:
     358        op = "op_get_by_id_proto_accessor";
     359        break;
     360    case op_get_by_id_proto_custom:
     361        op = "op_get_by_id_proto_custom";
     362        break;
    357363    case op_get_array_length:
    358364        op = "array_length";
     
    11381144        case op_get_by_id_proto_load:
    11391145        case op_get_by_id_unset:
     1146        case op_get_by_id_proto_accessor:
     1147        case op_get_by_id_proto_custom:
    11401148        case op_get_array_length: {
    11411149            printGetByIdOp(out, exec, location, it);
     
    27972805        case op_get_by_id:
    27982806        case op_get_by_id_proto_load:
    2799         case op_get_by_id_unset: {
     2807        case op_get_by_id_unset:
     2808        case op_get_by_id_proto_accessor:
     2809        case op_get_by_id_proto_custom: {
    28002810            StructureID oldStructureID = curInstruction[4].u.structureID;
    28012811            if (!oldStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(oldStructureID)))
  • trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp

    r202093 r202627  
    7979    Opcode opcode = instruction[0].u.opcode;
    8080
    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));
     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) || opcode == LLInt::getOpcode(op_get_by_id_proto_accessor) || opcode == LLInt::getOpcode(op_get_by_id_proto_custom));
    8282
    8383    // FIXME: We should not just bail if we see a try_get_by_id or a get_by_id_proto_load.
  • trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h

    r202098 r202627  
    108108
    109109class UnlinkedCodeBlock : public JSCell {
     110    friend class LLIntOffsetsExtractor;
    110111public:
    111112    typedef JSCell Base;
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r202487 r202627  
    41464146        case op_get_by_id_proto_load:
    41474147        case op_get_by_id_unset:
     4148        case op_get_by_id_proto_accessor:
     4149        case op_get_by_id_proto_custom:
    41484150        case op_get_array_length: {
    41494151            SpeculatedType prediction = getPrediction();
  • trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp

    r202125 r202627  
    159159    case op_get_by_id_proto_load:
    160160    case op_get_by_id_unset:
     161    case op_get_by_id_proto_accessor:
     162    case op_get_by_id_proto_custom:
    161163    case op_get_by_id_with_this:
    162164    case op_get_by_val_with_this:
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r202397 r202627  
    251251        case op_get_by_id_proto_load:
    252252        case op_get_by_id_unset:
     253        case op_get_by_id_proto_accessor:
     254        case op_get_by_id_proto_custom:
    253255        DEFINE_OP(op_get_by_id)
    254256        DEFINE_OP(op_get_by_id_with_this)
     
    436438        case op_get_by_id_proto_load:
    437439        case op_get_by_id_unset:
     440        case op_get_by_id_proto_accessor:
     441        case op_get_by_id_proto_custom:
    438442        DEFINE_SLOWCASE_OP(op_get_by_id)
    439443        DEFINE_SLOWCASE_OP(op_get_by_val)
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r202588 r202627  
    599599    if (slot.isUnset())
    600600        conditions = generateConditionsForPropertyMiss(vm, codeBlock, exec, structure, ident.impl());
     601    else if (slot.isCustom())
     602        conditions = generateConditionsForPrototypePropertyHitCustom(vm, codeBlock, exec, structure, slot.slotBase(), ident.impl());
    601603    else
    602604        conditions = generateConditionsForPrototypePropertyHit(vm, codeBlock, exec, structure, slot.slotBase(), ident.impl());
     
    615617        result.iterator->value.add(condition, pc)->install();
    616618    }
    617     ASSERT((offset == invalidOffset) == slot.isUnset());
     619    ASSERT((offset == invalidOffset) == (slot.isUnset() || slot.isCustom()));
    618620
    619621    ConcurrentJITLocker locker(codeBlock->m_lock);
     
    623625        pc[4].u.structureID = structure->id();
    624626        return;
    625     }
    626     ASSERT(slot.isValue());
    627 
    628     pc[0].u.opcode = LLInt::getOpcode(op_get_by_id_proto_load);
     627    } else if (slot.isCustom()) {
     628        pc[0].u.opcode = LLInt::getOpcode(op_get_by_id_proto_custom);
     629        pc[4].u.structureID = structure->id();
     630        pc[5].u.getterFunc = slot.customGetter();
     631        pc[6].u.pointer = slot.attributes() & CustomAccessor ? 0 : slot.slotBase();
     632        return;
     633    }
     634    ASSERT(slot.isValue() || slot.isAccessor());
     635
     636    if (slot.isAccessor())
     637        pc[0].u.opcode = LLInt::getOpcode(op_get_by_id_proto_accessor);
     638    else
     639        pc[0].u.opcode = LLInt::getOpcode(op_get_by_id_proto_load);
     640
    629641    pc[4].u.structureID = structure->id();
    630642    pc[5].u.operand = offset;
     
    667679                ConcurrentJITLocker locker(codeBlock->m_lock);
    668680
    669                 pc[4].u.structureID = structure->id();
    670                 pc[5].u.operand = slot.cachedOffset();
     681                if (slot.isValue()) {
     682                    pc[4].u.structureID = structure->id();
     683                    pc[5].u.operand = slot.cachedOffset();
     684                }
    671685            }
    672         } else if (UNLIKELY(pc[7].u.operand && (slot.isValue() || slot.isUnset()))) {
     686        } else if (UNLIKELY(pc[7].u.operand && (slot.isValue() || slot.isUnset() || ((slot.isAccessor() || slot.isCustom()) && (slot.slotBase() != baseValue))))) {
    673687            ASSERT(slot.slotBase() != baseValue);
    674688
     
    690704    pc[OPCODE_LENGTH(op_get_by_id) - 1].u.profile->m_buckets[0] = JSValue::encode(result);
    691705    LLINT_END();
     706}
     707
     708LLINT_SLOW_PATH_DECL(slow_path_get_proto_accessor)
     709{
     710    LLINT_BEGIN();
     711    JSValue baseValue = LLINT_OP_C(2).jsValue();
     712    PropertyOffset offset = pc[5].u.operand;
     713    JSObject* slotBase = jsCast<JSObject*>(pc[6].u.jsCell.get());
     714    JSValue getterSetter = slotBase->getDirect(offset);
     715
     716    JSValue result = callGetter(exec, baseValue, getterSetter);
     717
     718    LLINT_RETURN_PROFILED(op_get_by_id, result);
    692719}
    693720
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.h

    r202131 r202627  
    7474LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_try_get_by_id);
    7575LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_by_id);
     76LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_proto_accessor);
    7677LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_arguments_length);
    7778LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_by_id);
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r202131 r202627  
    422422    .ok:
    423423    end
     424end
     425
     426macro loadIdentifier(index, dest)
     427    loadp CodeBlock[cfr], t1
     428    loadp CodeBlock::m_unlinkedCode[t1], t2
     429    loadp UnlinkedCodeBlock::m_identifiers[t2], t1
     430    move index, t2
     431    mulp sizeof Identifier, t2
     432    addp t2, t1
     433    loadp Identifier::m_string[t1], dest
    424434end
    425435
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r202435 r202627  
    14211421.opGetByIdUnsetSlow:
    14221422    callOpcodeSlowPath(_llint_slow_path_get_by_id)
     1423    dispatch(9)
     1424
     1425
     1426_llint_op_get_by_id_proto_accessor:
     1427    traceExecution()
     1428    loadi 8[PC], t0
     1429    loadi 16[PC], t1
     1430    loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdProtoAcessorSlow)
     1431    bineq JSCell::m_structureID[t3], t1, .opGetByIdProtoAcessorSlow
     1432    callSlowPath(_llint_slow_path_get_proto_accessor)
     1433    dispatch(9)
     1434
     1435.opGetByIdProtoAcessorSlow:
     1436    callSlowPath(_llint_slow_path_get_by_id)
     1437    dispatch(9)
     1438
     1439macro loadEncodedThisValue(baseValue, dest)
     1440   loadp 24[PC], dest
     1441   bineq 0, dest, .loadEncodedThisValueDone
     1442   move baseValue, dest
     1443   .loadEncodedThisValueDone:
     1444end
     1445
     1446_llint_op_get_by_id_proto_custom:
     1447    traceExecution()
     1448    loadi 8[PC], t0
     1449    loadi 16[PC], t1
     1450    loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdProtoCustomSlow)
     1451    bineq JSCell::m_structureID[t3], t1, .opGetByIdProtoCustomSlow
     1452    # Setting the topCallFrame
     1453    loadp Callee[cfr], t0
     1454    andp MarkedBlockMask, t0, t1
     1455    loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t1
     1456    storep cfr, VM::topCallFrame[t1]
     1457    loadi 12[PC], t0
     1458    loadIdentifier(t0, t2)
     1459    loadEncodedThisValue(t3, t1)
     1460    loadp 20[PC], t0
     1461    # Inlining the GetValueFunc call
     1462    push t1 # Load arg3 JSObject *
     1463    push t2 # Load arg2 PropertyName
     1464    move CellTag, t3
     1465    if BIG_ENDIAN
     1466        push t1 # Load arg1 Payload of EncodedJSValue
     1467        push t3 # Load arg1 Tag of EncodedJSValue
     1468    else
     1469        push t3 # Load arg1 Tag of EncodedJSValue
     1470        push t1 # Load arg1 Payload of EncodedJSValue
     1471    end
     1472    push cfr # Loading exec
     1473    call t0
     1474    addp 20, sp
     1475    loadi 4[PC], t2
     1476    storei r1, TagOffset[cfr, t2, 8]
     1477    storei r0, PayloadOffset[cfr, t2, 8]
     1478    valueProfile(r0, r1, 32, t2)
     1479    dispatch(9)
     1480
     1481.opGetByIdProtoCustomSlow:
     1482    callSlowPath(_llint_slow_path_get_by_id)
    14231483    dispatch(9)
    14241484
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r202435 r202627  
    12951295
    12961296
     1297_llint_op_get_by_id_proto_accessor:
     1298    traceExecution()
     1299    loadisFromInstruction(2, t0)
     1300    loadConstantOrVariableCell(t0, t3, .opGetByIdProtoAcessorSlow)
     1301    loadi JSCell::m_structureID[t3], t1
     1302    loadisFromInstruction(4, t2)
     1303    bineq t2, t1, .opGetByIdProtoAcessorSlow
     1304    callSlowPath(_llint_slow_path_get_proto_accessor)
     1305    dispatch(9)
     1306
     1307.opGetByIdProtoAcessorSlow:
     1308    callSlowPath(_llint_slow_path_get_by_id)
     1309    dispatch(9)
     1310
     1311
     1312macro loadEncodedThisValue(baseValue, dest)
     1313   loadpFromInstruction(6, dest)
     1314   bineq 0, dest, .loadEncodedThisValueDone
     1315   move baseValue, dest
     1316   .loadEncodedThisValueDone:
     1317end
     1318
     1319_llint_op_get_by_id_proto_custom:
     1320    traceExecution()
     1321    loadisFromInstruction(2, t0)
     1322    loadConstantOrVariableCell(t0, t3, .opGetByIdProtoCustomSlow)
     1323    loadi JSCell::m_structureID[t3], t1
     1324    loadisFromInstruction(4, t2)
     1325    bineq t2, t1, .opGetByIdProtoCustomSlow
     1326    # Setting the topCallFrame
     1327    loadp Callee[cfr], t0
     1328    andp MarkedBlockMask, t0, t1
     1329    loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t1
     1330    storep cfr, VM::topCallFrame[t1]
     1331    push PC
     1332    push PB
     1333    loadpFromInstruction(3, t0)
     1334    loadIdentifier(t0, a2)
     1335    loadEncodedThisValue(t3, a1)
     1336    loadpFromInstruction(5, t0)
     1337    prepareStateForCCall()
     1338    move cfr, a0
     1339    move a1, a3
     1340    cCall4(t0)
     1341    restoreStateAfterCCall()
     1342    pop PB
     1343    pop PC
     1344    loadisFromInstruction(1, t2)
     1345    storeq r0, [cfr, t2, 8]
     1346    valueProfile(r0, 8, t1)
     1347    dispatch(9)
     1348
     1349.opGetByIdProtoCustomSlow:
     1350    callSlowPath(_llint_slow_path_get_by_id)
     1351    dispatch(9)
     1352
     1353
    12971354_llint_op_get_array_length:
    12981355    traceExecution()
  • trunk/Source/JavaScriptCore/runtime/Identifier.h

    r196785 r202627  
    8888class Identifier {
    8989    friend class Structure;
     90    friend class LLIntOffsetsExtractor;
    9091public:
    9192    Identifier() { }
Note: See TracChangeset for help on using the changeset viewer.