Changeset 277926 in webkit


Ignore:
Timestamp:
May 22, 2021 8:50:06 PM (14 months ago)
Author:
Ross Kirsling
Message:

Support Ergonomic Brand Checks proposal (#x in obj)
https://bugs.webkit.org/show_bug.cgi?id=221093

Reviewed by Caio Araujo Neponoceno de Lima.

JSTests:

  • stress/private-in.js: Added.
  • test262/config.yaml: Add feature flag.

Source/JavaScriptCore:

This patch implements the following Stage 3 proposal (behind a runtime option):
https://github.com/tc39/proposal-private-fields-in-in

Specifically, it extends the in keyword to allow the LHS to be a private name,
thereby allowing users to implement Array.isArray-esque brand checks for their own classes
*without* having to wrap a private member get in a try-catch.

For example:
`
class C {

#x;
static isC(obj) { return #x in obj; }

}
`

This is done by adding two new bytecode ops, HasPrivateName and HasPrivateBrand. For the moment,
these are implemented without fast paths, as we should do so for InByVal first and then have these follow suit.

  • bytecode/BytecodeList.rb:
  • bytecode/BytecodeUseDef.cpp:

(JSC::computeUsesForBytecodeIndexImpl):
(JSC::computeDefsForBytecodeIndexImpl):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitHasPrivateName):
(JSC::BytecodeGenerator::emitHasPrivateBrand):
(JSC::BytecodeGenerator::emitCheckPrivateBrand):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::InNode::emitBytecode):

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGByteCodeParser.cpp:

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

  • dfg/DFGCapabilities.cpp:

(JSC::DFG::capabilityLevel):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGNodeType.h:
  • dfg/DFGPredictionPropagationPhase.cpp:
  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileHasPrivateName):
(JSC::DFG::SpeculativeJIT::compileHasPrivateBrand):

  • dfg/DFGSpeculativeJIT.h:
  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileHasPrivateName):
(JSC::FTL::DFG::LowerDFGToB3::compileHasPrivateBrand):

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):

  • jit/JITOperations.cpp:

(JSC::JSC_DEFINE_JIT_OPERATION):

  • jit/JITOperations.h:
  • llint/LowLevelInterpreter.asm:
  • parser/ASTBuilder.h:

(JSC::ASTBuilder::createPrivateIdentifierNode):

  • parser/NodeConstructors.h:

(JSC::PrivateIdentifierNode::PrivateIdentifierNode):

  • parser/Nodes.h:

(JSC::ExpressionNode::isPrivateIdentifier const):

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseBinaryExpression):

  • parser/SyntaxChecker.h:

(JSC::SyntaxChecker::createPrivateIdentifierNode):

  • parser/VariableEnvironment.h:
  • runtime/CommonSlowPaths.cpp:

(JSC::JSC_DEFINE_COMMON_SLOW_PATH):

  • runtime/CommonSlowPaths.h:
  • runtime/JSObject.h:
  • runtime/JSObjectInlines.h:

(JSC::JSObject::hasPrivateField):
(JSC::JSObject::hasPrivateBrand):
(JSC::JSObject::checkPrivateBrand):

  • runtime/OptionsList.h:
Location:
trunk
Files:
1 added
38 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r277851 r277926  
     12021-05-22  Ross Kirsling  <ross.kirsling@sony.com>
     2
     3        Support Ergonomic Brand Checks proposal (`#x in obj`)
     4        https://bugs.webkit.org/show_bug.cgi?id=221093
     5
     6        Reviewed by Caio Araujo Neponoceno de Lima.
     7
     8        * stress/private-in.js: Added.
     9        * test262/config.yaml: Add feature flag.
     10
    1112021-05-21  Angelos Oikonomopoulos  <angelos@igalia.com>
    212
  • trunk/JSTests/test262/config.yaml

    r277221 r277926  
    66  class-fields-private: usePrivateClassFields
    77  class-methods-private: usePrivateMethods
     8  class-fields-private-in: usePrivateIn
    89  class-static-fields-public: usePublicStaticClassFields
    910  class-static-fields-private: usePrivateStaticClassFields
     
    2425    - legacy-regexp
    2526    - cleanupSome
    26     # https://bugs.webkit.org/show_bug.cgi?id=221093
    27     - class-fields-private-in
    2827  paths:
    2928  files:
  • trunk/Source/JavaScriptCore/ChangeLog

    r277920 r277926  
     12021-05-22  Ross Kirsling  <ross.kirsling@sony.com>
     2
     3        Support Ergonomic Brand Checks proposal (`#x in obj`)
     4        https://bugs.webkit.org/show_bug.cgi?id=221093
     5
     6        Reviewed by Caio Araujo Neponoceno de Lima.
     7
     8        This patch implements the following Stage 3 proposal (behind a runtime option):
     9        https://github.com/tc39/proposal-private-fields-in-in
     10
     11        Specifically, it extends the `in` keyword to allow the LHS to be a private name,
     12        thereby allowing users to implement Array.isArray-esque brand checks for their own classes
     13        *without* having to wrap a private member get in a try-catch.
     14
     15        For example:
     16        ```
     17        class C {
     18            #x;
     19            static isC(obj) { return #x in obj; }
     20        }
     21        ```
     22
     23        This is done by adding two new bytecode ops, HasPrivateName and HasPrivateBrand. For the moment,
     24        these are implemented without fast paths, as we should do so for InByVal first and then have these follow suit.
     25
     26        * bytecode/BytecodeList.rb:
     27        * bytecode/BytecodeUseDef.cpp:
     28        (JSC::computeUsesForBytecodeIndexImpl):
     29        (JSC::computeDefsForBytecodeIndexImpl):
     30        * bytecompiler/BytecodeGenerator.cpp:
     31        (JSC::BytecodeGenerator::emitHasPrivateName):
     32        (JSC::BytecodeGenerator::emitHasPrivateBrand):
     33        (JSC::BytecodeGenerator::emitCheckPrivateBrand):
     34        * bytecompiler/BytecodeGenerator.h:
     35        * bytecompiler/NodesCodegen.cpp:
     36        (JSC::InNode::emitBytecode):
     37        * dfg/DFGAbstractInterpreterInlines.h:
     38        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     39        * dfg/DFGByteCodeParser.cpp:
     40        (JSC::DFG::ByteCodeParser::parseBlock):
     41        * dfg/DFGCapabilities.cpp:
     42        (JSC::DFG::capabilityLevel):
     43        * dfg/DFGClobberize.h:
     44        (JSC::DFG::clobberize):
     45        * dfg/DFGDoesGC.cpp:
     46        (JSC::DFG::doesGC):
     47        * dfg/DFGFixupPhase.cpp:
     48        (JSC::DFG::FixupPhase::fixupNode):
     49        * dfg/DFGNodeType.h:
     50        * dfg/DFGPredictionPropagationPhase.cpp:
     51        * dfg/DFGSafeToExecute.h:
     52        (JSC::DFG::safeToExecute):
     53        * dfg/DFGSpeculativeJIT.cpp:
     54        (JSC::DFG::SpeculativeJIT::compileHasPrivateName):
     55        (JSC::DFG::SpeculativeJIT::compileHasPrivateBrand):
     56        * dfg/DFGSpeculativeJIT.h:
     57        * dfg/DFGSpeculativeJIT32_64.cpp:
     58        (JSC::DFG::SpeculativeJIT::compile):
     59        * dfg/DFGSpeculativeJIT64.cpp:
     60        (JSC::DFG::SpeculativeJIT::compile):
     61        * ftl/FTLCapabilities.cpp:
     62        (JSC::FTL::canCompile):
     63        * ftl/FTLLowerDFGToB3.cpp:
     64        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
     65        (JSC::FTL::DFG::LowerDFGToB3::compileHasPrivateName):
     66        (JSC::FTL::DFG::LowerDFGToB3::compileHasPrivateBrand):
     67        * jit/JIT.cpp:
     68        (JSC::JIT::privateCompileMainPass):
     69        * jit/JITOperations.cpp:
     70        (JSC::JSC_DEFINE_JIT_OPERATION):
     71        * jit/JITOperations.h:
     72        * llint/LowLevelInterpreter.asm:
     73        * parser/ASTBuilder.h:
     74        (JSC::ASTBuilder::createPrivateIdentifierNode):
     75        * parser/NodeConstructors.h:
     76        (JSC::PrivateIdentifierNode::PrivateIdentifierNode):
     77        * parser/Nodes.h:
     78        (JSC::ExpressionNode::isPrivateIdentifier const):
     79        * parser/Parser.cpp:
     80        (JSC::Parser<LexerType>::parseBinaryExpression):
     81        * parser/SyntaxChecker.h:
     82        (JSC::SyntaxChecker::createPrivateIdentifierNode):
     83        * parser/VariableEnvironment.h:
     84        * runtime/CommonSlowPaths.cpp:
     85        (JSC::JSC_DEFINE_COMMON_SLOW_PATH):
     86        * runtime/CommonSlowPaths.h:
     87        * runtime/JSObject.h:
     88        * runtime/JSObjectInlines.h:
     89        (JSC::JSObject::hasPrivateField):
     90        (JSC::JSObject::hasPrivateBrand):
     91        (JSC::JSObject::checkPrivateBrand):
     92        * runtime/OptionsList.h:
     93
    1942021-05-22  Chris Dumez  <cdumez@apple.com>
    295
  • trunk/Source/JavaScriptCore/bytecode/BytecodeList.rb

    r276896 r277926  
    455455    }
    456456
     457op :has_private_name,
     458    args: {
     459        dst: VirtualRegister,
     460        base: VirtualRegister,
     461        property: VirtualRegister,
     462    }
     463
     464op :has_private_brand,
     465    args: {
     466        dst: VirtualRegister,
     467        base: VirtualRegister,
     468        brand: VirtualRegister,
     469    }
     470
    457471op :get_by_id,
    458472    args: {
     
    609623        brand: WriteBarrier[JSCell],
    610624    }
    611    
    612625
    613626op :put_by_val,
  • trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.cpp

    r273225 r277926  
    233233    USES(OpCheckPrivateBrand, base, brand)
    234234    USES(OpInByVal, base, property)
     235    USES(OpHasPrivateName, base, property)
     236    USES(OpHasPrivateBrand, base, brand)
    235237    USES(OpOverridesHasInstance, constructor, hasInstanceValue)
    236238    USES(OpInstanceof, value, prototype)
     
    510512    DEFS(OpInById, dst)
    511513    DEFS(OpInByVal, dst)
     514    DEFS(OpHasPrivateName, dst)
     515    DEFS(OpHasPrivateBrand, dst)
    512516    DEFS(OpToNumber, dst)
    513517    DEFS(OpToNumeric, dst)
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r276719 r277926  
    27252725}
    27262726
     2727RegisterID* BytecodeGenerator::emitHasPrivateName(RegisterID* dst, RegisterID* base, RegisterID* property)
     2728{
     2729    OpHasPrivateName::emit(this, dst, base, property);
     2730    return dst;
     2731}
     2732
    27272733RegisterID* BytecodeGenerator::emitDirectPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
    27282734{
     
    27972803}
    27982804
     2805RegisterID* BytecodeGenerator::emitHasPrivateBrand(RegisterID* dst, RegisterID* base, RegisterID* brand, bool isStatic)
     2806{
     2807    if (isStatic) {
     2808        Ref<Label> isObjectLabel = newLabel();
     2809        emitJumpIfTrue(emitIsObject(newTemporary(), base), isObjectLabel.get());
     2810        emitThrowTypeError("Cannot access static private method or accessor of a non-Object");
     2811        emitLabel(isObjectLabel.get());
     2812        emitEqualityOp<OpStricteq>(dst, base, brand);
     2813    } else
     2814        OpHasPrivateBrand::emit(this, dst, base, brand);
     2815    return dst;
     2816}
     2817
    27992818void BytecodeGenerator::emitCheckPrivateBrand(RegisterID* base, RegisterID* brand, bool isStatic)
    28002819{
     
    28022821        Ref<Label> brandCheckOkLabel = newLabel();
    28032822        emitJumpIfTrue(emitEqualityOp<OpStricteq>(newTemporary(), base, brand), brandCheckOkLabel.get());
    2804         emitThrowTypeError("Cannot access static private method or acessor");
     2823        emitThrowTypeError("Cannot access static private method or accessor");
    28052824        emitLabel(brandCheckOkLabel.get());
    28062825        return;
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r276384 r277926  
    841841        RegisterID* emitPrivateFieldPut(RegisterID* base, RegisterID* property, RegisterID* value);
    842842        RegisterID* emitGetPrivateName(RegisterID* dst, RegisterID* base, RegisterID* property);
     843        RegisterID* emitHasPrivateName(RegisterID* dst, RegisterID* base, RegisterID* property);
    843844
    844845        void emitCreatePrivateBrand(RegisterID* dst, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
     
    847848
    848849        RegisterID* emitGetPrivateBrand(RegisterID* dst, RegisterID* scope, bool isStatic);
     850        RegisterID* emitHasPrivateBrand(RegisterID* dst, RegisterID* base, RegisterID* brand, bool isStatic);
    849851        void emitCheckPrivateBrand(RegisterID* base, RegisterID* brand, bool isStatic);
    850852
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r275439 r277926  
    32073207RegisterID* InNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    32083208{
     3209    if (m_expr1->isPrivateIdentifier()) {
     3210        RefPtr<RegisterID> base = generator.emitNode(m_expr2);
     3211
     3212        auto identifier = static_cast<PrivateIdentifierNode*>(m_expr1)->value();
     3213        auto privateTraits = generator.getPrivateTraits(identifier);
     3214        Variable var = generator.variable(identifier);
     3215        RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
     3216
     3217        if (privateTraits.isField()) {
     3218            RefPtr<RegisterID> privateName = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
     3219            return generator.emitHasPrivateName(generator.finalDestination(dst, base.get()), base.get(), privateName.get());
     3220        }
     3221
     3222        ASSERT(privateTraits.isPrivateMethodOrAccessor());
     3223        RefPtr<RegisterID> privateBrand = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get(), privateTraits.isStatic());
     3224        return generator.emitHasPrivateBrand(generator.finalDestination(dst, base.get()), base.get(), privateBrand.get(), privateTraits.isStatic());
     3225    }
     3226
    32093227    if (isNonIndexStringElement(*m_expr1)) {
    32103228        RefPtr<RegisterID> base = generator.emitNode(m_expr2);
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r277909 r277926  
    42134213    }
    42144214
     4215    case HasPrivateName:
     4216    case HasPrivateBrand: {
     4217        clobberWorld();
     4218        filter(node->child1(), SpecObject);
     4219        filter(node->child2(), SpecSymbol);
     4220        setNonCellTypeForNode(node, SpecBoolean);
     4221        break;
     4222    }
     4223
    42154224    case HasOwnProperty: {
    42164225        clobberWorld();
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r277758 r277926  
    82588258            NEXT_OPCODE(op_in_by_id);
    82598259        }
     8260       
     8261        case op_has_private_name: {
     8262            // FIXME: Improve this once InByVal has been optimized.
     8263            // https://bugs.webkit.org/show_bug.cgi?id=226146
     8264            auto bytecode = currentInstruction->as<OpHasPrivateName>();
     8265            set(bytecode.m_dst, addToGraph(HasPrivateName, get(bytecode.m_base), get(bytecode.m_property)));
     8266            NEXT_OPCODE(op_has_private_name);
     8267        }
     8268
     8269        case op_has_private_brand: {
     8270            // FIXME: Improve this once InByVal has been optimized.
     8271            // https://bugs.webkit.org/show_bug.cgi?id=226146
     8272            auto bytecode = currentInstruction->as<OpHasPrivateBrand>();
     8273            set(bytecode.m_dst, addToGraph(HasPrivateBrand, get(bytecode.m_base), get(bytecode.m_brand)));
     8274            NEXT_OPCODE(op_has_private_brand);
     8275        }
    82608276
    82618277        case op_get_enumerable_length: {
  • trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp

    r276896 r277926  
    251251    case op_in_by_val:
    252252    case op_in_by_id:
     253    case op_has_private_name:
     254    case op_has_private_brand:
    253255    case op_get_scope:
    254256    case op_get_from_scope:
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r274037 r277926  
    707707    case InByVal:
    708708    case InById:
     709    case HasPrivateName:
     710    case HasPrivateBrand:
    709711    case HasOwnProperty:
    710712    case ValueNegate:
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r274037 r277926  
    308308    case InById:
    309309    case InByVal:
     310    case HasPrivateName:
     311    case HasPrivateBrand:
    310312    case InstanceOf:
    311313    case InstanceOfCustom:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r274037 r277926  
    21042104
    21052105            fixEdge<CellUse>(node->child1());
     2106            break;
     2107        }
     2108
     2109        case HasPrivateName:
     2110        case HasPrivateBrand: {
     2111            fixEdge<CellUse>(node->child1());
     2112            fixEdge<SymbolUse>(node->child2());
    21062113            break;
    21072114        }
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r274037 r277926  
    432432    macro(InByVal, NodeResultBoolean | NodeMustGenerate) \
    433433    macro(InById, NodeResultBoolean | NodeMustGenerate) \
     434    macro(HasPrivateName, NodeResultBoolean | NodeMustGenerate) \
     435    macro(HasPrivateBrand, NodeResultBoolean | NodeMustGenerate) \
    434436    macro(ProfileType, NodeMustGenerate) \
    435437    macro(ProfileControlFlow, NodeMustGenerate) \
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r274037 r277926  
    12051205            break;
    12061206
     1207        case GetEnumerableLength: {
     1208            setPrediction(SpecInt32Only);
     1209            break;
     1210        }
    12071211        case InByVal:
    12081212        case InById:
    1209             setPrediction(SpecBoolean);
    1210             break;
    1211 
     1213        case HasPrivateName:
     1214        case HasPrivateBrand:
    12121215        case HasOwnProperty:
    1213             setPrediction(SpecBoolean);
    1214             break;
    1215 
    1216         case GetEnumerableLength: {
    1217             setPrediction(SpecInt32Only);
    1218             break;
    1219         }
    12201216        case HasOwnStructureProperty:
    12211217        case InStructureProperty:
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r274037 r277926  
    592592    case InByVal:
    593593    case InById:
     594    case HasPrivateName:
     595    case HasPrivateBrand:
    594596    case HasOwnProperty:
    595597    case PushWithScope:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r277117 r277926  
    12791279    JSValueRegs resultRegs = result.regs();
    12801280    callOperation(operationInByVal, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, regs);
     1281    m_jit.exceptionCheck();
     1282    blessedBooleanResult(resultRegs.payloadGPR(), node, UseChildrenCalledExplicitly);
     1283}
     1284
     1285void SpeculativeJIT::compileHasPrivateName(Node* node)
     1286{
     1287    SpeculateCellOperand base(this, node->child1());
     1288    SpeculateCellOperand key(this, node->child2());
     1289
     1290    GPRReg baseGPR = base.gpr();
     1291    GPRReg keyGPR = key.gpr();
     1292
     1293    speculateSymbol(node->child2(), keyGPR);
     1294
     1295    base.use();
     1296    key.use();
     1297
     1298    flushRegisters();
     1299    JSValueRegsFlushedCallResult result(this);
     1300    JSValueRegs resultRegs = result.regs();
     1301    callOperation(operationHasPrivateName, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, CCallHelpers::CellValue(keyGPR));
     1302    m_jit.exceptionCheck();
     1303    blessedBooleanResult(resultRegs.payloadGPR(), node, UseChildrenCalledExplicitly);
     1304}
     1305
     1306void SpeculativeJIT::compileHasPrivateBrand(Node* node)
     1307{
     1308    SpeculateCellOperand base(this, node->child1());
     1309    SpeculateCellOperand brand(this, node->child2());
     1310
     1311    GPRReg baseGPR = base.gpr();
     1312    GPRReg brandGPR = brand.gpr();
     1313
     1314    speculateSymbol(node->child2(), brandGPR);
     1315
     1316    base.use();
     1317    brand.use();
     1318
     1319    flushRegisters();
     1320    JSValueRegsFlushedCallResult result(this);
     1321    JSValueRegs resultRegs = result.regs();
     1322    callOperation(operationHasPrivateBrand, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, CCallHelpers::CellValue(brandGPR));
    12811323    m_jit.exceptionCheck();
    12821324    blessedBooleanResult(resultRegs.payloadGPR(), node, UseChildrenCalledExplicitly);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r275079 r277926  
    739739    void compileInById(Node*);
    740740    void compileInByVal(Node*);
     741    void compileHasPrivateName(Node*);
     742    void compileHasPrivateBrand(Node*);
    741743   
    742744    void nonSpeculativeNonPeepholeCompareNullOrUndefined(Edge operand);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r277680 r277926  
    39843984    case InByVal:
    39853985        compileInByVal(node);
     3986        break;
     3987
     3988    case HasPrivateName:
     3989        compileHasPrivateName(node);
     3990        break;
     3991
     3992    case HasPrivateBrand:
     3993        compileHasPrivateBrand(node);
    39863994        break;
    39873995
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r277680 r277926  
    49514951    case InByVal:
    49524952        compileInByVal(node);
     4953        break;
     4954
     4955    case HasPrivateName:
     4956        compileHasPrivateName(node);
     4957        break;
     4958
     4959    case HasPrivateBrand:
     4960        compileHasPrivateBrand(node);
    49534961        break;
    49544962
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r274037 r277926  
    244244    case InByVal:
    245245    case InById:
     246    case HasPrivateName:
     247    case HasPrivateBrand:
    246248    case HasOwnProperty:
    247249    case IsCellWithType:
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r277680 r277926  
    963963            compileInByVal();
    964964            break;
     965        case HasPrivateName:
     966            compileHasPrivateName();
     967            break;
     968        case HasPrivateBrand:
     969            compileHasPrivateBrand();
     970            break;
    965971        case CheckPrivateBrand:
    966972            compileCheckPrivateBrand();
     
    1221312219        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
    1221412220        setJSValue(vmCall(Int64, operationInByVal, weakPointer(globalObject), lowCell(m_node->child1()), lowJSValue(m_node->child2())));
     12221    }
     12222   
     12223    void compileHasPrivateName()
     12224    {
     12225        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
     12226        setJSValue(vmCall(Int64, operationHasPrivateName, weakPointer(globalObject), lowCell(m_node->child1()), lowSymbol(m_node->child2())));
     12227    }
     12228
     12229    void compileHasPrivateBrand()
     12230    {
     12231        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
     12232        setJSValue(vmCall(Int64, operationHasPrivateBrand, weakPointer(globalObject), lowCell(m_node->child1()), lowSymbol(m_node->child2())));
    1221512233    }
    1221612234
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r277850 r277926  
    282282        switch (opcodeID) {
    283283        DEFINE_SLOW_OP(in_by_val)
     284        DEFINE_SLOW_OP(has_private_name)
     285        DEFINE_SLOW_OP(has_private_brand)
    284286        DEFINE_SLOW_OP(less)
    285287        DEFINE_SLOW_OP(lesseq)
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r277680 r277926  
    463463
    464464    return JSValue::encode(jsBoolean(CommonSlowPaths::opInByVal(globalObject, base, JSValue::decode(key))));
     465}
     466
     467JSC_DEFINE_JIT_OPERATION(operationHasPrivateName, EncodedJSValue, (JSGlobalObject* globalObject, JSCell* base, EncodedJSValue key))
     468{
     469    SuperSamplerScope superSamplerScope(false);
     470   
     471    VM& vm = globalObject->vm();
     472    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     473    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
     474
     475    auto scope = DECLARE_THROW_SCOPE(vm);
     476    if (!base->isObject()) {
     477        throwException(globalObject, scope, createInvalidInParameterError(globalObject, base));
     478        return encodedJSValue();
     479    }
     480
     481    JSValue propertyValue = JSValue::decode(key);
     482    ASSERT(propertyValue.isSymbol());
     483    auto property = propertyValue.toPropertyKey(globalObject);
     484    EXCEPTION_ASSERT(!scope.exception());
     485
     486    return JSValue::encode(jsBoolean(asObject(base)->hasPrivateField(globalObject, property)));
     487}
     488
     489JSC_DEFINE_JIT_OPERATION(operationHasPrivateBrand, EncodedJSValue, (JSGlobalObject* globalObject, JSCell* base, EncodedJSValue brand))
     490{
     491    SuperSamplerScope superSamplerScope(false);
     492   
     493    VM& vm = globalObject->vm();
     494    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     495    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
     496
     497    auto scope = DECLARE_THROW_SCOPE(vm);
     498    if (!base->isObject()) {
     499        throwException(globalObject, scope, createInvalidInParameterError(globalObject, base));
     500        return encodedJSValue();
     501    }
     502
     503    return JSValue::encode(jsBoolean(asObject(base)->hasPrivateBrand(globalObject, JSValue::decode(brand))));
    465504}
    466505
  • trunk/Source/JavaScriptCore/jit/JITOperations.h

    r275995 r277926  
    179179
    180180JSC_DECLARE_JIT_OPERATION(operationInByVal, EncodedJSValue, (JSGlobalObject*, JSCell*, EncodedJSValue));
     181JSC_DECLARE_JIT_OPERATION(operationHasPrivateName, EncodedJSValue, (JSGlobalObject*, JSCell*, EncodedJSValue));
     182JSC_DECLARE_JIT_OPERATION(operationHasPrivateBrand, EncodedJSValue, (JSGlobalObject*, JSCell*, EncodedJSValue));
    181183
    182184JSC_DECLARE_JIT_OPERATION(operationPutByIdStrict, void, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t));
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r277716 r277926  
    20122012
    20132013slowPathOp(in_by_val)
     2014slowPathOp(has_private_name)
     2015slowPathOp(has_private_brand)
    20142016slowPathOp(is_callable)
    20152017slowPathOp(is_constructor)
  • trunk/Source/JavaScriptCore/parser/ASTBuilder.h

    r275439 r277926  
    208208        return new (m_parserArena) ResolveNode(location, ident, start);
    209209    }
     210    ExpressionNode* createPrivateIdentifierNode(const JSTokenLocation& location, const Identifier& ident)
     211    {
     212        return new (m_parserArena) PrivateIdentifierNode(location, ident);
     213    }
    210214    ExpressionNode* createObjectLiteral(const JSTokenLocation& location) { return new (m_parserArena) ObjectLiteralNode(location); }
    211215    ExpressionNode* createObjectLiteral(const JSTokenLocation& location, PropertyListNode* properties) { return new (m_parserArena) ObjectLiteralNode(location, properties); }
  • trunk/Source/JavaScriptCore/parser/NodeConstructors.h

    r271265 r277926  
    210210    }
    211211
     212    inline PrivateIdentifierNode::PrivateIdentifierNode(const JSTokenLocation& location, const Identifier& ident)
     213        : ExpressionNode(location)
     214        , m_ident(ident)
     215    {
     216    }
     217
    212218    inline ElementNode::ElementNode(int elision, ExpressionNode* node)
    213219        : m_node(node)
  • trunk/Source/JavaScriptCore/parser/Nodes.h

    r277714 r277926  
    214214        virtual bool isDeleteNode() const { return false; }
    215215        virtual bool isOptionalChain() const { return false; }
     216        virtual bool isPrivateIdentifier() const { return false; }
    216217
    217218        virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label&, Label&, FallThroughMode);
     
    682683        const Identifier& m_ident;
    683684        JSTextPosition m_start;
     685    };
     686
     687    // Dummy expression to hold the LHS of `#x in obj`.
     688    class PrivateIdentifierNode final : public ExpressionNode {
     689    public:
     690        PrivateIdentifierNode(const JSTokenLocation&, const Identifier&);
     691
     692        const Identifier& value() const { return m_ident; }
     693
     694    private:
     695        RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = nullptr) final { RELEASE_ASSERT_NOT_REACHED(); }
     696
     697        bool isPrivateIdentifier() const final { return true; }
     698
     699        const Identifier& m_ident;
    684700    };
    685701
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r276942 r277926  
    42344234        int initialAssignments = m_parserState.assignmentCount;
    42354235        JSTokenType leadingTokenTypeForUnaryExpression = m_token.m_type;
    4236         TreeExpression current = parseUnaryExpression(context);
     4236
     4237        TreeExpression current = 0;
     4238        if (Options::usePrivateIn() && match(PRIVATENAME)) {
     4239            const Identifier* ident = m_token.m_data.ident;
     4240            ASSERT(ident);
     4241            semanticFailIfFalse(usePrivateName(ident), "Cannot reference private names outside of class");
     4242            currentScope()->useVariable(ident, false);
     4243            next();
     4244            semanticFailIfTrue(m_token.m_type != INTOKEN, "Bare private name can only be used as the left-hand side of an `in` expression");
     4245            current = context.createPrivateIdentifierNode(location, *ident);
     4246        } else
     4247            current = parseUnaryExpression(context);
    42374248        failIfFalse(current, "Cannot parse expression");
    42384249
  • trunk/Source/JavaScriptCore/parser/SyntaxChecker.h

    r275439 r277926  
    8686        TemplateExpressionListResult, TemplateExpr,
    8787        TaggedTemplateExpr, YieldExpr, AwaitExpr,
    88         ModuleNameResult,
     88        ModuleNameResult, PrivateIdentifier,
    8989        ImportSpecifierResult, ImportSpecifierListResult,
    9090        ExportSpecifierResult, ExportSpecifierListResult,
     
    169169    ALWAYS_INLINE bool isImportMeta(ExpressionType type) { return type == ImportMetaExpr; }
    170170    ExpressionType createResolve(const JSTokenLocation&, const Identifier&, int, int) { return ResolveExpr; }
     171    ExpressionType createPrivateIdentifierNode(const JSTokenLocation&, const Identifier&) { return PrivateIdentifier; }
    171172    ExpressionType createObjectLiteral(const JSTokenLocation&) { return ObjectLiteralExpr; }
    172173    ExpressionType createObjectLiteral(const JSTokenLocation&, int) { return ObjectLiteralExpr; }
  • trunk/Source/JavaScriptCore/parser/VariableEnvironment.h

    r273107 r277926  
    110110    ALWAYS_INLINE bool isSetter() const { return m_bits & IsSetter; }
    111111    ALWAYS_INLINE bool isGetter() const { return m_bits & IsGetter; }
    112     ALWAYS_INLINE bool isField() const { return !isPrivateMethodOrAcessor(); }
     112    ALWAYS_INLINE bool isField() const { return !isPrivateMethodOrAccessor(); }
    113113    ALWAYS_INLINE bool isStatic() const { return m_bits & IsStatic; }
    114114
    115     bool isPrivateMethodOrAcessor() const { return isMethod() || isSetter() || isGetter(); }
     115    bool isPrivateMethodOrAccessor() const { return isMethod() || isSetter() || isGetter(); }
    116116
    117117    ALWAYS_INLINE void setIsUsed() { m_bits |= IsUsed; }
     
    275275
    276276        for (auto entry : privateNames()) {
    277             if (entry.value.isPrivateMethodOrAcessor() && entry.value.isStatic())
     277            if (entry.value.isPrivateMethodOrAccessor() && entry.value.isStatic())
    278278                return true;
    279279        }
     
    288288       
    289289        for (auto entry : privateNames()) {
    290             if (entry.value.isPrivateMethodOrAcessor() && !entry.value.isStatic())
     290            if (entry.value.isPrivateMethodOrAccessor() && !entry.value.isStatic())
    291291                return true;
    292292        }
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp

    r277716 r277926  
    839839}
    840840
     841JSC_DEFINE_COMMON_SLOW_PATH(slow_path_has_private_name)
     842{
     843    BEGIN();
     844
     845    auto bytecode = pc->as<OpHasPrivateName>();
     846    auto baseValue = GET_C(bytecode.m_base).jsValue();
     847    if (!baseValue.isObject())
     848        THROW(createInvalidInParameterError(globalObject, baseValue));
     849
     850    auto propertyValue = GET_C(bytecode.m_property).jsValue();
     851    ASSERT(propertyValue.isSymbol());
     852    auto property = propertyValue.toPropertyKey(globalObject);
     853    EXCEPTION_ASSERT(!throwScope.exception());
     854
     855    RETURN(jsBoolean(asObject(baseValue)->hasPrivateField(globalObject, property)));
     856}
     857
     858JSC_DEFINE_COMMON_SLOW_PATH(slow_path_has_private_brand)
     859{
     860    BEGIN();
     861
     862    auto bytecode = pc->as<OpHasPrivateBrand>();
     863    auto baseValue = GET_C(bytecode.m_base).jsValue();
     864    if (!baseValue.isObject())
     865        THROW(createInvalidInParameterError(globalObject, baseValue));
     866
     867    RETURN(jsBoolean(asObject(baseValue)->hasPrivateBrand(globalObject, GET_C(bytecode.m_brand).jsValue())));
     868}
     869
    841870template<OpcodeSize width>
    842871ALWAYS_INLINE SlowPathReturnType iteratorOpenTryFastImpl(VM& vm, JSGlobalObject* globalObject, CodeBlock* codeBlock, CallFrame* callFrame, const Instruction* pc)
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h

    r277716 r277926  
    253253JSC_DECLARE_COMMON_SLOW_PATH(slow_path_is_constructor);
    254254JSC_DECLARE_COMMON_SLOW_PATH(slow_path_in_by_val);
     255JSC_DECLARE_COMMON_SLOW_PATH(slow_path_has_private_name);
     256JSC_DECLARE_COMMON_SLOW_PATH(slow_path_has_private_brand);
    255257JSC_DECLARE_COMMON_SLOW_PATH(slow_path_strcat);
    256258JSC_DECLARE_COMMON_SLOW_PATH(slow_path_to_primitive);
  • trunk/Source/JavaScriptCore/runtime/JSObject.h

    r277665 r277926  
    180180
    181181    static bool getPrivateFieldSlot(JSObject*, JSGlobalObject*, PropertyName, PropertySlot&);
     182    inline bool hasPrivateField(JSGlobalObject*, PropertyName);
    182183    inline bool getPrivateField(JSGlobalObject*, PropertyName, PropertySlot&);
    183184    inline void setPrivateField(JSGlobalObject*, PropertyName, JSValue, PutPropertySlot&);
    184185    inline void definePrivateField(JSGlobalObject*, PropertyName, JSValue, PutPropertySlot&);
    185     inline bool checkPrivateBrand(JSGlobalObject*, JSValue brand);
     186    inline bool hasPrivateBrand(JSGlobalObject*, JSValue brand);
     187    inline void checkPrivateBrand(JSGlobalObject*, JSValue brand);
    186188    inline void setPrivateBrand(JSGlobalObject*, JSValue brand);
    187189
  • trunk/Source/JavaScriptCore/runtime/JSObjectInlines.h

    r277665 r277926  
    616616}
    617617
     618inline bool JSObject::hasPrivateField(JSGlobalObject* globalObject, PropertyName propertyName)
     619{
     620    ASSERT(propertyName.isPrivateName());
     621    VM& vm = getVM(globalObject);
     622    unsigned attributes;
     623    return structure(vm)->get(vm, propertyName, attributes) != invalidOffset;
     624}
     625
    618626inline bool JSObject::getPrivateField(JSGlobalObject* globalObject, PropertyName propertyName, PropertySlot& slot)
    619627{
     
    677685}
    678686
    679 inline bool JSObject::checkPrivateBrand(JSGlobalObject* globalObject, JSValue brand)
    680 {
    681     ASSERT(brand.isSymbol());
    682     VM& vm = getVM(globalObject);
    683     auto scope = DECLARE_THROW_SCOPE(vm);
    684 
     687inline bool JSObject::hasPrivateBrand(JSGlobalObject* globalObject, JSValue brand)
     688{
     689    ASSERT(brand.isSymbol() && asSymbol(brand)->uid().isPrivate());
     690    VM& vm = getVM(globalObject);
    685691    Structure* structure = this->structure(vm);
    686     if (!structure->isBrandedStructure() || !jsCast<BrandedStructure*>(structure)->checkBrand(asSymbol(brand))) {
     692    return structure->isBrandedStructure() && jsCast<BrandedStructure*>(structure)->checkBrand(asSymbol(brand));
     693}
     694
     695inline void JSObject::checkPrivateBrand(JSGlobalObject* globalObject, JSValue brand)
     696{
     697    ASSERT(brand.isSymbol() && asSymbol(brand)->uid().isPrivate());
     698    VM& vm = getVM(globalObject);
     699    auto scope = DECLARE_THROW_SCOPE(vm);
     700
     701    Structure* structure = this->structure(vm);
     702    if (!structure->isBrandedStructure() || !jsCast<BrandedStructure*>(structure)->checkBrand(asSymbol(brand)))
    687703        throwException(globalObject, scope, createPrivateMethodAccessError(globalObject));
    688         RELEASE_AND_RETURN(scope, false);
    689     }
    690     EXCEPTION_ASSERT(!scope.exception());
    691 
    692     return true;
    693704}
    694705
    695706inline void JSObject::setPrivateBrand(JSGlobalObject* globalObject, JSValue brand)
    696707{
    697     ASSERT(brand.isSymbol());
     708    ASSERT(brand.isSymbol() && asSymbol(brand)->uid().isPrivate());
    698709    VM& vm = getVM(globalObject);
    699710    auto scope = DECLARE_THROW_SCOPE(vm);
  • trunk/Source/JavaScriptCore/runtime/OptionsList.h

    r277110 r277926  
    522522    v(Bool, usePrivateClassFields, true, Normal, "If true, the parser will understand private data fields inside classes.") \
    523523    v(Bool, usePrivateMethods, true, Normal, "If true, the parser will understand private methods inside classes.") \
     524    v(Bool, usePrivateIn, false, Normal, "If true, the parser will understand private member existence checks with the `in` operator.") \
    524525    v(Bool, useWebAssemblyStreaming, true, Normal, "Allow to run WebAssembly's Streaming API") \
    525526    v(Bool, useWebAssemblyReferences, true, Normal, "Allow types from the wasm references spec.") \
Note: See TracChangeset for help on using the changeset viewer.