From de3dedd82c982e6038d3d8e52cbb6485b875e740 Mon Sep 17 00:00:00 2001 From: Haiyang Date: Thu, 26 Sep 2019 11:05:48 +0200 Subject: [PATCH 1/3] forinof callback fix --- .../js/analysis/forinof/analysis.js | 15 +++++ .../forinof/minitests.forinof.js.expected | 21 +++++++ .../js/analysis/trivial/emptyTemplate.js | 11 ++++ .../ch/usi/inf/nodeprof/ProfiledTagEnum.java | 8 +-- .../handlers/CFBlockEventHandler.java | 26 ++++++++ .../inf/nodeprof/jalangi/JalangiAnalysis.java | 23 +++++-- .../jalangi/factory/CFBlockFactory.java | 60 +++++++++++++++++++ .../jalangi/factory/ForObjectFactory.java | 15 ++++- 8 files changed, 169 insertions(+), 10 deletions(-) create mode 100644 src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/handlers/CFBlockEventHandler.java create mode 100644 src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/CFBlockFactory.java diff --git a/src/ch.usi.inf.nodeprof/js/analysis/forinof/analysis.js b/src/ch.usi.inf.nodeprof/js/analysis/forinof/analysis.js index 57c58376..88406589 100644 --- a/src/ch.usi.inf.nodeprof/js/analysis/forinof/analysis.js +++ b/src/ch.usi.inf.nodeprof/js/analysis/forinof/analysis.js @@ -21,6 +21,21 @@ this.forObject = function (iid, isForIn) { console.log('forObject@', J$.iidToLocation(iid), isForIn, lastExprResult); } + this.forObjectPost = function (iid, isForIn) { + console.log('forObjectPost@', J$.iidToLocation(iid), isForIn); + } + this.cfBlockEnter = function(iid) { + console.log('iterationEnter@', J$.iidToLocation(iid)); + } + this.cfBlockExit = function(iid) { + console.log('iterationExit@', J$.iidToLocation(iid)); + } + this.read = function(iid, name, value) { + console.log('read@', J$.iidToLocation(iid), name); + } + this.write = function(iid, name, value) { + console.log('write@', J$.iidToLocation(iid), name); + } this.endExpression = function (iid, type, result) { lastExprResult = result; } diff --git a/src/ch.usi.inf.nodeprof/js/analysis/forinof/minitests.forinof.js.expected b/src/ch.usi.inf.nodeprof/js/analysis/forinof/minitests.forinof.js.expected index 8399d7aa..994ebbd8 100644 --- a/src/ch.usi.inf.nodeprof/js/analysis/forinof/minitests.forinof.js.expected +++ b/src/ch.usi.inf.nodeprof/js/analysis/forinof/minitests.forinof.js.expected @@ -1,2 +1,23 @@ +write@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:1:66:4:2) obj +read@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:6:17:6:20) obj forObject@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:6:1:7:2) true { x: 'valueX', y: 'valueY' } +iterationEnter@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:6:1:7:2) +write@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:6:1:7:2) key +iterationExit@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:6:1:7:2) +iterationEnter@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:6:1:7:2) +write@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:6:1:7:2) key +iterationExit@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:6:1:7:2) +forObjectPost@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:6:1:7:2) true +write@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:9:5:9:21) arr +read@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:17:11:20) arr forObject@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) false [ 41, 42, 43 ] +iterationEnter@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) +write@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) val +iterationExit@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) +iterationEnter@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) +write@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) val +iterationExit@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) +iterationEnter@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) +write@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) val +iterationExit@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) +forObjectPost@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) false diff --git a/src/ch.usi.inf.nodeprof/js/analysis/trivial/emptyTemplate.js b/src/ch.usi.inf.nodeprof/js/analysis/trivial/emptyTemplate.js index b06b1dfc..1a9c7f1b 100644 --- a/src/ch.usi.inf.nodeprof/js/analysis/trivial/emptyTemplate.js +++ b/src/ch.usi.inf.nodeprof/js/analysis/trivial/emptyTemplate.js @@ -171,6 +171,17 @@ **/ this.forObject = function (iid, isForIn) { } + this.forObjectPost = function (iid, isForIn) { + } + + /** + * This callback is called before a value is returned from a function using the return keyword. + * + * @param {number} iid - Static unique instruction identifier of this callback + * @param {*} val - Value to be returned + */ + this._return = function (iid, val) { + }; /** * This callback is called before a value is returned from a function using the return keyword. diff --git a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/ProfiledTagEnum.java b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/ProfiledTagEnum.java index 1765d1e5..90642b49 100644 --- a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/ProfiledTagEnum.java +++ b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/ProfiledTagEnum.java @@ -26,9 +26,9 @@ public enum ProfiledTagEnum { UNARY(JSTags.UnaryOperationTag.class, -1), // have multiple case BINARY(JSTags.BinaryOperationTag.class, 2), - CF_BRANCH(JSTags.ControlFlowBranchTag.class, -1), // to be checked - CF_BLOCK(JSTags.ControlFlowBlockTag.class, -1), // to be checked - CF_ROOT(JSTags.ControlFlowRootTag.class, 0), // to be checked + CF_BRANCH(JSTags.ControlFlowBranchTag.class, -1), // have multiple case + CF_BLOCK(JSTags.ControlFlowBlockTag.class, 0), + CF_ROOT(JSTags.ControlFlowRootTag.class, 0), EVAL(JSTags.EvalCallTag.class, 2), DECLARE(JSTags.DeclareTag.class, 0), VAR_READ(JSTags.ReadVariableTag.class, 0), @@ -42,7 +42,7 @@ public enum ProfiledTagEnum { BUILTIN(JSTags.BuiltinRootTag.class, 0), LITERAL(JSTags.LiteralTag.class, 0), STATEMENT(StandardTags.StatementTag.class, 0), - NEW(JSTags.ObjectAllocationTag.class, -1), + NEW(JSTags.ObjectAllocationTag.class, -1), // any number of inputs for arguments EXPRESSION(StandardTags.ExpressionTag.class, 0); // the corresponding JSTags class diff --git a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/handlers/CFBlockEventHandler.java b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/handlers/CFBlockEventHandler.java new file mode 100644 index 00000000..85b1a392 --- /dev/null +++ b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/handlers/CFBlockEventHandler.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright 2018 Dynamic Analysis Group, Università della Svizzera Italiana (USI) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ +package ch.usi.inf.nodeprof.handlers; + +import com.oracle.truffle.api.instrumentation.EventContext; + +import ch.usi.inf.nodeprof.ProfiledTagEnum; + +public abstract class CFBlockEventHandler extends BaseSingleTagEventHandler { + public CFBlockEventHandler(EventContext context) { + super(context, ProfiledTagEnum.CF_BLOCK); + } +} diff --git a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/JalangiAnalysis.java b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/JalangiAnalysis.java index b57bcd90..9f1f8341 100644 --- a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/JalangiAnalysis.java +++ b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/JalangiAnalysis.java @@ -36,6 +36,7 @@ import ch.usi.inf.nodeprof.jalangi.factory.BinaryFactory; import ch.usi.inf.nodeprof.jalangi.factory.ReturnFactory; import ch.usi.inf.nodeprof.jalangi.factory.BuiltinFactory; +import ch.usi.inf.nodeprof.jalangi.factory.CFBlockFactory; import ch.usi.inf.nodeprof.jalangi.factory.ConditionalFactory; import ch.usi.inf.nodeprof.jalangi.factory.DeclareFactory; import ch.usi.inf.nodeprof.jalangi.factory.EvalFactory; @@ -126,6 +127,12 @@ public class JalangiAnalysis { put("asyncFunctionExit", EnumSet.of(CF_ROOT)); put("forObject", EnumSet.of(CF_ROOT)); + put("forObjectPost", EnumSet.of(CF_ROOT)); + + put("cfBlockEnter", EnumSet.of(CF_BLOCK)); + put("cfBlockExit", EnumSet.of(CF_BLOCK)); + + put("_return", EnumSet.of(CF_BRANCH)); put("_return", EnumSet.of(CF_BRANCH)); @@ -134,6 +141,7 @@ public class JalangiAnalysis { put("startExpression", EnumSet.of(EXPRESSION)); put("endExpression", EnumSet.of(EXPRESSION)); + } }); @@ -279,10 +287,10 @@ public void onReady() { new EvalFunctionFactory(this.jsAnalysis, callbacks.get("evalFunctionPre"), callbacks.get("evalFunctionPost"))); } - if (this.callbacks.containsKey("forObject")) { + if (this.callbacks.containsKey("forObject") || this.callbacks.containsKey("forObjectPost")) { this.instrument.onCallback( ProfiledTagEnum.CF_ROOT, - new ForObjectFactory(this.jsAnalysis, callbacks.get("forObject"))); + new ForObjectFactory(this.jsAnalysis, callbacks.get("forObject"), callbacks.get("forObjectPost"))); } /** @@ -303,8 +311,6 @@ public void onReady() { } /** - * TODO - * * Loop not tested */ if (this.callbacks.containsKey("loopEnter") || this.callbacks.containsKey("loopExit")) { @@ -313,6 +319,15 @@ public void onReady() { new LoopFactory(this.jsAnalysis, callbacks.get("loopEnter"), callbacks.get("loopExit"))); } + /** + * cfBlockEnter, cfBlockExit + */ + if (this.callbacks.containsKey("cfBlockEnter") || this.callbacks.containsKey("cfBlockExit")) { + this.instrument.onCallback( + ProfiledTagEnum.CF_BLOCK, + new CFBlockFactory(this.jsAnalysis, callbacks.get("cfBlockEnter"), callbacks.get("cfBlockExit"))); + } + /** * _return callback */ diff --git a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/CFBlockFactory.java b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/CFBlockFactory.java new file mode 100644 index 00000000..b7c445da --- /dev/null +++ b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/CFBlockFactory.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright 2018 Dynamic Analysis Group, Università della Svizzera Italiana (USI) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ +package ch.usi.inf.nodeprof.jalangi.factory; + +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.instrumentation.EventContext; +import com.oracle.truffle.api.nodes.DirectCallNode; +import com.oracle.truffle.api.object.DynamicObject; + +import ch.usi.inf.nodeprof.handlers.BaseEventHandlerNode; +import ch.usi.inf.nodeprof.handlers.CFBlockEventHandler; + +public class CFBlockFactory extends AbstractFactory { + public CFBlockFactory(Object jalangiAnalysis, DynamicObject pre, DynamicObject post) { + super("cfblock", jalangiAnalysis, pre, post, 1, 1); + } + + @Override + public BaseEventHandlerNode create(EventContext context) { + return new CFBlockEventHandler(context) { + @Child DirectCallNode preCall = createPreCallNode(); + @Child DirectCallNode postCall = createPostCallNode(); + + @Override + public void executePre(VirtualFrame frame, Object[] inputs) { + if (pre != null) { + setPreArguments(0, getSourceIID()); + // TODO + // add information about the type of the block (if, iteration, switch) + directCall(preCall, true, getSourceIID()); + } + } + + @Override + public void executePost(VirtualFrame frame, Object result, + Object[] inputs) { + if (post != null) { + setPostArguments(0, getSourceIID()); + // TODO + // add information about the type of the block (if, iteration, switch) + directCall(postCall, false, getSourceIID()); + } + } + }; + } + +} diff --git a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/ForObjectFactory.java b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/ForObjectFactory.java index f7176049..2c5775d6 100644 --- a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/ForObjectFactory.java +++ b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/ForObjectFactory.java @@ -24,14 +24,15 @@ import ch.usi.inf.nodeprof.handlers.LoopEventHandler; public class ForObjectFactory extends AbstractFactory { - public ForObjectFactory(Object jalangiAnalysis, DynamicObject pre) { - super("forObject", jalangiAnalysis, pre, null, 2, -1); + public ForObjectFactory(Object jalangiAnalysis, DynamicObject pre, DynamicObject post) { + super("forObject", jalangiAnalysis, pre, post, 2, 2); } @Override public BaseEventHandlerNode create(EventContext context) { return new LoopEventHandler(context) { @Child DirectCallNode preCall = createPreCallNode(); + @Child DirectCallNode postCall = createPostCallNode(); @Override public void executePre(VirtualFrame frame, @@ -42,6 +43,16 @@ public void executePre(VirtualFrame frame, directCall(preCall, true, getSourceIID()); } } + + @Override + public void executePost(VirtualFrame frame, Object result, Object[] inputs) { + if (post != null && (isForIn() || isForOf())) { + setPostArguments(0, getSourceIID()); + setPostArguments(1, isForIn()); + directCall(postCall, true, getSourceIID()); + } + + } }; } From 001a6769e28c5a3918f78ea20688c79306283431 Mon Sep 17 00:00:00 2001 From: Alexander Jordan Date: Mon, 30 Sep 2019 15:56:53 +1000 Subject: [PATCH 2/3] Remove loop/for callbacks in favor of CF root/block Extended forinof test uses the callbacks with a custom for-of iterator. --- .../js/minitests/forinof.js | 42 +++++++++ .../js/analysis/forinof/analysis.js | 89 ++++++++++++++++--- .../forinof/minitests.forinof.js.expected | 62 ++++++++----- .../js/analysis/trivial/emptyTemplate.js | 22 ++--- src/ch.usi.inf.nodeprof/js/jalangi.js | 8 +- .../handlers/CFBlockEventHandler.java | 13 +++ .../nodeprof/handlers/CFRootEventHandler.java | 7 +- .../nodeprof/handlers/LoopEventHandler.java | 42 --------- .../inf/nodeprof/jalangi/JalangiAnalysis.java | 29 ++---- .../jalangi/factory/CFBlockFactory.java | 8 +- .../{LoopFactory.java => CFRootFactory.java} | 15 ++-- .../jalangi/factory/ForObjectFactory.java | 59 ------------ .../usi/inf/nodeprof/utils/NodeProfUtil.java | 38 ++++++++ 13 files changed, 251 insertions(+), 183 deletions(-) delete mode 100644 src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/handlers/LoopEventHandler.java rename src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/{LoopFactory.java => CFRootFactory.java} (82%) delete mode 100644 src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/ForObjectFactory.java create mode 100644 src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/utils/NodeProfUtil.java diff --git a/src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js b/src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js index 127ac8ca..9171e725 100644 --- a/src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js +++ b/src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js @@ -1,3 +1,19 @@ +/******************************************************************************* + * Copyright 2019 Dynamic Analysis Group, Università della Svizzera Italiana (USI) + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ let obj = { x:'valueX', y:'valueY', @@ -10,3 +26,29 @@ let arr = [41,42,43]; for (let val of arr) { } + +const itemA = 42; +class Foo { + constructor() { + this.itemB = 'bar'; + } + [Symbol.iterator]() { + let moreToIterate = 2; + return { + next: () => { + if (moreToIterate) { + const ret = { value: moreToIterate == 2 ? itemA : this.itemB, done: false }; + moreToIterate--; + return ret; + } else { + return { done: true } + } + } + } + } +} + +let o = new Foo(); + +for (i of o) { +} diff --git a/src/ch.usi.inf.nodeprof/js/analysis/forinof/analysis.js b/src/ch.usi.inf.nodeprof/js/analysis/forinof/analysis.js index 88406589..142a16c2 100644 --- a/src/ch.usi.inf.nodeprof/js/analysis/forinof/analysis.js +++ b/src/ch.usi.inf.nodeprof/js/analysis/forinof/analysis.js @@ -16,25 +16,94 @@ *******************************************************************************/ //DO NOT INSTRUMENT (function (sandbox) { + const assert = require('assert'); function MyAnalysis() { + + // last expression before for-in/for-of is the iteration object let lastExprResult; - this.forObject = function (iid, isForIn) { - console.log('forObject@', J$.iidToLocation(iid), isForIn, lastExprResult); + + // control flow tracking + let cfRoots = new Map; + let cfBlockStack = []; + // ignore control flow other that for-in/for-of + let ignoredIIDs = new Set; + + // keep track of user-defined iterators + let iteratorFuncs = new Set; + let iteratorIIDs = new Set; + let nextFuncs = new Set; + let rwTrackStack = []; + + function logLoc(cbName, iid, ...extra) { + if (ignoredIIDs.has(iid)) { + return; + } + console.log('%s@%s', cbName, J$.iidToLocation(iid), ...extra); + } + function storeIterator(obj) { + let proto = obj; + while (proto != null) { + let iterator = proto[Symbol.iterator]; + if (iterator) { + iteratorFuncs.add(iterator); + } + proto = Object.getPrototypeOf(proto); + } } - this.forObjectPost = function (iid, isForIn) { - console.log('forObjectPost@', J$.iidToLocation(iid), isForIn); + + this.cfRootEnter = function (iid, type) { + if (type === J$.cf.IF) { + ignoredIIDs.add(iid); + } + logLoc('cfRootEnter', iid, type); + if (type === J$.cf.FOR_OF || type === J$.cf.FOR_IN) { + const o = lastExprResult; + console.log('iteration obj:', nextFuncs.has(o.next) ? '' : o); + } + cfRoots.set(iid, type); + } + this.cfRootExit = function (iid, type) { + logLoc('cfRootExit', iid, type); } - this.cfBlockEnter = function(iid) { - console.log('iterationEnter@', J$.iidToLocation(iid)); + this.cfBlockEnter = function(iid, iidParent) { + cfBlockStack.push(iid); } - this.cfBlockExit = function(iid) { - console.log('iterationExit@', J$.iidToLocation(iid)); + this.cfBlockExit = function(iid, iidParent) { + assert(cfBlockStack.pop() === iid); + if (!ignoredIIDs.has(iidParent)) { + console.log('cfRoot %s @ %s', cfRoots.get(iidParent), J$.iidToLocation(iidParent)); + console.log(' \\-cfBlock @ %s', J$.iidToLocation(iid)); + } } this.read = function(iid, name, value) { - console.log('read@', J$.iidToLocation(iid), name); + if (rwTrackStack.length) { + console.log('read@', J$.iidToLocation(iid), name); // only inside iter-next() + } } this.write = function(iid, name, value) { - console.log('write@', J$.iidToLocation(iid), name); + if (rwTrackStack.length) { + console.log('write@', J$.iidToLocation(iid), name); // only inside iter-next() + } + } + this.functionEnter = function (iid, f, dis, args) { + if (iteratorFuncs.has(f)) { + console.log("functionEnter: %s / %s / %d", f.name, J$.iidToLocation(iid), arguments.length); + iteratorIIDs.add(iid); + } + if (nextFuncs.has(f) || rwTrackStack.length) { + rwTrackStack.push(iid); // stack length > 0 when inside next() + } + } + this.functionExit = function (iid, returnVal) { + if (iteratorIIDs.has(iid)) { + nextFuncs.add(returnVal.next); + } + rwTrackStack.pop(); + } + this.invokeFun = function (iid, f, base, args, result, isConstructor, isMethod) { + if (typeof result === 'object') { + storeIterator(result); + } } this.endExpression = function (iid, type, result) { lastExprResult = result; diff --git a/src/ch.usi.inf.nodeprof/js/analysis/forinof/minitests.forinof.js.expected b/src/ch.usi.inf.nodeprof/js/analysis/forinof/minitests.forinof.js.expected index 994ebbd8..765175ad 100644 --- a/src/ch.usi.inf.nodeprof/js/analysis/forinof/minitests.forinof.js.expected +++ b/src/ch.usi.inf.nodeprof/js/analysis/forinof/minitests.forinof.js.expected @@ -1,23 +1,39 @@ -write@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:1:66:4:2) obj -read@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:6:17:6:20) obj -forObject@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:6:1:7:2) true { x: 'valueX', y: 'valueY' } -iterationEnter@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:6:1:7:2) -write@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:6:1:7:2) key -iterationExit@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:6:1:7:2) -iterationEnter@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:6:1:7:2) -write@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:6:1:7:2) key -iterationExit@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:6:1:7:2) -forObjectPost@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:6:1:7:2) true -write@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:9:5:9:21) arr -read@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:17:11:20) arr -forObject@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) false [ 41, 42, 43 ] -iterationEnter@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) -write@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) val -iterationExit@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) -iterationEnter@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) -write@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) val -iterationExit@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) -iterationEnter@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) -write@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) val -iterationExit@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) -forObjectPost@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:11:1:12:2) false +cfRootEnter@(src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:22:1:23:2) ForInIteration +iteration obj: { x: 'valueX', y: 'valueY' } +cfRoot ForInIteration @ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:22:1:23:2) + \-cfBlock @ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:22:1:23:2) +cfRoot ForInIteration @ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:22:1:23:2) + \-cfBlock @ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:22:1:23:2) +cfRootExit@(src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:22:1:23:2) ForInIteration +cfRootEnter@(src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:27:1:28:2) ForOfIteration +iteration obj: [ 41, 42, 43 ] +cfRoot ForOfIteration @ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:27:1:28:2) + \-cfBlock @ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:27:1:28:2) +cfRoot ForOfIteration @ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:27:1:28:2) + \-cfBlock @ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:27:1:28:2) +cfRoot ForOfIteration @ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:27:1:28:2) + \-cfBlock @ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:27:1:28:2) +cfRootExit@(src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:27:1:28:2) ForOfIteration +functionEnter: [Symbol.iterator] / (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:35:3:48:4) / 4 +cfRootEnter@(src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:53:1:54:2) ForOfIteration +iteration obj: +read@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:39:13:39:26) moreToIterate +read@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:40:32:40:45) moreToIterate +read@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:40:53:40:58) itemA +write@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:40:17:40:86) ret +read@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:41:11:41:26) moreToIterate +write@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:41:11:41:26) moreToIterate +read@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:42:18:42:21) ret +cfRoot ForOfIteration @ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:53:1:54:2) + \-cfBlock @ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:53:1:54:2) +read@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:39:13:39:26) moreToIterate +read@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:40:32:40:45) moreToIterate +read@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:40:61:40:65) this +write@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:40:17:40:86) ret +read@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:41:11:41:26) moreToIterate +write@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:41:11:41:26) moreToIterate +read@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:42:18:42:21) ret +cfRoot ForOfIteration @ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:53:1:54:2) + \-cfBlock @ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:53:1:54:2) +read@ (src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:39:13:39:26) moreToIterate +cfRootExit@(src/ch.usi.inf.nodeprof.test/js/minitests/forinof.js:53:1:54:2) ForOfIteration diff --git a/src/ch.usi.inf.nodeprof/js/analysis/trivial/emptyTemplate.js b/src/ch.usi.inf.nodeprof/js/analysis/trivial/emptyTemplate.js index 1a9c7f1b..1c41bae7 100644 --- a/src/ch.usi.inf.nodeprof/js/analysis/trivial/emptyTemplate.js +++ b/src/ch.usi.inf.nodeprof/js/analysis/trivial/emptyTemplate.js @@ -165,15 +165,6 @@ this.declare = function (iid, name, type) { }; - /** - * forin or forof support - * the object being iterated can be known by checking the last expression's result (via endExpression) - **/ - this.forObject = function (iid, isForIn) { - } - this.forObjectPost = function (iid, isForIn) { - } - /** * This callback is called before a value is returned from a function using the return keyword. * @@ -201,13 +192,18 @@ this.awaitPost = function (iid, result, exceptionVal) { } + // TODO incubation stage + this.cfBlockEnter = function(iid, iidParent) { + }; + this.cfBlockExit = function(iid, iidParent) { + }; + this.cfRootEnter = function (iid, type) { + }; + this.cfRootExit = function (iid, type) { + }; } if(false) { - // replaced with forObject including support for forin and forof - this.forinObject = function (iid, val) { - }; - //not supported yet this._throw = function (iid, val) { }; diff --git a/src/ch.usi.inf.nodeprof/js/jalangi.js b/src/ch.usi.inf.nodeprof/js/jalangi.js index 6ab0fc20..b5fc6468 100644 --- a/src/ch.usi.inf.nodeprof/js/jalangi.js +++ b/src/ch.usi.inf.nodeprof/js/jalangi.js @@ -61,10 +61,16 @@ J$={}; sandbox.disableAnalysis = function() { return sandbox.adapter.instrumentationSwitch(false); } - }catch (e){ + } catch (e){ console.log("cannot load nodeprof jalangi adapter"); } + sandbox.cf = { + FOR_IN: "ForInIteration", + FOR_OF: "ForOfIteration", + IF: "Conditional" + } + sandbox.analyses=[]; sandbox.enabledCBs = []; if(process.env.ENABLED_JALANGI_CBS && process.env.ENABLED_JALANGI_CBS.length > 0){ diff --git a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/handlers/CFBlockEventHandler.java b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/handlers/CFBlockEventHandler.java index 85b1a392..848e496e 100644 --- a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/handlers/CFBlockEventHandler.java +++ b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/handlers/CFBlockEventHandler.java @@ -15,12 +15,25 @@ *******************************************************************************/ package ch.usi.inf.nodeprof.handlers; +import ch.usi.inf.nodeprof.utils.NodeProfUtil; +import ch.usi.inf.nodeprof.utils.SourceMapping; import com.oracle.truffle.api.instrumentation.EventContext; import ch.usi.inf.nodeprof.ProfiledTagEnum; +import com.oracle.truffle.js.nodes.JavaScriptNode; +import com.oracle.truffle.js.nodes.instrumentation.JSTags; public abstract class CFBlockEventHandler extends BaseSingleTagEventHandler { + private final int parentIID; + public CFBlockEventHandler(EventContext context) { super(context, ProfiledTagEnum.CF_BLOCK); + JavaScriptNode parent = (JavaScriptNode) NodeProfUtil.getParentSkipWrappers(context.getInstrumentedNode()); + assert parent.hasTag(JSTags.ControlFlowRootTag.class); + this.parentIID = SourceMapping.getIIDForSourceSection(parent.getSourceSection()); + } + + public int getParentIID() { + return parentIID; } } diff --git a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/handlers/CFRootEventHandler.java b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/handlers/CFRootEventHandler.java index f7abb2dd..edd78d5b 100644 --- a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/handlers/CFRootEventHandler.java +++ b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/handlers/CFRootEventHandler.java @@ -1,5 +1,6 @@ /******************************************************************************* * Copyright 2018 Dynamic Analysis Group, Università della Svizzera Italiana (USI) + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,9 +17,9 @@ package ch.usi.inf.nodeprof.handlers; import com.oracle.truffle.api.instrumentation.EventContext; -import com.oracle.truffle.js.nodes.instrumentation.JSTags; import ch.usi.inf.nodeprof.ProfiledTagEnum; +import com.oracle.truffle.js.nodes.instrumentation.JSTags; public abstract class CFRootEventHandler extends BaseSingleTagEventHandler { @@ -29,6 +30,10 @@ public CFRootEventHandler(EventContext context) { this.type = (String) getAttribute("type"); } + public String getCFRootType() { + return type; + } + public boolean isAsyncRoot() { return this.type.equals(JSTags.ControlFlowRootTag.Type.AsyncFunction.name()); } diff --git a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/handlers/LoopEventHandler.java b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/handlers/LoopEventHandler.java deleted file mode 100644 index f835e52b..00000000 --- a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/handlers/LoopEventHandler.java +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * Copyright 2018 Dynamic Analysis Group, Università della Svizzera Italiana (USI) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package ch.usi.inf.nodeprof.handlers; - -import com.oracle.truffle.api.instrumentation.EventContext; -import com.oracle.truffle.js.nodes.instrumentation.JSTags; - -import ch.usi.inf.nodeprof.ProfiledTagEnum; - -/** - * Abstract event handler for loop events - */ -public abstract class LoopEventHandler extends BaseSingleTagEventHandler { - public LoopEventHandler(EventContext context) { - super(context, ProfiledTagEnum.CF_ROOT); - } - - public String getLoopType() { - return (String) getAttribute("type"); - } - - public boolean isForIn() { - return getLoopType().equals(JSTags.ControlFlowRootTag.Type.ForInIteration.name()); - } - - public boolean isForOf() { - return getLoopType().equals(JSTags.ControlFlowRootTag.Type.ForOfIteration.name()); - } -} diff --git a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/JalangiAnalysis.java b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/JalangiAnalysis.java index 9f1f8341..b00b9eb5 100644 --- a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/JalangiAnalysis.java +++ b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/JalangiAnalysis.java @@ -42,12 +42,11 @@ import ch.usi.inf.nodeprof.jalangi.factory.EvalFactory; import ch.usi.inf.nodeprof.jalangi.factory.EvalFunctionFactory; import ch.usi.inf.nodeprof.jalangi.factory.ExpressionFactory; -import ch.usi.inf.nodeprof.jalangi.factory.ForObjectFactory; import ch.usi.inf.nodeprof.jalangi.factory.GetElementFactory; import ch.usi.inf.nodeprof.jalangi.factory.GetFieldFactory; import ch.usi.inf.nodeprof.jalangi.factory.InvokeFactory; import ch.usi.inf.nodeprof.jalangi.factory.LiteralFactory; -import ch.usi.inf.nodeprof.jalangi.factory.LoopFactory; +import ch.usi.inf.nodeprof.jalangi.factory.CFRootFactory; import ch.usi.inf.nodeprof.jalangi.factory.PutElementFactory; import ch.usi.inf.nodeprof.jalangi.factory.PutFieldFactory; import ch.usi.inf.nodeprof.jalangi.factory.ReadFactory; @@ -125,19 +124,16 @@ public class JalangiAnalysis { put("asyncFunctionEnter", EnumSet.of(CF_ROOT)); put("asyncFunctionExit", EnumSet.of(CF_ROOT)); + put("awaitPre", EnumSet.of(CF_BRANCH)); + put("awaitPost", EnumSet.of(CF_BRANCH)); - put("forObject", EnumSet.of(CF_ROOT)); - put("forObjectPost", EnumSet.of(CF_ROOT)); - + put("cfRootEnter", EnumSet.of(CF_ROOT)); + put("cfRootExit", EnumSet.of(CF_ROOT)); put("cfBlockEnter", EnumSet.of(CF_BLOCK)); put("cfBlockExit", EnumSet.of(CF_BLOCK)); put("_return", EnumSet.of(CF_BRANCH)); - put("_return", EnumSet.of(CF_BRANCH)); - - put("awaitPre", EnumSet.of(CF_BRANCH)); - put("awaitPost", EnumSet.of(CF_BRANCH)); put("startExpression", EnumSet.of(EXPRESSION)); put("endExpression", EnumSet.of(EXPRESSION)); @@ -287,12 +283,6 @@ public void onReady() { new EvalFunctionFactory(this.jsAnalysis, callbacks.get("evalFunctionPre"), callbacks.get("evalFunctionPost"))); } - if (this.callbacks.containsKey("forObject") || this.callbacks.containsKey("forObjectPost")) { - this.instrument.onCallback( - ProfiledTagEnum.CF_ROOT, - new ForObjectFactory(this.jsAnalysis, callbacks.get("forObject"), callbacks.get("forObjectPost"))); - } - /** * async function */ @@ -311,17 +301,14 @@ public void onReady() { } /** - * Loop not tested + * Control flow roots (if, loops, etc.) and their related control flow blocks */ - if (this.callbacks.containsKey("loopEnter") || this.callbacks.containsKey("loopExit")) { + if (this.callbacks.containsKey("cfRootEnter") || this.callbacks.containsKey("cfRootExit")) { this.instrument.onCallback( ProfiledTagEnum.CF_ROOT, - new LoopFactory(this.jsAnalysis, callbacks.get("loopEnter"), callbacks.get("loopExit"))); + new CFRootFactory(this.jsAnalysis, callbacks.get("cfRootEnter"), callbacks.get("cfRootExit"))); } - /** - * cfBlockEnter, cfBlockExit - */ if (this.callbacks.containsKey("cfBlockEnter") || this.callbacks.containsKey("cfBlockExit")) { this.instrument.onCallback( ProfiledTagEnum.CF_BLOCK, diff --git a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/CFBlockFactory.java b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/CFBlockFactory.java index b7c445da..7b24cea8 100644 --- a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/CFBlockFactory.java +++ b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/CFBlockFactory.java @@ -25,7 +25,7 @@ public class CFBlockFactory extends AbstractFactory { public CFBlockFactory(Object jalangiAnalysis, DynamicObject pre, DynamicObject post) { - super("cfblock", jalangiAnalysis, pre, post, 1, 1); + super("cfblock", jalangiAnalysis, pre, post, 2, 2); } @Override @@ -38,8 +38,7 @@ public BaseEventHandlerNode create(EventContext context) { public void executePre(VirtualFrame frame, Object[] inputs) { if (pre != null) { setPreArguments(0, getSourceIID()); - // TODO - // add information about the type of the block (if, iteration, switch) + setPreArguments(1, getParentIID()); directCall(preCall, true, getSourceIID()); } } @@ -49,8 +48,7 @@ public void executePost(VirtualFrame frame, Object result, Object[] inputs) { if (post != null) { setPostArguments(0, getSourceIID()); - // TODO - // add information about the type of the block (if, iteration, switch) + setPostArguments(1, getParentIID()); directCall(postCall, false, getSourceIID()); } } diff --git a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/LoopFactory.java b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/CFRootFactory.java similarity index 82% rename from src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/LoopFactory.java rename to src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/CFRootFactory.java index ae175bad..016beed9 100644 --- a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/LoopFactory.java +++ b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/CFRootFactory.java @@ -21,16 +21,16 @@ import com.oracle.truffle.api.object.DynamicObject; import ch.usi.inf.nodeprof.handlers.BaseEventHandlerNode; -import ch.usi.inf.nodeprof.handlers.LoopEventHandler; +import ch.usi.inf.nodeprof.handlers.CFRootEventHandler; -public class LoopFactory extends AbstractFactory { - public LoopFactory(Object jalangiAnalysis, DynamicObject pre, DynamicObject post) { - super("loop", jalangiAnalysis, pre, post, 2, 2); +public class CFRootFactory extends AbstractFactory { + public CFRootFactory(Object jalangiAnalysis, DynamicObject pre, DynamicObject post) { + super("cfroot", jalangiAnalysis, pre, post, 2, 2); } @Override public BaseEventHandlerNode create(EventContext context) { - return new LoopEventHandler(context) { + return new CFRootEventHandler(context) { @Child DirectCallNode preCall = createPreCallNode(); @Child DirectCallNode postCall = createPostCallNode(); @@ -38,7 +38,7 @@ public BaseEventHandlerNode create(EventContext context) { public void executePre(VirtualFrame frame, Object[] inputs) { if (pre != null) { setPreArguments(0, getSourceIID()); - setPreArguments(1, getLoopType()); + setPreArguments(1, getCFRootType()); directCall(preCall, true, getSourceIID()); } } @@ -47,9 +47,8 @@ public void executePre(VirtualFrame frame, Object[] inputs) { public void executePost(VirtualFrame frame, Object result, Object[] inputs) { if (post != null) { - setPostArguments(0, getSourceIID()); - setPostArguments(1, getLoopType()); + setPostArguments(1, getCFRootType()); directCall(postCall, false, getSourceIID()); } } diff --git a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/ForObjectFactory.java b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/ForObjectFactory.java deleted file mode 100644 index 2c5775d6..00000000 --- a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/jalangi/factory/ForObjectFactory.java +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * Copyright 2018 Dynamic Analysis Group, Università della Svizzera Italiana (USI) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ -package ch.usi.inf.nodeprof.jalangi.factory; - -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.instrumentation.EventContext; -import com.oracle.truffle.api.nodes.DirectCallNode; -import com.oracle.truffle.api.object.DynamicObject; - -import ch.usi.inf.nodeprof.handlers.BaseEventHandlerNode; -import ch.usi.inf.nodeprof.handlers.LoopEventHandler; - -public class ForObjectFactory extends AbstractFactory { - public ForObjectFactory(Object jalangiAnalysis, DynamicObject pre, DynamicObject post) { - super("forObject", jalangiAnalysis, pre, post, 2, 2); - } - - @Override - public BaseEventHandlerNode create(EventContext context) { - return new LoopEventHandler(context) { - @Child DirectCallNode preCall = createPreCallNode(); - @Child DirectCallNode postCall = createPostCallNode(); - - @Override - public void executePre(VirtualFrame frame, - Object[] inputs) { - if (pre != null && (isForIn() || isForOf())) { - setPreArguments(0, getSourceIID()); - setPreArguments(1, isForIn()); - directCall(preCall, true, getSourceIID()); - } - } - - @Override - public void executePost(VirtualFrame frame, Object result, Object[] inputs) { - if (post != null && (isForIn() || isForOf())) { - setPostArguments(0, getSourceIID()); - setPostArguments(1, isForIn()); - directCall(postCall, true, getSourceIID()); - } - - } - }; - } - -} diff --git a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/utils/NodeProfUtil.java b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/utils/NodeProfUtil.java new file mode 100644 index 00000000..e0566d4f --- /dev/null +++ b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/utils/NodeProfUtil.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ +package ch.usi.inf.nodeprof.utils; + +import com.oracle.truffle.api.instrumentation.InstrumentableNode; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.js.nodes.access.GlobalScopeVarWrapperNode; +import com.oracle.truffle.js.nodes.instrumentation.JSInputGeneratingNodeWrapper; +import com.oracle.truffle.js.nodes.instrumentation.JSTaggedExecutionNode; + +public class NodeProfUtil { + public static Node getParentSkipWrappers(Node n) { + assert n != null; + Node parent = n.getParent(); + while (parent != null && (isWrapperNode(parent) || parent.getSourceSection() == null)) { + parent = parent.getParent(); + } + return parent; + } + + public static boolean isWrapperNode(Node n) { + return n instanceof JSInputGeneratingNodeWrapper || n instanceof InstrumentableNode.WrapperNode || + n instanceof GlobalScopeVarWrapperNode || n instanceof JSTaggedExecutionNode; + } +} From 31b601076a0d421b051bef7d87c2a2d9f3b6ddcc Mon Sep 17 00:00:00 2001 From: Alexander Jordan Date: Wed, 2 Oct 2019 23:51:10 +1000 Subject: [PATCH 3/3] Add GeneratorWrapperNode to isWrapper() --- .../src/ch/usi/inf/nodeprof/utils/NodeProfUtil.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/utils/NodeProfUtil.java b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/utils/NodeProfUtil.java index e0566d4f..40ef380c 100644 --- a/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/utils/NodeProfUtil.java +++ b/src/ch.usi.inf.nodeprof/src/ch/usi/inf/nodeprof/utils/NodeProfUtil.java @@ -18,6 +18,7 @@ import com.oracle.truffle.api.instrumentation.InstrumentableNode; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.js.nodes.access.GlobalScopeVarWrapperNode; +import com.oracle.truffle.js.nodes.control.GeneratorWrapperNode; import com.oracle.truffle.js.nodes.instrumentation.JSInputGeneratingNodeWrapper; import com.oracle.truffle.js.nodes.instrumentation.JSTaggedExecutionNode; @@ -32,7 +33,8 @@ public static Node getParentSkipWrappers(Node n) { } public static boolean isWrapperNode(Node n) { - return n instanceof JSInputGeneratingNodeWrapper || n instanceof InstrumentableNode.WrapperNode || - n instanceof GlobalScopeVarWrapperNode || n instanceof JSTaggedExecutionNode; + return n instanceof InstrumentableNode.WrapperNode || n instanceof JSInputGeneratingNodeWrapper || + n instanceof GlobalScopeVarWrapperNode || n instanceof JSTaggedExecutionNode || + n instanceof GeneratorWrapperNode; } }