Ignore:
Timestamp:
Feb 9, 2021, 8:30:24 AM (4 years ago)
Author:
Caio Lima
Message:

[ESNext] Implement private methods
https://bugs.webkit.org/show_bug.cgi?id=194434

Reviewed by Filip Pizlo.

JSTests:

  • stress/private-brand-installed-after-super-call-from-arrow-function.js: Added.
  • stress/private-brand-installed-after-super-call-from-eval.js: Added.
  • stress/private-method-brand-check.js: Added.
  • stress/private-method-change-attribute-from-branded-structure.js: Added.
  • stress/private-method-change-prototype-from-branded-structure.js: Added.
  • stress/private-method-check-private-brand-ic.js: Added.
  • stress/private-method-check-structure-miss.js: Added.
  • stress/private-method-comparison.js: Added.
  • stress/private-method-delete-property-from-branded-structure.js: Added.
  • stress/private-method-extends-brand-check.js: Added.
  • stress/private-method-get-and-call.js: Added.
  • stress/private-method-invalid-multiple-brand-installation.js: Added.
  • stress/private-method-invalidate-compiled-with-constant-symbol.js: Added.
  • stress/private-method-nested-class.js: Added.
  • stress/private-method-on-sealed-objects.js: Added.
  • stress/private-method-on-uncacheable-dictionary.js: Added.
  • stress/private-method-polymorphic-with-constant-symbol.js: Added.
  • stress/private-method-set-brand-should-have-write-barrier.js: Added.
  • stress/private-method-untyped-use.js: Added.
  • stress/private-method-with-uncacheable-dictionary-transition.js: Added.
  • stress/private-methods-inline-cache.js: Added.
  • stress/private-methods-megamorphic-ic.js: Added.
  • stress/private-methods-on-proxy.js: Added.
  • stress/private-methods-poly-ic-multiple-classes.js: Added.
  • stress/private-methods-poly-ic-single-class.js: Added.
  • stress/private-names-available-on-direct-eval.js: Added.
  • test262/config.yaml:

Source/JavaScriptCore:

This patch is adding support to private methods following the
specification on https://tc39.es/proposal-private-methods/.
This is introducing a new way to declare private methods on
class syntax. Private methods are only accessible within
classes they were declared, and only can be called from
objects that are instance of these classes.
To guarantee such rules, the proposal presents the concept of
Brand Check. During class evaluation, if a private method is present,
a brand is installed in this class. Every instance of such class
then gets this brand installed during [[Construct]] operation. It
means that an object can have multiple brands (e.g when there is also
private methods declared on super class). Before accessing a private
method, there is a check to validate if the target of the call has the
brand of callee method.
The brand check mechanism is implemented using a @privateBrand
stored on class scope. Here is a representation of how this mechanism
works:

`
class C {

#m() { return 3; }
method() { return this.#m(); }

}

let c = new C();
console.log(c.method()); prints 3
`

Generated bytecode for the following representation:
`
{ class lexical scope

const @privateBrand = @createPrivateSymbol();
const #m = function () { return 3; }
C.prototype.method = function() {

@check_private_brand(this, @privateBrand);
return #m.call(this);

}
C = function() {

@set_private_brand(this, @privateBrand);

}

}

let c = new C();
console.log(c.method()); prints 3
`

# Resolving correct brand to check

In the case of shadowing or nested scope, we need to emit brand
checks to the right private brand. See code below:

`
class C {

#m() { return 3; }
method() { return this.#m();}

A = class {

#m2() { return 3; }
foo(o) { return o.#m(); }

}

}
`

The call of "#m" in foo refers to "C::#m". In such case, we need to
check C's private brand, instead of A's private brand.
To perform the proper check, we first resolve scope of "#m" and then
check the private brand of this scope (the scope where the private
method and brand are stored is the same).
So the bytecode to lookup the right brand is:

`
mov loc9, arg1
resolve_scope loc10, "#m"
get_from_scope loc11, loc10, "@privateBrand"
check_private_brand loc9, loc11
get_from_scope loc11, loc10, "#m"
setup call frame
call loc11, ...
...
`

# Brand check mechanism

We are introducing in this patch 2 new bytecodes to allow brand check
of objects: op_set_brand and op_check_brand.
op_set_brand sets a new brand in an object, so we can perform the brand
check later when accessing private methods. This operations throws when
trying to add the same brand twice in an Object.
op_check_brand checks if the given object contains the brand we are
looking for. It traverses the brand chain to verify if the brand is
present, and throws TypeError otherwise.

We are also introducing a subclass for Structure called BrandedStructure.
It is used to store brands and to allow brand check mechanism. BrandedStructure
stores a brand and a parent pointer to another BrandedStructure that allow
us traverse the brand chain. With BrandedStructure, we can then
infer that a given object has the brand we are looking for just
checking its structureId. This is a very good optimization, since we can
reduce most of brand checks to structure checks.

We created a new kind of transition called SetBrand that happens when
op_set_brand is executed. This allow us to cache such kind of
trasitions on trasition table using the key `<brand->uid, 0,
TransitionKind::SetBrand>`. During this transition, we take previous
structure and apply one of the following rules:

  1. If it's a BrandedStructure, we then set it to m_parentBrand, to allow proper brand chain check.
  1. If it's not a BrandedStructure, we set m_parentBrand to nullptr, meaning that this is the first brand being added to the object with this structure.

For now, we are using the flag isBrandedStructure to identify that a
given Structure is a BrandedStructure. This is done to avoid changes
on places where we are checking for vm.structureStructure().
However, if we ever need space on Structure, this flag is a good
candidate to be deleted and we can move to a solution that uses
vm.brandedStructureStructure();

# JIT Support

This patch also includes initial JIT support for set_private_brand
and check_private_brand. On Baseline JIT, we are using
JITPravateBrandAccessGenerator to support IC for both operands.
On DFGByteCodeParser we are trying to inline brand access whenever
possible, and fallbacking to SetPrivateBrand and
CheckPrivateBrand otherwise. Those nodes are not being optimized at
their full potential, but the code generated by them is also relying on
JITPrivateBrandAccessGenerator to have IC support for both DFG and
FTL. During DFG parsing, we try to reduce those access to CheckIsConstant
and CheckStructure (with PutStructure for set_private_brand cases)
based on available profiled data. This is meant to make brand checks
almost free on DFG/FTL tiers when we have a single evaluation of a
class, since the CheckIsConstant can be eliminated by the constant-folded
scope load, and the CheckStructure is very likely to be redundant
to any other CheckStructure that can be performed on receiver
when we have a finite structure set.
For instance, when we have a brand check on a path-of-no-return to
a GetByOffset sequence on the same receiver, the CheckStructure
for the brand check will enable CSE of the CheckStructure that
would happen for that GetByOffset. Such design is possible because brand
checks supports polymorphic access very similr to what we have for
GetByOffset sequences.

  • CMakeLists.txt:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Sources.txt:
  • builtins/BuiltinExecutables.cpp:

(JSC::BuiltinExecutables::createDefaultConstructor):
(JSC::BuiltinExecutables::createExecutable):

  • builtins/BuiltinExecutables.h:

We are adding a new parameter PrivateBrandRequirement to propagate
when a default constructor needs to emit code to setup private brand
on instances.

  • builtins/BuiltinNames.h:

Adding @privateBrand that we use to store private brand on
class's scope.

  • bytecode/AccessCase.cpp:

(JSC::AccessCase::createCheckPrivateBrand):
(JSC::AccessCase::createSetPrivateBrand):
(JSC::AccessCase::requiresIdentifierNameMatch const):
(JSC::AccessCase::requiresInt32PropertyCheck const):
(JSC::AccessCase::needsScratchFPR const):
(JSC::AccessCase::forEachDependentCell const):
(JSC::AccessCase::doesCalls const):
(JSC::AccessCase::canReplace const):
(JSC::AccessCase::dump const):
(JSC::AccessCase::generateWithGuard):
(JSC::AccessCase::generateImpl):

  • bytecode/AccessCase.h:

(JSC::AccessCase::structure const):
(JSC::AccessCase::newStructure const):

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

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

  • bytecode/CheckPrivateBrandStatus.cpp: Added.

(JSC::CheckPrivateBrandStatus::appendVariant):
(JSC::CheckPrivateBrandStatus::computeForBaseline):
(JSC::CheckPrivateBrandStatus::CheckPrivateBrandStatus):
(JSC::CheckPrivateBrandStatus::computeForStubInfoWithoutExitSiteFeedback):
(JSC::CheckPrivateBrandStatus::computeFor):
(JSC::CheckPrivateBrandStatus::slowVersion const):
(JSC::CheckPrivateBrandStatus::merge):
(JSC::CheckPrivateBrandStatus::filter):
(JSC::CheckPrivateBrandStatus::singleIdentifier const):
(JSC::CheckPrivateBrandStatus::visitAggregate):
(JSC::CheckPrivateBrandStatus::markIfCheap):
(JSC::CheckPrivateBrandStatus::finalize):
(JSC::CheckPrivateBrandStatus::dump const):

  • bytecode/CheckPrivateBrandStatus.h: Added.
  • bytecode/CheckPrivateBrandVariant.cpp: Added.

(JSC::CheckPrivateBrandVariant::CheckPrivateBrandVariant):
(JSC::CheckPrivateBrandVariant::~CheckPrivateBrandVariant):
(JSC::CheckPrivateBrandVariant::attemptToMerge):
(JSC::CheckPrivateBrandVariant::markIfCheap):
(JSC::CheckPrivateBrandVariant::finalize):
(JSC::CheckPrivateBrandVariant::visitAggregate):
(JSC::CheckPrivateBrandVariant::dump const):
(JSC::CheckPrivateBrandVariant::dumpInContext const):

  • bytecode/CheckPrivateBrandVariant.h: Added.

(JSC::CheckPrivateBrandVariant::structureSet const):
(JSC::CheckPrivateBrandVariant::structureSet):
(JSC::CheckPrivateBrandVariant::identifier const):
(JSC::CheckPrivateBrandVariant::overlaps):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::finishCreation):
(JSC::CodeBlock::finalizeLLIntInlineCaches):

  • bytecode/ExecutableInfo.h:

(JSC::ExecutableInfo::ExecutableInfo):
(JSC::ExecutableInfo::privateBrandRequirement const):

  • bytecode/PolymorphicAccess.cpp:

(JSC::PolymorphicAccess::regenerate):
(WTF::printInternal):

  • bytecode/RecordedStatuses.cpp:

(JSC::RecordedStatuses::operator=):
(JSC::RecordedStatuses::addCheckPrivateBrandStatus):
(JSC::RecordedStatuses::addSetPrivateBrandStatus):
(JSC::RecordedStatuses::visitAggregate):
(JSC::RecordedStatuses::markIfCheap):

  • bytecode/RecordedStatuses.h:

(JSC::RecordedStatuses::forEachVector):

  • bytecode/SetPrivateBrandStatus.cpp: Added.

(JSC::SetPrivateBrandStatus::appendVariant):
(JSC::SetPrivateBrandStatus::computeForBaseline):
(JSC::SetPrivateBrandStatus::SetPrivateBrandStatus):
(JSC::SetPrivateBrandStatus::computeForStubInfoWithoutExitSiteFeedback):
(JSC::SetPrivateBrandStatus::computeFor):
(JSC::SetPrivateBrandStatus::slowVersion const):
(JSC::SetPrivateBrandStatus::merge):
(JSC::SetPrivateBrandStatus::filter):
(JSC::SetPrivateBrandStatus::singleIdentifier const):
(JSC::SetPrivateBrandStatus::visitAggregate):
(JSC::SetPrivateBrandStatus::markIfCheap):
(JSC::SetPrivateBrandStatus::finalize):
(JSC::SetPrivateBrandStatus::dump const):

  • bytecode/SetPrivateBrandStatus.h: Added.
  • bytecode/SetPrivateBrandVariant.cpp: Added.

(JSC::SetPrivateBrandVariant::SetPrivateBrandVariant):
(JSC::SetPrivateBrandVariant::~SetPrivateBrandVariant):
(JSC::SetPrivateBrandVariant::attemptToMerge):
(JSC::SetPrivateBrandVariant::markIfCheap):
(JSC::SetPrivateBrandVariant::finalize):
(JSC::SetPrivateBrandVariant::visitAggregate):
(JSC::SetPrivateBrandVariant::dump const):
(JSC::SetPrivateBrandVariant::dumpInContext const):

  • bytecode/SetPrivateBrandVariant.h: Added.

(JSC::SetPrivateBrandVariant::oldStructure const):
(JSC::SetPrivateBrandVariant::newStructure const):
(JSC::SetPrivateBrandVariant::identifier const):
(JSC::SetPrivateBrandVariant::overlaps):

  • bytecode/StructureStubInfo.cpp:

(JSC::StructureStubInfo::reset):

  • bytecode/StructureStubInfo.h:
  • bytecode/UnlinkedCodeBlock.cpp:

(JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):

  • bytecode/UnlinkedCodeBlock.h:

(JSC::UnlinkedCodeBlock::privateBrandRequirement const):

  • bytecode/UnlinkedCodeBlockGenerator.h:

(JSC::UnlinkedCodeBlockGenerator::privateBrandRequirement const):

  • bytecode/UnlinkedFunctionExecutable.cpp:

(JSC::generateUnlinkedFunctionCodeBlock):
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):

  • bytecode/UnlinkedFunctionExecutable.h:
  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::BytecodeGenerator):

We changed BytecodeGenerator for FunctionNode and EvalNode to
propagate parentScope PrivateNameEnvironment. These environments stores
private name entries that are visible into the scope of the
function/eval.
This is required to identify the kind of access a private name is
referring to, since it can be a private field or a private method.

(JSC::BytecodeGenerator::instantiateLexicalVariables):
(JSC::BytecodeGenerator::emitGetPrivateName):
(JSC::BytecodeGenerator::emitCreatePrivateBrand):

The process to create a private brand is as follows:

  1. Create a PrivateSymbol using @createPrivateSymbol.
  2. Store this symbol into a given scope (i.e class lexical scope) on @privateBrand variable.

(JSC::BytecodeGenerator::emitInstallPrivateBrand):
(JSC::BytecodeGenerator::emitGetPrivateBrand):

We added m_privateNamesStack to BytecodeGenerator to represent the
scope chain of available private names while generating bytecode.

(JSC::BytecodeGenerator::emitCheckPrivateBrand):
(JSC::BytecodeGenerator::isPrivateMethod):
(JSC::BytecodeGenerator::pushPrivateAccessNames):
(JSC::BytecodeGenerator::popPrivateAccessNames):
(JSC::BytecodeGenerator::getAvailablePrivateAccessNames):
(JSC::BytecodeGenerator::emitNewDefaultConstructor):
(JSC::BytecodeGenerator::emitNewClassFieldInitializerFunction):
(JSC::BytecodeGenerator::emitDirectGetByVal): Deleted.

  • bytecompiler/BytecodeGenerator.h:

(JSC::BytecodeGenerator::privateBrandRequirement const):
(JSC::BytecodeGenerator::generate):
(JSC::BytecodeGenerator::makeFunction):

This change is required to properly propagate PrivateBrandRequirement
to arrow functions that can potentially call super().

  • bytecompiler/NodesCodegen.cpp:

(JSC::PropertyListNode::emitDeclarePrivateFieldNames):
(JSC::PropertyListNode::emitBytecode):
(JSC::PropertyListNode::emitPutConstantProperty):
(JSC::BaseDotNode::emitGetPropertyValue):

Adding support to properly access private method. Since we store
private methods on class lexical scope, we need a different set of
instructions to access a private method.

(JSC::BaseDotNode::emitPutProperty):

In the case of we trying to write in a private method, we need to
throw a TypeError according to specification
(https://tc39.es/proposal-private-methods/#sec-privatefieldset).

(JSC::FunctionCallValueNode::emitBytecode):
(JSC::PostfixNode::emitDot):
(JSC::PrefixNode::emitDot):
(JSC::ClassExprNode::emitBytecode):

  • debugger/DebuggerCallFrame.cpp:

(JSC::DebuggerCallFrame::evaluateWithScopeExtension):

  • dfg/DFGAbstractInterpreterInlines.h:

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

  • dfg/DFGArgumentsEliminationPhase.cpp:
  • dfg/DFGByteCodeParser.cpp:

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

  • dfg/DFGCapabilities.cpp:

(JSC::DFG::capabilityLevel):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGClobbersExitState.cpp:

(JSC::DFG::clobbersExitState):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

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

  • dfg/DFGGraph.h:
  • dfg/DFGJITCompiler.cpp:

(JSC::DFG::JITCompiler::link):

  • dfg/DFGJITCompiler.h:

(JSC::DFG::JITCompiler::addPrivateBrandAccess):

  • dfg/DFGMayExit.cpp:
  • dfg/DFGNode.h:

(JSC::DFG::Node::hasCheckPrivateBrandStatus):
(JSC::DFG::Node::checkPrivateBrandStatus):
(JSC::DFG::Node::hasSetPrivateBrandStatus):
(JSC::DFG::Node::setPrivateBrandStatus):

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

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileCheckPrivateBrand):
(JSC::DFG::SpeculativeJIT::compileSetPrivateBrand):

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

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • dfg/DFGStoreBarrierInsertionPhase.cpp:
  • dfg/DFGVarargsForwardingPhase.cpp:
  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compilePrivateBrandAccess):
(JSC::FTL::DFG::LowerDFGToB3::compileCheckPrivateBrand):
(JSC::FTL::DFG::LowerDFGToB3::compileSetPrivateBrand):

  • interpreter/Interpreter.cpp:

(JSC::eval):

  • jit/JIT.cpp:

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

  • jit/JIT.h:
  • jit/JITInlineCacheGenerator.cpp:

(JSC::JITPrivateBrandAccessGenerator::JITPrivateBrandAccessGenerator):
(JSC::JITPrivateBrandAccessGenerator::generateFastPath):
(JSC::JITPrivateBrandAccessGenerator::finalize):

  • jit/JITInlineCacheGenerator.h:

(JSC::JITPrivateBrandAccessGenerator::JITPrivateBrandAccessGenerator):
(JSC::JITPrivateBrandAccessGenerator::slowPathJump const):

  • jit/JITOperations.cpp:

(JSC::JSC_DEFINE_JIT_OPERATION):
(JSC::getPrivateName):

  • jit/JITOperations.h:
  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emit_op_set_private_brand):
(JSC::JIT::emitSlow_op_set_private_brand):
(JSC::JIT::emit_op_check_private_brand):
(JSC::JIT::emitSlow_op_check_private_brand):

  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::emit_op_set_private_brand):
(JSC::JIT::emitSlow_op_set_private_brand):
(JSC::JIT::emit_op_check_private_brand):
(JSC::JIT::emitSlow_op_check_private_brand):

  • jit/Repatch.cpp:

(JSC::tryCacheCheckPrivateBrand):
(JSC::repatchCheckPrivateBrand):
(JSC::tryCacheSetPrivateBrand):
(JSC::repatchSetPrivateBrand):
(JSC::resetCheckPrivateBrand):
(JSC::resetSetPrivateBrand):

  • jit/Repatch.h:
  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::LLINT_SLOW_PATH_DECL):

  • llint/LLIntSlowPaths.h:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • parser/Nodes.cpp:

(JSC::FunctionMetadataNode::FunctionMetadataNode):

  • parser/Nodes.h:

(JSC::BaseDotNode::isPrivateMember const):
(JSC::BaseDotNode::isPrivateField const): Deleted.

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseClass):
(JSC::Parser<LexerType>::parseMemberExpression):

  • parser/Parser.h:

(JSC::Scope::declarePrivateMethod):
(JSC::Scope::declarePrivateField):
(JSC::Parser<LexerType>::parse):
(JSC::parse):
(JSC::Scope::declarePrivateName): Deleted.

  • parser/ParserModes.h:
  • parser/SyntaxChecker.h:

(JSC::SyntaxChecker::createDotAccess):

  • parser/VariableEnvironment.cpp:

(JSC::VariableEnvironment::declarePrivateMethod):

  • parser/VariableEnvironment.h:

(JSC::VariableEnvironmentEntry::isPrivateField const):
(JSC::VariableEnvironmentEntry::isPrivateMethod const):
(JSC::VariableEnvironmentEntry::setIsPrivateField):
(JSC::VariableEnvironmentEntry::setIsPrivateMethod):
(JSC::PrivateNameEntry::isMethod const):
(JSC::PrivateNameEntry::isPrivateMethodOrAcessor const):
(JSC::VariableEnvironment::addPrivateName):
(JSC::VariableEnvironment::declarePrivateField):
(JSC::VariableEnvironment::declarePrivateMethod):
(JSC::VariableEnvironment::privateNameEnvironment const):
(JSC::VariableEnvironment::hasPrivateMethodOrAccessor const):
(JSC::VariableEnvironment::addPrivateNamesFrom):
(JSC::VariableEnvironmentEntry::isPrivateName const): Deleted.
(JSC::VariableEnvironmentEntry::setIsPrivateName): Deleted.
(JSC::VariableEnvironment::declarePrivateName): Deleted.

  • runtime/CachedTypes.cpp:

(JSC::CachedCodeBlockRareData::encode):
(JSC::CachedCodeBlockRareData::decode const):
(JSC::CachedFunctionExecutableRareData::encode):
(JSC::CachedFunctionExecutableRareData::decode const):
(JSC::CachedFunctionExecutable::privateBrandRequirement const):
(JSC::CachedCodeBlock::derivedContextType const):
(JSC::CachedFunctionExecutable::encode):
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
(JSC::CachedCodeBlock::needsClassFieldInitializer const): Deleted.

  • runtime/CodeCache.cpp:

(JSC::generateUnlinkedCodeBlockImpl):
(JSC::generateUnlinkedCodeBlock):
(JSC::generateUnlinkedCodeBlockForDirectEval):
(JSC::CodeCache::getUnlinkedGlobalFunctionExecutable):

  • runtime/CodeCache.h:
  • runtime/DirectEvalExecutable.cpp:

(JSC::DirectEvalExecutable::create):
(JSC::DirectEvalExecutable::DirectEvalExecutable):

  • runtime/DirectEvalExecutable.h:
  • runtime/EvalExecutable.cpp:

(JSC::EvalExecutable::EvalExecutable):

  • runtime/EvalExecutable.h:

(JSC::EvalExecutable::executableInfo const):
(JSC::EvalExecutable::privateBrandRequirement const):

  • runtime/ExceptionHelpers.cpp:

(JSC::createInvalidPrivateNameError):

  • runtime/IndirectEvalExecutable.cpp:

(JSC::IndirectEvalExecutable::IndirectEvalExecutable):

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

(JSC::JSObject::checkPrivateBrand):
(JSC::JSObject::setPrivateBrand):

  • runtime/JSScope.cpp:

(JSC::JSScope::collectClosureVariablesUnderTDZ):

  • runtime/JSScope.h:
  • runtime/ModuleProgramExecutable.h:
  • runtime/Options.cpp:

(JSC::Options::recomputeDependentOptions):

  • runtime/OptionsList.h:
  • runtime/ProgramExecutable.h:
  • runtime/Structure.cpp:

(JSC::Structure::materializePropertyTable):
(JSC::BrandedStructure::BrandedStructure):
(JSC::BrandedStructure::create):
(JSC::BrandedStructure::checkBrand):
(JSC::Structure::setBrandTransitionFromExistingStructureImpl):
(JSC::Structure::setBrandTransitionFromExistingStructureConcurrently):
(JSC::Structure::setBrandTransition):

  • runtime/Structure.h:

(JSC::Structure::finishCreation):

  • runtime/StructureInlines.h:

(JSC::Structure::create):
(JSC::Structure::forEachPropertyConcurrently):

  • runtime/StructureTransitionTable.h:
  • runtime/SymbolTable.cpp:

(JSC::SymbolTable::cloneScopePart):

  • runtime/SymbolTable.h:
  • runtime/VM.cpp:

(JSC::VM::VM):

  • runtime/VM.h:
Location:
trunk/Source/JavaScriptCore/bytecompiler
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r270874 r272580  
    290290}
    291291
    292 BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, ECMAMode ecmaMode)
     292BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, const PrivateNameEnvironment*, ECMAMode ecmaMode)
    293293    : BytecodeGeneratorBase(makeUnique<UnlinkedCodeBlockGenerator>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters())
    294294    , m_codeGenerationMode(codeGenerationMode)
     
    337337}
    338338
    339 BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, UnlinkedFunctionCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, ECMAMode ecmaMode)
     339BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, UnlinkedFunctionCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, const PrivateNameEnvironment* parentPrivateNameEnvironment, ECMAMode ecmaMode)
    340340    : BytecodeGeneratorBase(makeUnique<UnlinkedCodeBlockGenerator>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters())
    341341    , m_codeGenerationMode(codeGenerationMode)
     
    360360    , m_derivedContextType(codeBlock->derivedContextType())
    361361{
     362    pushPrivateAccessNames(parentPrivateNameEnvironment);
     363
    362364    SymbolTable* functionSymbolTable = SymbolTable::create(m_vm);
    363365    functionSymbolTable->setUsesNonStrictEval(m_usesNonStrictEval);
     
    708710                case ConstructorKind::Base:
    709711                    emitCreateThis(&m_thisRegister);
     712                    if (Options::usePrivateMethods() && privateBrandRequirement() == PrivateBrandRequirement::Needed)
     713                        emitInstallPrivateBrand(&m_thisRegister);
     714
    710715                    emitInstanceFieldInitializationIfNeeded(&m_thisRegister, &m_calleeRegister, m_scopeNode->position(), m_scopeNode->position(), m_scopeNode->position());
    711716                    break;
     
    839844}
    840845
    841 BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, ECMAMode ecmaMode)
     846BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, const PrivateNameEnvironment* parentPrivateNameEnvironment, ECMAMode ecmaMode)
    842847    : BytecodeGeneratorBase(makeUnique<UnlinkedCodeBlockGenerator>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters())
    843848    , m_codeGenerationMode(codeGenerationMode)
     
    857862    m_codeBlock->setNumParameters(1);
    858863
     864    pushPrivateAccessNames(parentPrivateNameEnvironment);
     865
    859866    m_cachedParentTDZ = parentScopeTDZVariables;
    860867
     
    902909}
    903910
    904 BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNode, UnlinkedModuleProgramCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, ECMAMode ecmaMode)
     911BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNode, UnlinkedModuleProgramCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, const PrivateNameEnvironment*, ECMAMode ecmaMode)
    905912    : BytecodeGeneratorBase(makeUnique<UnlinkedCodeBlockGenerator>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters())
    906913    , m_codeGenerationMode(codeGenerationMode)
     
    18941901            // FIXME: only do this if there is an eval() within a nested scope --- otherwise it isn't needed.
    18951902            // https://bugs.webkit.org/show_bug.cgi?id=206663
    1896             if (entry.value.isPrivateName())
    1897                 symbolTable->addPrivateName(entry.key.get());
     1903            if (entry.value.isPrivateField())
     1904                symbolTable->addPrivateName(entry.key.get(), PrivateNameEntry(PrivateNameEntry::Traits::IsDeclared));
     1905            else if (entry.value.isPrivateMethod())
     1906                symbolTable->addPrivateName(entry.key.get(), PrivateNameEntry(PrivateNameEntry::Traits::IsDeclared | PrivateNameEntry::Traits::IsMethod));
    18981907        }
    18991908    }
     
    27152724}
    27162725
    2717 RegisterID* BytecodeGenerator::emitDirectGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
     2726RegisterID* BytecodeGenerator::emitGetPrivateName(RegisterID* dst, RegisterID* base, RegisterID* property)
    27182727{
    27192728    OpGetPrivateName::emit(this, dst, base, property);
     
    27512760}
    27522761
     2762void BytecodeGenerator::emitCreatePrivateBrand(RegisterID* scope, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
     2763{
     2764    RefPtr<RegisterID> createPrivateSymbol = moveLinkTimeConstant(nullptr, LinkTimeConstant::createPrivateSymbol);
     2765
     2766    CallArguments arguments(*this, nullptr, 0);
     2767    emitLoad(arguments.thisRegister(), jsUndefined());
     2768    RegisterID* newSymbol = emitCall(finalDestination(nullptr, createPrivateSymbol.get()), createPrivateSymbol.get(), NoExpectedFunction, arguments, divot, divotStart, divotEnd, DebuggableCall::No);
     2769
     2770    Variable privateBrandVar = variable(propertyNames().builtinNames().privateBrandPrivateName());
     2771
     2772    emitPutToScope(scope, privateBrandVar, newSymbol, DoNotThrowIfNotFound, InitializationMode::Initialization);
     2773}
     2774
     2775void BytecodeGenerator::emitInstallPrivateBrand(RegisterID* target)
     2776{
     2777    Variable privateBrandVar = variable(propertyNames().builtinNames().privateBrandPrivateName());
     2778    RefPtr<RegisterID> privateBrandVarScope = emitResolveScope(nullptr, privateBrandVar);
     2779    RegisterID* privateBrandSymbol = emitGetPrivateBrand(newTemporary(), privateBrandVarScope.get());
     2780    OpSetPrivateBrand::emit(this, target, privateBrandSymbol);
     2781}
     2782
     2783RegisterID* BytecodeGenerator::emitGetPrivateBrand(RegisterID* dst, RegisterID* scope)
     2784{
     2785    Variable privateBrandVar = variable(propertyNames().builtinNames().privateBrandPrivateName());
     2786    return emitGetFromScope(dst, scope, privateBrandVar, ThrowIfNotFound);
     2787}
     2788
    27532789RegisterID* BytecodeGenerator::emitPrivateFieldPut(RegisterID* base, RegisterID* property, RegisterID* value)
    27542790{
    27552791    OpPutPrivateName::emit(this, base, property, value, PrivateFieldPutKind::set());
    27562792    return value;
     2793}
     2794
     2795void BytecodeGenerator::emitCheckPrivateBrand(RegisterID* base, RegisterID* brandSymbol)
     2796{
     2797    OpCheckPrivateBrand::emit(this, base, brandSymbol);
    27572798}
    27582799
     
    28892930        }
    28902931    }
     2932}
     2933
     2934bool BytecodeGenerator::isPrivateMethod(const Identifier& ident)
     2935{
     2936    for (unsigned i = m_privateNamesStack.size(); i--; ) {
     2937        auto& map = m_privateNamesStack[i];
     2938        auto it = map.find(ident.impl());
     2939        if (it != map.end())
     2940            return it->value.isMethod();
     2941    }
     2942
     2943    return false;
     2944}
     2945
     2946void BytecodeGenerator::pushPrivateAccessNames(const PrivateNameEnvironment* environment)
     2947{
     2948    if (!environment || !environment->size())
     2949        return;
     2950
     2951    m_privateNamesStack.append(*environment);
     2952}
     2953
     2954void BytecodeGenerator::popPrivateAccessNames()
     2955{
     2956    ASSERT(m_privateNamesStack.size());
     2957    m_privateNamesStack.removeLast();
    28912958}
    28922959
     
    29102977
    29112978    m_TDZStack.append(TDZStackEntry { WTFMove(map), nullptr });
     2979}
     2980
     2981Optional<PrivateNameEnvironment> BytecodeGenerator::getAvailablePrivateAccessNames()
     2982{
     2983    PrivateNameEnvironment result;
     2984    SmallPtrSet<UniquedStringImpl*, 16> excludedNames;
     2985    for (unsigned i = m_privateNamesStack.size(); i--; ) {
     2986        auto& map = m_privateNamesStack[i];
     2987        for (auto& entry : map)  {
     2988            if (entry.value.isPrivateMethodOrAcessor()) {
     2989                if (!excludedNames.contains(entry.key.get())) {
     2990                    result.add(entry.key, entry.value);
     2991                    excludedNames.add(entry.key.get());
     2992                }
     2993            } else
     2994                excludedNames.add(entry.key.get());
     2995        }
     2996    }
     2997
     2998    if (!result.size())
     2999        return WTF::nullopt;
     3000    return result;
    29123001}
    29133002
     
    31213210
    31223211RegisterID* BytecodeGenerator::emitNewDefaultConstructor(RegisterID* dst, ConstructorKind constructorKind, const Identifier& name,
    3123     const Identifier& ecmaName, const SourceCode& classSource, NeedsClassFieldInitializer needsClassFieldInitializer)
    3124 {
    3125     UnlinkedFunctionExecutable* executable = m_vm.builtinExecutables()->createDefaultConstructor(constructorKind, name, needsClassFieldInitializer);
     3212    const Identifier& ecmaName, const SourceCode& classSource, NeedsClassFieldInitializer needsClassFieldInitializer, PrivateBrandRequirement privateBrandRequirement)
     3213{
     3214    UnlinkedFunctionExecutable* executable = m_vm.builtinExecutables()->createDefaultConstructor(constructorKind, name, needsClassFieldInitializer, privateBrandRequirement);
    31263215    executable->setInvalidTypeProfilingOffsets();
    31273216    executable->setEcmaName(ecmaName);
     
    31473236
    31483237    auto variablesUnderTDZ = getVariablesUnderTDZ();
     3238    Optional<PrivateNameEnvironment> parentPrivateNameEnvironment = getAvailablePrivateAccessNames();
    31493239    SourceParseMode parseMode = SourceParseMode::ClassFieldInitializerMode;
    31503240    ConstructAbility constructAbility = ConstructAbility::CannotConstruct;
     
    31533243    FunctionMetadataNode metadata(parserArena(), JSTokenLocation(), JSTokenLocation(), 0, 0, 0, 0, 0, alwaysStrictInClass, ConstructorKind::None, superBinding, 0, parseMode, false);
    31543244    metadata.finishParsing(m_scopeNode->source(), Identifier(), FunctionMode::MethodDefinition);
    3155     auto initializer = UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), &metadata, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, scriptMode(), WTFMove(variablesUnderTDZ), newDerivedContextType, NeedsClassFieldInitializer::No);
     3245    auto initializer = UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), &metadata, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, scriptMode(), WTFMove(variablesUnderTDZ), WTFMove(parentPrivateNameEnvironment), newDerivedContextType, NeedsClassFieldInitializer::No, PrivateBrandRequirement::None);
    31563246    initializer->setClassFieldLocations(WTFMove(classFieldLocations));
    31573247
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r270874 r272580  
    409409        typedef DeclarationStacks::FunctionStack FunctionStack;
    410410
    411         BytecodeGenerator(VM&, ProgramNode*, UnlinkedProgramCodeBlock*, OptionSet<CodeGenerationMode>, const RefPtr<TDZEnvironmentLink>&, ECMAMode);
    412         BytecodeGenerator(VM&, FunctionNode*, UnlinkedFunctionCodeBlock*, OptionSet<CodeGenerationMode>, const RefPtr<TDZEnvironmentLink>&, ECMAMode);
    413         BytecodeGenerator(VM&, EvalNode*, UnlinkedEvalCodeBlock*, OptionSet<CodeGenerationMode>, const RefPtr<TDZEnvironmentLink>&, ECMAMode);
    414         BytecodeGenerator(VM&, ModuleProgramNode*, UnlinkedModuleProgramCodeBlock*, OptionSet<CodeGenerationMode>, const RefPtr<TDZEnvironmentLink>&, ECMAMode);
     411        BytecodeGenerator(VM&, ProgramNode*, UnlinkedProgramCodeBlock*, OptionSet<CodeGenerationMode>, const RefPtr<TDZEnvironmentLink>&, const PrivateNameEnvironment*, ECMAMode);
     412        BytecodeGenerator(VM&, FunctionNode*, UnlinkedFunctionCodeBlock*, OptionSet<CodeGenerationMode>, const RefPtr<TDZEnvironmentLink>&, const PrivateNameEnvironment*, ECMAMode);
     413        BytecodeGenerator(VM&, EvalNode*, UnlinkedEvalCodeBlock*, OptionSet<CodeGenerationMode>, const RefPtr<TDZEnvironmentLink>&, const PrivateNameEnvironment*, ECMAMode);
     414        BytecodeGenerator(VM&, ModuleProgramNode*, UnlinkedModuleProgramCodeBlock*, OptionSet<CodeGenerationMode>, const RefPtr<TDZEnvironmentLink>&, const PrivateNameEnvironment*, ECMAMode);
    415415
    416416        ~BytecodeGenerator();
     
    426426        bool usesEval() const { return m_scopeNode->usesEval(); }
    427427        bool usesThis() const { return m_scopeNode->usesThis(); }
     428        PrivateBrandRequirement privateBrandRequirement() const { return m_codeBlock->privateBrandRequirement(); }
    428429        ConstructorKind constructorKind() const { return m_codeBlock->constructorKind(); }
    429430        SuperBinding superBinding() const { return m_codeBlock->superBinding(); }
     
    432433
    433434        template<typename Node, typename UnlinkedCodeBlock>
    434         static ParserError generate(VM& vm, Node* node, const SourceCode& sourceCode, UnlinkedCodeBlock* unlinkedCodeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, ECMAMode ecmaMode)
     435        static ParserError generate(VM& vm, Node* node, const SourceCode& sourceCode, UnlinkedCodeBlock* unlinkedCodeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, const PrivateNameEnvironment* privateNameEnvironment, ECMAMode ecmaMode)
    435436        {
    436437            MonotonicTime before;
     
    439440
    440441            DeferGC deferGC(vm.heap);
    441             auto bytecodeGenerator = makeUnique<BytecodeGenerator>(vm, node, unlinkedCodeBlock, codeGenerationMode, parentScopeTDZVariables, ecmaMode);
     442            auto bytecodeGenerator = makeUnique<BytecodeGenerator>(vm, node, unlinkedCodeBlock, codeGenerationMode, parentScopeTDZVariables, privateNameEnvironment, ecmaMode);
    442443            auto result = bytecodeGenerator->generate();
    443444
     
    775776        RegisterID* emitNewFunction(RegisterID* dst, FunctionMetadataNode*);
    776777        RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode*);
    777         RegisterID* emitNewDefaultConstructor(RegisterID* dst, ConstructorKind, const Identifier& name, const Identifier& ecmaName, const SourceCode& classSource, NeedsClassFieldInitializer);
     778        RegisterID* emitNewDefaultConstructor(RegisterID* dst, ConstructorKind, const Identifier& name, const Identifier& ecmaName, const SourceCode& classSource, NeedsClassFieldInitializer, PrivateBrandRequirement);
    778779        RegisterID* emitNewClassFieldInitializerFunction(RegisterID* dst, Vector<JSTextPosition>&& classFieldLocations, bool isDerived);
    779780        RegisterID* emitNewArrowFunctionExpression(RegisterID*, ArrowFuncExprNode*);
     
    816817        RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
    817818        RegisterID* emitPutByVal(RegisterID* base, RegisterID* thisValue, RegisterID* property, RegisterID* value);
    818         RegisterID* emitDirectGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
    819819        RegisterID* emitDirectPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
    820820        RegisterID* emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
     
    824824        RegisterID* emitDefinePrivateField(RegisterID* base, RegisterID* property, RegisterID* value);
    825825        RegisterID* emitPrivateFieldPut(RegisterID* base, RegisterID* property, RegisterID* value);
     826        RegisterID* emitGetPrivateName(RegisterID* dst, RegisterID* base, RegisterID* property);
     827
     828        void emitCreatePrivateBrand(RegisterID* dst, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
     829        void emitInstallPrivateBrand(RegisterID* target);
     830        RegisterID* emitGetPrivateBrand(RegisterID* dst, RegisterID* scope);
     831        void emitCheckPrivateBrand(RegisterID* base, RegisterID* brand);
    826832
    827833        void emitSuperSamplerBegin();
     
    11771183
    11781184            NeedsClassFieldInitializer needsClassFieldInitializer = metadata->isConstructorAndNeedsClassFieldInitializer() ? NeedsClassFieldInitializer::Yes : NeedsClassFieldInitializer::No;
     1185            PrivateBrandRequirement privateBrandRequirement = metadata->privateBrandRequirement();
    11791186            if (SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode, SourceParseMode::AsyncArrowFunctionBodyMode).contains(metadata->parseMode())) {
    11801187                if (constructorKind() == ConstructorKind::Extends || isDerivedConstructorContext()) {
    11811188                    newDerivedContextType = DerivedContextType::DerivedConstructorContext;
    11821189                    needsClassFieldInitializer = m_codeBlock->needsClassFieldInitializer();
     1190                    privateBrandRequirement = m_codeBlock->privateBrandRequirement();
    11831191                }
    11841192                else if (m_codeBlock->isClassContext() || isDerivedClassContext())
     
    11871195
    11881196            auto optionalVariablesUnderTDZ = getVariablesUnderTDZ();
     1197            Optional<PrivateNameEnvironment> parentPrivateNameEnvironment = getAvailablePrivateAccessNames();
    11891198
    11901199            // FIXME: These flags, ParserModes and propagation to XXXCodeBlocks should be reorganized.
     
    11951204                constructAbility = ConstructAbility::CanConstruct;
    11961205
    1197             return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), metadata, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, scriptMode(), WTFMove(optionalVariablesUnderTDZ), newDerivedContextType, needsClassFieldInitializer);
     1206            return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), metadata, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, scriptMode(), WTFMove(optionalVariablesUnderTDZ), WTFMove(parentPrivateNameEnvironment), newDerivedContextType, needsClassFieldInitializer, privateBrandRequirement);
    11981207        }
    11991208
    12001209        RefPtr<TDZEnvironmentLink> getVariablesUnderTDZ();
     1210        Optional<PrivateNameEnvironment> getAvailablePrivateAccessNames();
    12011211
    12021212        RegisterID* emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall);
     
    12541264        }
    12551265
     1266        bool isPrivateMethod(const Identifier&);
     1267
     1268        void pushPrivateAccessNames(const PrivateNameEnvironment*);
     1269        void popPrivateAccessNames();
     1270
    12561271    private:
    12571272        OptionSet<CodeGenerationMode> m_codeGenerationMode;
     
    12671282        RefPtr<TDZEnvironmentLink> m_cachedParentTDZ;
    12681283        Vector<TDZStackEntry> m_TDZStack;
     1284        Vector<PrivateNameEnvironment> m_privateNamesStack;
    12691285        Optional<size_t> m_varScopeLexicalScopeStackIndex;
    12701286        void pushTDZVariables(const VariableEnvironment&, TDZCheckOptimization, TDZRequirement);
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r272243 r272580  
    564564    for (PropertyListNode* p = this; p; p = p->m_next) {
    565565        const PropertyNode& node = *p->m_node;
    566         if (node.type() & PropertyNode::Private) {
     566        if (node.type() & PropertyNode::PrivateField) {
    567567            if (!createPrivateSymbol)
    568568                createPrivateSymbol = generator.moveLinkTimeConstant(nullptr, LinkTimeConstant::createPrivateSymbol);
     
    590590            emitSaveComputedFieldName(generator, *p->m_node);
    591591
    592         if (p->isInstanceClassField()) {
     592        if (p->isInstanceClassField() && !(p->m_node->type() & PropertyNode::PrivateMethod)) {
    593593            ASSERT(instanceFieldLocations);
    594594            instanceFieldLocations->append(p->position());
     
    758758{
    759759    // Private fields are handled in a synthetic classFieldInitializer function, not here.
    760     ASSERT(!(node.type() & PropertyNode::Private));
     760    ASSERT(!(node.type() & PropertyNode::PrivateField));
    761761
    762762    if (PropertyNode::isUnderscoreProtoSetter(generator.vm(), node)) {
     
    783783    if (node.isClassProperty()) {
    784784        ASSERT(node.needsSuperBinding());
     785
     786        if (node.type() & PropertyNode::PrivateMethod) {
     787            Variable var = generator.variable(*node.name());
     788            generator.emitPutToScope(generator.scopeRegister(), var, value.get(), DoNotThrowIfNotFound, InitializationMode::ConstInitialization);
     789            return;
     790        }
     791
     792        RefPtr<RegisterID> propertyNameRegister;
    785793        if (node.name())
    786794            propertyName = generator.emitLoad(nullptr, *node.name());
     
    911919RegisterID* BaseDotNode::emitGetPropertyValue(BytecodeGenerator& generator, RegisterID* dst, RegisterID* base, RefPtr<RegisterID>& thisValue)
    912920{
    913     if (isPrivateField()) {
     921    if (isPrivateMember()) {
     922        if (generator.isPrivateMethod(identifier())) {
     923            Variable var = generator.variable(identifier());
     924            RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
     925
     926            RegisterID* privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
     927            generator.emitCheckPrivateBrand(base, privateBrandSymbol);
     928
     929            return generator.emitGetFromScope(dst, scope.get(), var, ThrowIfNotFound);
     930        }
     931
    914932        Variable var = generator.variable(m_ident);
    915933        ASSERT_WITH_MESSAGE(!var.local(), "Private Field names must be stored in captured variables");
     
    918936        RefPtr<RegisterID> privateName = generator.newTemporary();
    919937        generator.emitGetFromScope(privateName.get(), scope.get(), var, DoNotThrowIfNotFound);
    920         return generator.emitDirectGetByVal(dst, base, privateName.get());
     938        return generator.emitGetPrivateName(dst, base, privateName.get());
    921939    }
    922940
     
    938956RegisterID* BaseDotNode::emitPutProperty(BytecodeGenerator& generator, RegisterID* base, RegisterID* value, RefPtr<RegisterID>& thisValue)
    939957{
    940     if (isPrivateField()) {
     958    if (isPrivateMember()) {
     959        auto identifierName = identifier();
     960        if (generator.isPrivateMethod(identifierName)) {
     961            Variable var = generator.variable(identifierName);
     962            RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
     963
     964            RegisterID* privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
     965            generator.emitCheckPrivateBrand(base, privateBrandSymbol);
     966
     967            generator.emitThrowTypeError("Trying to access a not defined private setter");
     968        }
     969
    941970        Variable var = generator.variable(m_ident);
    942971        ASSERT_WITH_MESSAGE(!var.local(), "Private Field names must be stored in captured variables");
     
    10961125
    10971126        // Initialize instance fields after super-call.
     1127        if (Options::usePrivateMethods() && generator.privateBrandRequirement() == PrivateBrandRequirement::Needed)
     1128            generator.emitInstallPrivateBrand(generator.thisRegister());
     1129
    10981130        if (generator.needsClassFieldInitializer() == NeedsClassFieldInitializer::Yes) {
    10991131            ASSERT(generator.isConstructor() || generator.isDerivedConstructorContext());
     
    11011133            generator.emitInstanceFieldInitializationIfNeeded(generator.thisRegister(), func.get(), divot(), divotStart(), divotEnd());
    11021134        }
    1103 
    11041135        return ret;
    11051136    }
     
    22552286    generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
    22562287
    2257     if (dotAccessor->isPrivateField()) {
     2288    if (dotAccessor->isPrivateMember()) {
    22582289        ASSERT(!baseIsSuper);
    22592290        Variable var = generator.variable(ident);
     
    22622293        generator.emitGetFromScope(privateName.get(), scope.get(), var, DoNotThrowIfNotFound);
    22632294
    2264         RefPtr<RegisterID> value = generator.emitDirectGetByVal(generator.newTemporary(), base.get(), privateName.get());
     2295        RefPtr<RegisterID> value = generator.emitGetPrivateName(generator.newTemporary(), base.get(), privateName.get());
    22652296        RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
    22662297        generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     
    24942525    generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
    24952526    RegisterID* value;
    2496     if (dotAccessor->isPrivateField()) {
     2527    if (dotAccessor->isPrivateMember()) {
    24972528        ASSERT(!baseNode->isSuperNode());
    24982529        Variable var = generator.variable(ident);
     
    25012532        generator.emitGetFromScope(privateName.get(), scope.get(), var, DoNotThrowIfNotFound);
    25022533
    2503         value = generator.emitDirectGetByVal(propDst.get(), base.get(), privateName.get());
     2534        value = generator.emitGetPrivateName(propDst.get(), base.get(), privateName.get());
    25042535        emitIncOrDec(generator, value, m_operator);
    25052536        generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     
    49164947        generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested);
    49174948
     4949    bool hasPrivateNames = !!m_lexicalVariables.privateNamesSize();
     4950    bool shouldEmitPrivateBrand = m_lexicalVariables.hasPrivateMethodOrAccessor();
     4951    if (hasPrivateNames)
     4952        generator.pushPrivateAccessNames(m_lexicalVariables.privateNameEnvironment());
     4953    if (shouldEmitPrivateBrand)
     4954        generator.emitCreatePrivateBrand(generator.scopeRegister(), m_position, m_position, m_position);
     4955
    49184956    RefPtr<RegisterID> superclass;
    49194957    if (m_classHeritage) {
     
    49264964
    49274965    auto needsClassFieldInitializer = this->hasInstanceFields() ? NeedsClassFieldInitializer::Yes : NeedsClassFieldInitializer::No;
    4928 
     4966    auto privateBrandRequirement = shouldEmitPrivateBrand ? PrivateBrandRequirement::Needed : PrivateBrandRequirement::None;
    49294967    if (m_constructorExpression) {
    49304968        ASSERT(m_constructorExpression->isFuncExprNode());
     
    49334971        metadata->setClassSource(m_classSource);
    49344972        metadata->setNeedsClassFieldInitializer(needsClassFieldInitializer == NeedsClassFieldInitializer::Yes);
     4973        metadata->setPrivateBrandRequirement(privateBrandRequirement);
    49354974        constructor = generator.emitNode(constructor.get(), m_constructorExpression);
    49364975        needsHomeObject = m_classHeritage || metadata->superBinding() == SuperBinding::Needed;
    49374976    } else
    4938         constructor = generator.emitNewDefaultConstructor(constructor.get(), m_classHeritage ? ConstructorKind::Extends : ConstructorKind::Base, m_name, ecmaName(), m_classSource, needsClassFieldInitializer);
     4977        constructor = generator.emitNewDefaultConstructor(constructor.get(), m_classHeritage ? ConstructorKind::Extends : ConstructorKind::Base, m_name, ecmaName(), m_classSource, needsClassFieldInitializer, privateBrandRequirement);
    49394978
    49404979    const auto& propertyNames = generator.propertyNames();
     
    50145053    if (m_needsLexicalScope)
    50155054        generator.popLexicalScope(this);
     5055
     5056    if (hasPrivateNames)
     5057        generator.popPrivateAccessNames();
    50165058
    50175059    return generator.move(generator.finalDestination(dst, constructor.get()), constructor.get());
Note: See TracChangeset for help on using the changeset viewer.