use of com.github.anba.es6draft.ast.Declaration in project es6draft by anba.
the class BlockDeclarationInstantiationGenerator method generateMethod.
/**
* stack: [] {@literal ->} []
*
* @param node
* the block statement
* @param cx
* the execution context
* @param env
* the lexical environment
* @param mv
* the instruction visitor
*/
void generateMethod(BlockStatement node, Variable<ExecutionContext> cx, Variable<LexicalEnvironment<DeclarativeEnvironmentRecord>> env, InstructionVisitor mv) {
List<Declaration> declarations = LexicallyScopedDeclarations(node);
if (declarations.size() <= METHOD_LIMIT) {
generate(declarations, cx, env, mv);
} else {
for (int i = 0, size = declarations.size(); i < size; i += METHOD_LIMIT) {
List<Declaration> sublist = declarations.subList(i, Math.min(i + METHOD_LIMIT, size));
MethodName method = codegen.compile(node, sublist, this);
mv.load(env);
mv.load(cx);
mv.invoke(method);
}
}
}
use of com.github.anba.es6draft.ast.Declaration in project es6draft by anba.
the class BlockDeclarationInstantiationGenerator method generateMethod.
/**
* stack: [] {@literal ->} []
*
* @param node
* the switch statement
* @param cx
* the execution context
* @param env
* the lexical environment
* @param mv
* the instruction visitor
*/
void generateMethod(SwitchStatement node, Variable<ExecutionContext> cx, Variable<LexicalEnvironment<DeclarativeEnvironmentRecord>> env, InstructionVisitor mv) {
List<Declaration> declarations = LexicallyScopedDeclarations(node);
if (declarations.size() <= METHOD_LIMIT) {
generate(declarations, cx, env, mv);
} else {
for (int i = 0, size = declarations.size(); i < size; i += METHOD_LIMIT) {
List<Declaration> sublist = declarations.subList(i, Math.min(i + METHOD_LIMIT, size));
MethodName method = codegen.compile(node, sublist, this);
mv.load(env);
mv.load(cx);
mv.invoke(method);
}
}
}
use of com.github.anba.es6draft.ast.Declaration in project es6draft by anba.
the class FunctionDeclarationInstantiationGenerator method generate.
private void generate(FunctionNode function, FunctionDeclInitVisitor mv) {
Variable<ExecutionContext> context = mv.getExecutionContext();
Variable<LexicalEnvironment<FunctionEnvironmentRecord>> env = mv.newVariable("env", LexicalEnvironment.class).uncheckedCast();
Variable<FunctionEnvironmentRecord> envRec = mv.newVariable("envRec", FunctionEnvironmentRecord.class);
Variable<FunctionObject> fo = null;
Variable<Undefined> undefined = mv.newVariable("undef", Undefined.class);
mv.loadUndefined();
mv.store(undefined);
FunctionScope fscope = function.getScope();
boolean hasParameters = !function.getParameters().getFormals().isEmpty();
Variable<Iterator<?>> iterator = null;
if (hasParameters) {
iterator = mv.newVariable("iterator", Iterator.class).uncheckedCast();
mv.load(mv.getArguments());
mv.invoke(Methods.Arrays_asList);
mv.invoke(Methods.List_iterator);
mv.store(iterator);
}
/* step 1 (omitted) */
/* step 2 */
getLexicalEnvironment(context, env, mv);
/* step 3 */
getEnvironmentRecord(env, envRec, mv);
/* step 4 */
// RuntimeInfo.Function code = func.getCode();
/* step 5 */
boolean strict = IsStrict(function);
/* step 6 */
FormalParameterList formals = function.getParameters();
/* step 7 */
ArrayList<Name> parameterNames = new ArrayList<>(BoundNames(formals));
HashSet<Name> parameterNamesSet = new HashSet<>(parameterNames);
/* step 8 */
boolean hasDuplicates = parameterNames.size() != parameterNamesSet.size();
/* step 9 */
boolean simpleParameterList = IsSimpleParameterList(formals);
/* step 10 */
boolean hasParameterExpressions = ContainsExpression(formals);
// invariant: hasDuplicates => simpleParameterList
assert !hasDuplicates || simpleParameterList;
// invariant: hasParameterExpressions => !simpleParameterList
assert !hasParameterExpressions || !simpleParameterList;
/* step 11 */
Set<Name> varNames = VarDeclaredNames(function);
/* step 12 */
List<StatementListItem> varDeclarations = VarScopedDeclarations(function);
/* step 13 */
Set<Name> lexicalNames = LexicallyDeclaredNames(function);
/* step 14 */
HashSet<Name> functionNames = new HashSet<>();
/* step 15 */
ArrayDeque<HoistableDeclaration> functionsToInitialize = new ArrayDeque<>();
/* step 16 */
for (StatementListItem item : reverse(varDeclarations)) {
if (item instanceof HoistableDeclaration) {
HoistableDeclaration d = (HoistableDeclaration) item;
Name fn = BoundName(d);
if (functionNames.add(fn)) {
functionsToInitialize.addFirst(d);
}
}
}
if (!functionsToInitialize.isEmpty()) {
fo = mv.newVariable("fo", FunctionObject.class);
}
/* step 17 */
// Optimization: Skip 'arguments' allocation if it's not referenced within the function.
boolean argumentsObjectNeeded = function.getScope().needsArguments();
Name arguments = function.getScope().arguments();
argumentsObjectNeeded &= arguments != null;
/* step 18 */
if (function.getThisMode() == FunctionNode.ThisMode.Lexical) {
argumentsObjectNeeded = false;
} else /* step 19 */
if (parameterNamesSet.contains(arguments)) {
argumentsObjectNeeded = false;
} else /* step 20 */
if (!hasParameterExpressions) {
if (functionNames.contains(arguments) || lexicalNames.contains(arguments)) {
argumentsObjectNeeded = false;
}
}
Variable<? extends LexicalEnvironment<? extends DeclarativeEnvironmentRecord>> paramsEnv;
Variable<? extends DeclarativeEnvironmentRecord> paramsEnvRec;
if (codegen.isEnabled(CompatibilityOption.SingleParameterEnvironment)) {
assert hasParameterExpressions || fscope.parameterVarNames().isEmpty();
if (hasParameterExpressions) {
// Var-scoped bindings from do-expressions in parameter expressions.
for (Name varName : fscope.parameterVarNames()) {
BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(envRec, varName);
op.createMutableBinding(envRec, varName, false, mv);
op.initializeBinding(envRec, varName, undefined, mv);
}
boolean hasParameterBindings = !parameterNames.isEmpty();
assert fscope.parametersScope().isPresent() == (hasParameterBindings || argumentsObjectNeeded);
if (hasParameterBindings || argumentsObjectNeeded) {
paramsEnv = newDeclarativeEnvironment("paramsEnv", env, mv);
paramsEnvRec = getDeclarativeEnvironmentRecord("paramsEnvRec", paramsEnv, mv);
setLexicalEnvironment(paramsEnv, mv);
} else {
// Optimization: Skip environment allocation if no parameters are present.
paramsEnv = env;
paramsEnvRec = envRec;
}
} else {
paramsEnv = env;
paramsEnvRec = envRec;
}
} else {
paramsEnv = env;
paramsEnvRec = envRec;
}
if (fscope.parametersScope() != fscope) {
mv.enterScope(fscope.parametersScope());
}
/* step 21 */
for (Name paramName : function.getScope().parameterNames()) {
BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(paramsEnvRec, paramName);
op.createMutableBinding(paramsEnvRec, paramName, false, mv);
if (hasDuplicates) {
op.initializeBinding(paramsEnvRec, paramName, undefined, mv);
}
}
/* steps 22-23 */
ArrayList<Name> parameterBindings;
HashSet<Name> parameterBindingsSet;
if (argumentsObjectNeeded) {
/* step 22 */
assert arguments != null;
Variable<ArgumentsObject> argumentsObj = mv.newVariable("argumentsObj", ArgumentsObject.class);
if (strict || !simpleParameterList) {
CreateUnmappedArgumentsObject(mv);
} else if (formals.getFormals().isEmpty()) {
CreateMappedArgumentsObject(mv);
} else {
CreateMappedArgumentsObject(paramsEnvRec, formals, mv);
}
mv.store(argumentsObj);
BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(paramsEnvRec, arguments);
if (strict) {
op.createImmutableBinding(paramsEnvRec, arguments, false, mv);
} else {
op.createMutableBinding(paramsEnvRec, arguments, false, mv);
}
op.initializeBinding(paramsEnvRec, arguments, argumentsObj, mv);
parameterBindings = new ArrayList<>(parameterNames);
parameterBindings.add(arguments);
parameterBindingsSet = new HashSet<>(parameterBindings);
} else {
/* step 23 */
parameterBindings = parameterNames;
parameterBindingsSet = parameterNamesSet;
}
/* steps 24-26 */
if (hasParameters) {
if (hasDuplicates) {
/* step 24 */
BindingInitialization(codegen, function, env, iterator, mv);
} else {
/* step 25 */
BindingInitialization(codegen, function, env, paramsEnvRec, iterator, mv);
}
}
/* steps 27-28 */
HashSet<Name> instantiatedVarNames;
Variable<? extends LexicalEnvironment<? extends DeclarativeEnvironmentRecord>> varEnv;
Variable<? extends DeclarativeEnvironmentRecord> varEnvRec;
if (!hasParameterExpressions) {
assert fscope == fscope.variableScope();
/* step 27.a (note) */
/* step 27.b */
instantiatedVarNames = new HashSet<>(parameterBindings);
/* step 27.c */
for (Name varName : varNames) {
if (instantiatedVarNames.add(varName)) {
BindingOp<FunctionEnvironmentRecord> op = BindingOp.of(envRec, varName);
op.createMutableBinding(envRec, varName, false, mv);
op.initializeBinding(envRec, varName, undefined, mv);
}
}
/* steps 27.d-27.e */
varEnv = env;
varEnvRec = envRec;
} else {
assert fscope != fscope.variableScope();
assert fscope.variableScope().isPresent();
mv.enterScope(fscope.variableScope());
/* step 28.a (note) */
/* step 28.b */
varEnv = newDeclarativeEnvironment("varEnv", paramsEnv, mv);
/* step 28.c */
varEnvRec = getDeclarativeEnvironmentRecord("varEnvRec", varEnv, mv);
/* step 28.d */
setVariableEnvironment(varEnv, mv);
/* step 28.e */
instantiatedVarNames = new HashSet<>();
/* step 28.f */
Variable<Object> tempValue = null;
for (Name varName : varNames) {
if (instantiatedVarNames.add(varName)) {
BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(varEnvRec, varName);
op.createMutableBinding(varEnvRec, varName, false, mv);
if (!parameterBindingsSet.contains(varName) || functionNames.contains(varName)) {
op.initializeBinding(varEnvRec, varName, undefined, mv);
} else {
BindingOp<DeclarativeEnvironmentRecord> opp = BindingOp.of(paramsEnvRec, varName);
opp.getBindingValue(paramsEnvRec, varName, strict, mv);
if (tempValue == null) {
tempValue = mv.newVariable("tempValue", Object.class);
}
mv.store(tempValue);
op.initializeBinding(varEnvRec, varName, tempValue, mv);
}
}
}
}
// FIXME: spec issue - wrong step reference in annexB
for (Name fname : function.getScope().blockFunctionNames()) {
// FIXME: spec bug - initial binding for "arguments" (https://github.com/tc39/ecma262/issues/991)
if (instantiatedVarNames.add(fname)) {
BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(varEnvRec, fname);
op.createMutableBinding(varEnvRec, fname, false, mv);
if (!fname.getIdentifier().equals("arguments") || !argumentsObjectNeeded) {
op.initializeBinding(varEnvRec, fname, undefined, mv);
} else {
BindingOp<DeclarativeEnvironmentRecord> opp = BindingOp.of(paramsEnvRec, fname);
opp.getBindingValue(paramsEnvRec, fname, false, mv);
Value<Object> tempValue = mv.storeTemporary(Object.class);
op.initializeBinding(varEnvRec, fname, tempValue, mv);
}
}
}
/* steps 30-32 */
Variable<? extends LexicalEnvironment<? extends DeclarativeEnvironmentRecord>> lexEnv;
Variable<? extends DeclarativeEnvironmentRecord> lexEnvRec;
assert strict || fscope.variableScope() != fscope.lexicalScope();
if (!strict || fscope.variableScope() != fscope.lexicalScope()) {
// NB: Scopes are unmodifiable once constructed, that means we need to emit the extra
// scope for functions with deferred strict-ness, even if this scope is not present in
// the specification.
mv.enterScope(fscope.lexicalScope());
assert fscope.lexicalScope().isPresent() == !lexicalNames.isEmpty();
if (!lexicalNames.isEmpty()) {
/* step 30 */
lexEnv = newDeclarativeEnvironment("lexEnv", varEnv, mv);
/* step 32 */
lexEnvRec = getDeclarativeEnvironmentRecord("lexEnvRec", lexEnv, mv);
} else {
// Optimization: Skip environment allocation if no lexical names are defined.
/* step 30 */
lexEnv = varEnv;
/* step 32 */
lexEnvRec = varEnvRec;
}
} else {
/* step 30 */
lexEnv = varEnv;
/* step 32 */
lexEnvRec = varEnvRec;
}
/* step 33 */
if (lexEnv != env) {
setLexicalEnvironment(lexEnv, mv);
}
/* step 34 */
List<Declaration> lexDeclarations = LexicallyScopedDeclarations(function);
/* step 35 */
for (Declaration d : lexDeclarations) {
assert !(d instanceof HoistableDeclaration);
for (Name dn : BoundNames(d)) {
BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(lexEnvRec, dn);
if (d.isConstDeclaration()) {
op.createImmutableBinding(lexEnvRec, dn, true, mv);
} else {
op.createMutableBinding(lexEnvRec, dn, false, mv);
}
}
}
/* step 36 */
for (HoistableDeclaration f : functionsToInitialize) {
Name fn = BoundName(f);
// stack: [] -> [fo]
InstantiateFunctionObject(context, lexEnv, f, mv);
mv.store(fo);
// stack: [fo] -> []
// Resolve the actual binding name: function(a){ function a(){} }
// TODO: Can be removed when StaticIdResolution handles this case.
Name name = fscope.variableScope().resolveName(fn);
BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(varEnvRec, name);
op.setMutableBinding(varEnvRec, name, fo, false, mv);
}
/* step 37 */
mv._return();
}
use of com.github.anba.es6draft.ast.Declaration in project es6draft by anba.
the class ModuleDeclarationInstantiationGenerator method generate.
private void generate(Module module, SourceTextModuleRecord moduleRecord, ModuleDeclInitVisitor mv) {
Variable<ExecutionContext> context = mv.getExecutionContext();
Variable<SourceTextModuleRecord> moduleRec = mv.getModule();
Variable<LexicalEnvironment<ModuleEnvironmentRecord>> env = mv.getModuleEnvironment();
Variable<ModuleEnvironmentRecord> envRec = mv.newVariable("envRec", ModuleEnvironmentRecord.class);
getEnvironmentRecord(env, envRec, mv);
Variable<ResolvedBinding> resolved = mv.newVariable("resolved", ResolvedBinding.class);
Variable<ScriptObject> namespace = null;
Variable<FunctionObject> fo = null;
Variable<Undefined> undef = mv.newVariable("undef", Undefined.class);
mv.loadUndefined();
mv.store(undef);
/* step 1 */
for (ExportEntry exportEntry : moduleRecord.getIndirectExportEntries()) {
mv.lineInfo(exportEntry.getLine());
mv.load(moduleRec);
mv.aconst(exportEntry.getExportName());
mv.invoke(Methods.ModuleOperations_resolveExportOrThrow);
}
/* step 8 */
for (ImportEntry importEntry : moduleRecord.getImportEntries()) {
mv.lineInfo(importEntry.getLine());
if (importEntry.isStarImport()) {
Name localName = new Name(importEntry.getLocalName());
BindingOp<ModuleEnvironmentRecord> op = BindingOp.of(envRec, localName);
op.createImmutableBinding(envRec, localName, true, mv);
mv.load(context);
mv.load(moduleRec);
mv.aconst(importEntry.getModuleRequest());
mv.invoke(Methods.ModuleOperations_getModuleNamespace);
if (namespace == null) {
namespace = mv.newVariable("namespace", ScriptObject.class);
}
mv.store(namespace);
op.initializeBinding(envRec, localName, namespace, mv);
} else {
mv.load(moduleRec);
mv.aconst(importEntry.getModuleRequest());
mv.aconst(importEntry.getImportName());
mv.invoke(Methods.ModuleOperations_resolveImportOrThrow);
mv.store(resolved);
/* step 8.d.iii */
createImportBinding(context, envRec, importEntry.getLocalName(), resolved, mv);
}
}
/* step 9 (not applicable) */
/* step 10 */
List<StatementListItem> varDeclarations = VarScopedDeclarations(module);
/* step 11 */
HashSet<Name> declaredVarNames = new HashSet<>();
/* step 12 */
for (StatementListItem d : varDeclarations) {
assert d instanceof VariableStatement;
for (Name dn : BoundNames((VariableStatement) d)) {
if (declaredVarNames.add(dn)) {
BindingOp<ModuleEnvironmentRecord> op = BindingOp.of(envRec, dn);
op.createMutableBinding(envRec, dn, false, mv);
op.initializeBinding(envRec, dn, undef, mv);
}
}
}
/* step 13 */
List<Declaration> lexDeclarations = LexicallyScopedDeclarations(module);
/* step 14 */
for (Declaration d : lexDeclarations) {
for (Name dn : BoundNames(d)) {
BindingOp<ModuleEnvironmentRecord> op = BindingOp.of(envRec, dn);
if (d.isConstDeclaration()) {
op.createImmutableBinding(envRec, dn, true, mv);
} else {
op.createMutableBinding(envRec, dn, false, mv);
}
if (d instanceof HoistableDeclaration) {
InstantiateFunctionObject(context, env, d, mv);
if (fo == null) {
fo = mv.newVariable("fo", FunctionObject.class);
}
mv.store(fo);
op.initializeBinding(envRec, dn, fo, mv);
}
}
}
mv._return();
}
use of com.github.anba.es6draft.ast.Declaration in project es6draft by anba.
the class EvalDeclarationInstantiationGenerator method generateGlobal.
private void generateGlobal(Script evalScript, EvalDeclInitVisitor mv) {
assert evalScript.isGlobalCode() && !evalScript.isStrict() && !evalScript.isScripting();
Variable<ExecutionContext> context = mv.getExecutionContext();
Variable<LexicalEnvironment<GlobalEnvironmentRecord>> varEnv = mv.newVariable("varEnv", LexicalEnvironment.class).uncheckedCast();
Variable<LexicalEnvironment<DeclarativeEnvironmentRecord>> lexEnv = mv.newVariable("lexEnv", LexicalEnvironment.class).uncheckedCast();
Variable<FunctionObject> fo = null;
getVariableEnvironment(context, varEnv, mv);
getLexicalEnvironment(context, lexEnv, mv);
/* step 1 */
Set<Name> varNames = VarDeclaredNames(evalScript);
/* step 2 */
List<StatementListItem> varDeclarations = VarScopedDeclarations(evalScript);
/* step 3 */
Variable<DeclarativeEnvironmentRecord> lexEnvRec = mv.newVariable("lexEnvRec", DeclarativeEnvironmentRecord.class);
/* step 4 */
Variable<GlobalEnvironmentRecord> varEnvRec = mv.newVariable("varEnvRec", GlobalEnvironmentRecord.class);
getEnvironmentRecord(varEnv, varEnvRec, mv);
/* step 5 */
if (!varNames.isEmpty()) {
/* step 5.a */
// Iterate over declarations to be able to emit line-info entries.
HashSet<Name> checkedVarNames = new HashSet<>();
for (StatementListItem item : VarScopedDeclarations(evalScript)) {
if (item instanceof VariableStatement) {
for (VariableDeclaration vd : ((VariableStatement) item).getElements()) {
for (Name name : BoundNames(vd)) {
if (checkedVarNames.add(name)) {
canDeclareVarScopedOrThrow(context, varEnvRec, vd, name, mv);
}
}
}
} else {
HoistableDeclaration d = (HoistableDeclaration) item;
Name name = BoundName(d);
if (checkedVarNames.add(name)) {
canDeclareVarScopedOrThrow(context, varEnvRec, d, name, mv);
}
}
}
/* steps 5.b-d */
if (isEnclosedByLexicalOrHasRestrictedVar(evalScript)) {
checkLexicalRedeclaration(evalScript, context, varEnv, lexEnv, varNames, mv);
}
}
// Extension: Class Fields
checkUndeclaredPrivateNames(evalScript, context, mv);
/* step 6 */
ArrayDeque<HoistableDeclaration> functionsToInitialize = new ArrayDeque<>();
/* step 7 */
HashSet<Name> declaredFunctionNames = new HashSet<>();
/* step 8 */
for (StatementListItem item : reverse(varDeclarations)) {
if (item instanceof HoistableDeclaration) {
HoistableDeclaration d = (HoistableDeclaration) item;
Name fn = BoundName(d);
if (declaredFunctionNames.add(fn)) {
canDeclareGlobalFunctionOrThrow(context, varEnvRec, d, fn, mv);
functionsToInitialize.addFirst(d);
}
}
}
if (!functionsToInitialize.isEmpty()) {
fo = mv.newVariable("fo", FunctionObject.class);
}
/* step 9 */
LinkedHashMap<Name, VariableDeclaration> declaredVarNames = new LinkedHashMap<>();
/* step 10 */
for (StatementListItem d : varDeclarations) {
if (d instanceof VariableStatement) {
for (VariableDeclaration vd : ((VariableStatement) d).getElements()) {
for (Name vn : BoundNames(vd)) {
if (!declaredFunctionNames.contains(vn)) {
canDeclareGlobalVarOrThrow(context, varEnvRec, vd, vn, mv);
declaredVarNames.put(vn, vd);
}
}
}
}
}
// ES2016: Block-scoped global function declarations
if (hasBlockFunctions(evalScript)) {
final boolean catchVar = codegen.isEnabled(CompatibilityOption.CatchVarStatement);
int idCounter = 0;
List<FunctionDeclaration> blockFunctions = evalScript.getScope().blockFunctions();
HashSet<Name> declaredFunctionOrVarNames = new HashSet<>();
declaredFunctionOrVarNames.addAll(declaredFunctionNames);
declaredFunctionOrVarNames.addAll(declaredVarNames.keySet());
for (FunctionDeclaration f : blockFunctions) {
Name fn = f.getName();
Jump next = new Jump();
// Runtime check always required for global block-level function declarations.
f.setLegacyBlockScopeId(++idCounter);
if (isEnclosedByLexical(evalScript)) {
canDeclareVarBinding(varEnv, lexEnv, fn, catchVar, next, mv);
}
// FIXME: spec issue - avoid (observable!) duplicate checks for same name?
// FIXME: spec issue - property creation order important?
canDeclareGlobalFunction(varEnvRec, f, fn, next, mv);
setLegacyBlockFunction(context, f, mv);
if (declaredFunctionOrVarNames.add(fn)) {
createGlobalFunctionBinding(varEnvRec, f, fn, true, mv);
}
mv.mark(next);
}
}
/* step 12 */
List<Declaration> lexDeclarations = LexicallyScopedDeclarations(evalScript);
/* step 13 */
if (!lexDeclarations.isEmpty()) {
getEnvironmentRecord(lexEnv, lexEnvRec, mv);
createLexicalDeclarations(lexDeclarations, lexEnvRec, mv);
}
/* step 14 */
for (HoistableDeclaration f : functionsToInitialize) {
Name fn = BoundName(f);
InstantiateFunctionObject(context, lexEnv, f, mv);
mv.store(fo);
createGlobalFunctionBinding(varEnvRec, f, fn, fo, true, mv);
}
/* step 15 */
for (Map.Entry<Name, VariableDeclaration> e : declaredVarNames.entrySet()) {
createGlobalVarBinding(varEnvRec, e.getValue(), e.getKey(), true, mv);
}
/* step 16 */
mv._return();
}
Aggregations