Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(299)

Unified Diff: lib/compiler/implementation/ssa/builder.dart

Issue 10911062: Codegen support for the argument definition test. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: lib/compiler/implementation/ssa/builder.dart
===================================================================
--- lib/compiler/implementation/ssa/builder.dart (revision 11792)
+++ lib/compiler/implementation/ssa/builder.dart (working copy)
@@ -806,13 +806,14 @@
LocalsHandler localsHandler;
HInstruction rethrowableException;
Map<Element, HParameterValue> parameters;
+ Map<Element, HInstruction> parametersWithSentinel;
Map<TargetElement, JumpHandler> jumpTargets;
/**
* Variables stored in the current activation. These variables are
* being updated in try/catch blocks, and should be
- * accessed indirectly through HFieldGet and HFieldSet.
+ * accessed indirectly through [HLocalGet] and [HLocalSet].
*/
Map<Element, HLocalValue> activationVariables;
@@ -841,6 +842,7 @@
activationVariables = new Map<Element, HLocalValue>(),
jumpTargets = new Map<TargetElement, JumpHandler>(),
parameters = new Map<Element, HParameterValue>(),
+ parametersWithSentinel = new Map<Element, HInstruction>(),
inliningStack = <InliningState>[],
super(work.resolutionTree) {
localsHandler = new LocalsHandler(this);
@@ -1226,6 +1228,59 @@
return closeFunction();
}
+ void addParameterCheckInstruction(Element element) {
+ // This is the code we emit for a parameter that is being checked
+ // on whether it was given at value at the call site:
+ //
+ // foo([a = 42) {
+ // if (?a) print('parameter passed $a');
+ // }
+ //
+ // foo([a = 42]) {
+ // var t1 = a === sentinel;
+ // if (t1) a = 42;
+ // if (!t1) print('parameter passed ' + a);
+ // }
+
+ // Fetch the original default value of [element];
+ ConstantHandler handler = compiler.constantHandler;
+ Constant constant = handler.compileVariable(element);
+ HConstant defaultValue = constant == null
+ ? graph.addConstantNull()
+ : graph.addConstant(constant);
+
+ // Emit the equality check with the sentinel.
+ HConstant sentinel = graph.addConstant(SentinelConstant.SENTINEL);
+ Element equalsHelper = interceptors.getTripleEqualsInterceptor();
+ HInstruction target = new HStatic(equalsHelper);
+ add(target);
+ HInstruction operand = parameters[element];
+ HInstruction check = new HIdentity(target, sentinel, operand);
+ add(check);
+
+ // If the check succeeds, we must update the parameter with the
+ // default value.
+ handleIf(element.parseNode(compiler),
+ () => stack.add(check),
+ () => localsHandler.updateLocal(element, defaultValue),
+ null);
+
+ // Create the instruction that parameter checks will use.
+ check = new HNot(check);
+ add(check);
+
+ // If the parameter check is also used by closures,
+ // we need to update the closure field holding that check.
+ ClosureClassMap closureData = localsHandler.closureData;
+ Element redirect = closureData.parametersWithSentinel[element];
+ if (redirect != null) {
+ localsHandler.updateLocal(redirect, check);
+ }
+ // Cache the check so that uses in this method share the same
+ // check instruction.
+ parametersWithSentinel[element] = check;
+ }
+
void openFunction(FunctionElement functionElement,
FunctionExpression node) {
HBasicBlock block = graph.addNewBlock();
@@ -1236,11 +1291,17 @@
open(block);
+ FunctionSignature params = functionElement.computeSignature(compiler);
+ params.forEachParameter((Element element) {
+ if (elements.isParameterChecked(element)) {
+ addParameterCheckInstruction(element);
+ }
+ });
+
// Put the type checks in the first successor of the entry,
// because that is where the type guards will also be inserted.
// This way we ensure that a type guard will dominate the type
// check.
- FunctionSignature params = functionElement.computeSignature(compiler);
params.forEachParameter((Element element) {
HInstruction newParameter = potentiallyCheckType(
localsHandler.directLocals[element], element);
@@ -1780,8 +1841,24 @@
void visitUnary(Send node, Operator op) {
String value = op.source.stringValue;
if (value === '?') {
kasperl 2012/09/04 10:50:08 node.isParameterCheck?
ngeoffray 2012/09/04 10:53:44 Done.
- // TODO(ahe): Implement argument definition test.
- stack.add(graph.addConstantBool(true));
+ Element element = elements[node.receiver];
+ // If the parameter we're accessing is from the current
+ // function, we can just fetch the cached instruction.
+ HInstruction check = parametersWithSentinel[element];
+ if (check !== null) {
+ stack.add(check);
+ } else {
+ // The parameter is from an outer function. Lookup the
+ // element in the closure data of the outer function and read
+ // it.
+ assert(element.enclosingElement != work.element);
+ Node node = element.enclosingElement.parseNode(compiler);
+ ClosureClassMap parameterClosureData =
+ compiler.closureToClassMapper.getMappingForNestedFunction(node);
+ Element fieldCheck =
+ parameterClosureData.parametersWithSentinel[element];
+ stack.add(localsHandler.readLocal(fieldCheck));
+ }
return;
}
assert(node.argumentsNode is Prefix);
@@ -2165,8 +2242,15 @@
return pop();
}
- HInstruction compileConstant(Element constantElement) {
- Constant constant = compiler.compileVariable(constantElement);
+ HInstruction compileConstant(Element parameter) {
+ Constant constant;
+ TreeElements calleeElements =
+ compiler.enqueuer.resolution.getCachedElements(element);
+ if (calleeElements.isParameterChecked(parameter)) {
+ constant = SentinelConstant.SENTINEL;
+ } else {
+ constant = compiler.compileVariable(parameter);
+ }
return graph.addConstant(constant);
}
@@ -3669,7 +3753,11 @@
tooDifficult = true;
}
- void visitSend(Node node) {
+ void visitSend(Send node) {
+ if (node.isParameterCheck) {
+ tooDifficult = true;
+ return;
+ }
node.visitChildren(this);
}

Powered by Google App Engine
This is Rietveld 408576698