Oh, Hi Ben. Thanks for the tip. I have tried ScopeInfo::CopyContextLocalsToScopeObject but it doesn't help. As far as I can see it is only better way of doing the "Add context containing declarations" part.
Now knowing about ScopeInfo::CopyContextLocalsToScopeObject, I see now that I should be using the MaterializeLocalScope convenience function. But unfortunately this did not help either. *Update patch attached. Same error.* Den lørdag den 30. august 2014 17.16.44 UTC+2 skrev Ben Noordhuis: > > On Sat, Aug 30, 2014 at 1:51 PM, Andreas Madsen <[email protected] > <javascript:>> wrote: > > I'm trying to suggest a change for v8 there will extend the frame > objects > > there can be obtained using Error.prepareStackTrace, so they also have > > a getFunctionArguments and a getFunctionVariabels method. As this is > > quite useful for understanding the cause of runtime errors. > > > > See attachment for .patch file. > > > > However there is an issue in the added test. The error is caused by the > > optimization of the test function. I have tried to solve it using the > > FrameInspector but without luck. I hope someone kind can help me solve > > the issue. > > The error output can be seen below. > > > > ======================================================== > > ./d8 --allow-natives-syntax test/mjsunit/mjsunit.js > > test/mjsunit/local-variabels.js > > > > ["param_def","param_undef","inner","locals"] > > ["outer","deep"] > > ["param_def","param_undef","inner","locals"] > > ["outer","deep"] > > ["param_def","param_undef","inner","locals"] > > ["outer","deep"] > > test/mjsunit/mjsunit.js:178: Failure: expected <"outer-scope"> found > > <undefined> > > throw new MjsUnitAssertionError(message); > > ^ > > Error > > at new MjsUnitAssertionError (test/mjsunit/mjsunit.js:31:16) > > at fail (test/mjsunit/mjsunit.js:178:11) > > at assertEquals (test/mjsunit/mjsunit.js:259:7) > > at deep (test/mjsunit/local-variabels.js:51:39) > > at test (test/mjsunit/local-variabels.js:54:3) > > at test/mjsunit/local-variabels.js:60:1 > > ======================================================== > > > > ======================================================== > > ./d8 --turbo-filter="*" --allow-natives-syntax test/mjsunit/mjsunit.js > > test/mjsunit/local-variabels.js > > ["param_def","param_undef","inner","locals"] > > ["outer","deep"] > > ["param_def","param_undef","inner","locals"] > > ["outer","deep"] > > ["param_def","param_undef","inner","locals"] > > > > \# > > \# Fatal error in ../src/deoptimizer.cc, line 151 > > \# CHECK_NE(deoptimization_index, Safepoint::kNoDeoptimizationIndex) > failed > > \# Value: 268435455 > > \# > > > > ==== C stack trace =============================== > > > > 1: ?? > > 2: ?? > > 3: ?? > > 4: ?? > > ======================================================== > > Hi Andreas, I didn't test it but, looking at the patch, I think > ScopeInfo::CopyContextLocalsToScopeObject() with |locals| as the > target should get you access to |outer|. > -- -- v8-users mailing list [email protected] http://groups.google.com/group/v8-users --- You received this message because you are subscribed to the Google Groups "v8-users" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
>From a922dca16686c8446a1f8e06501c294a7ff3f9fc Mon Sep 17 00:00:00 2001 From: Andreas Madsen <[email protected]> Date: Tue, 26 Aug 2014 21:49:55 +0200 Subject: [PATCH] Extend frame object to include variabel info The frame objects there can be obtained using Error.prepareStackTrace, now also have a getFunctionArguments and a getFunctionVariabels method. This is useful for understanding the cause of runtime errors. --- src/messages.js | 10 +++++ src/runtime.cc | 42 +++++++++++++++++++++ src/runtime.h | 1 + test/mjsunit/local-variabels.js | 60 ++++++++++++++++++++++++++++++ test/mjsunit/runtime-gen/localvariabels.js | 6 +++ tools/generate-runtime-tests.py | 6 +-- 6 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 test/mjsunit/local-variabels.js create mode 100644 test/mjsunit/runtime-gen/localvariabels.js diff --git a/src/messages.js b/src/messages.js index c86c12d..3559793 100644 --- a/src/messages.js +++ b/src/messages.js @@ -801,6 +801,14 @@ function CallSiteGetFunction() { ? UNDEFINED : GET_PRIVATE(this, CallSiteFunctionKey); } +function CallSiteGetFunctionArguments() { + return GET_PRIVATE(this, CallSiteFunctionKey).arguments; +} + +function CallSiteGetFunctionVariables() { + return %LocalVariabels(GET_PRIVATE(this, CallSiteFunctionKey)); +} + function CallSiteGetFunctionName() { // See if the function knows its own name var name = GET_PRIVATE(this, CallSiteFunctionKey).name; @@ -973,6 +981,8 @@ SetUpLockedPrototype(CallSite, $Array("receiver", "fun", "pos"), $Array( "getEvalOrigin", CallSiteGetEvalOrigin, "getScriptNameOrSourceURL", CallSiteGetScriptNameOrSourceURL, "getFunction", CallSiteGetFunction, + "getFunctionVariabels", CallSiteGetFunctionVariables, + "getFunctionArguments", CallSiteGetFunctionArguments, "getFunctionName", CallSiteGetFunctionName, "getMethodName", CallSiteGetMethodName, "getFileName", CallSiteGetFileName, diff --git a/src/runtime.cc b/src/runtime.cc index c69882f..d554207 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -14559,6 +14559,48 @@ RUNTIME_FUNCTION(Runtime_GetScript) { } +// Advances the iterator to the frame that matches the fuction and returns the +// inlined frame index, or -1 if not found. +static int FindJSFrameIndexFromFunction(JavaScriptFrameIterator* it, + JSFunction* function) { + for (; !it->done(); it->Advance()) { + List<FrameSummary> frames(FLAG_max_inlining_levels + 1); + it->frame()->Summarize(&frames); + for (int i = frames.length() - 1; i >= 0; i--) { + if (*frames[i].function().location() == function) return i; + } + } + return -1; +} + + +// Get variabels in this function scope +RUNTIME_FUNCTION(Runtime_LocalVariabels) { + HandleScope scope(isolate); + + DCHECK(args.length() == 1); + CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); + + // Function must be in script + if (!function->shared()->script()->IsScript()) { + return isolate->heap()->null_value(); + } + + // Search the frames for a function match and create a frame inspector + JavaScriptFrameIterator it(isolate); + int inlined_jsframe_index = + FindJSFrameIndexFromFunction(&it, *function.location()); + if (inlined_jsframe_index == -1) { + // function is not in active scope, stop here + return isolate->heap()->null_value(); + } + + Handle<Object> locals; + MaterializeLocalScope(isolate, it.frame(), inlined_jsframe_index).ToHandle(&locals); + return *locals.location(); +} + + // Collect the raw data for a stack trace. Returns an array of 4 // element segments each containing a receiver, function, code and // native code offset. diff --git a/src/runtime.h b/src/runtime.h index ef42b52..519747e 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -207,6 +207,7 @@ namespace internal { F(FunctionIsAPIFunction, 1, 1) \ F(FunctionIsBuiltin, 1, 1) \ F(GetScript, 1, 1) \ + F(LocalVariabels, 1, 1) \ F(CollectStackTrace, 2, 1) \ F(GetV8Version, 0, 1) \ \ diff --git a/test/mjsunit/local-variabels.js b/test/mjsunit/local-variabels.js new file mode 100644 index 0000000..3ef7074 --- /dev/null +++ b/test/mjsunit/local-variabels.js @@ -0,0 +1,60 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --allow-natives-syntax + +function hidden() { } + +function test() { + var outer = "outer-scope"; + + function deep(param_def, param_undef) { + var inner = "inner-scope"; + var locals; + + locals = %LocalVariabels(deep); + print(JSON.stringify(Object.keys(locals))); + assertEquals(4, Object.keys(locals).length); + assertEquals("inner-scope", locals.inner); + assertEquals("parameter", locals.param_def); + assertEquals(undefined, locals.param_undef); + assertEquals(undefined, locals.locals); + + locals = %LocalVariabels(test); + print(JSON.stringify(Object.keys(locals))); + assertEquals(2, Object.keys(locals).length); + assertEquals(deep, locals.deep); + assertEquals("outer-scope", locals.outer); + } + + deep("parameter"); +} + +test(); +test(); +%OptimizeFunctionOnNextCall(test); +test(); diff --git a/test/mjsunit/runtime-gen/localvariabels.js b/test/mjsunit/runtime-gen/localvariabels.js new file mode 100644 index 0000000..d8247e0 --- /dev/null +++ b/test/mjsunit/runtime-gen/localvariabels.js @@ -0,0 +1,6 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY +// Flags: --allow-natives-syntax --harmony --harmony-proxies +var _locals = new Object(); +var _function = function() {}; +%LocalVariabels(_locals, _function); diff --git a/tools/generate-runtime-tests.py b/tools/generate-runtime-tests.py index 50970b4..d4a45d0 100755 --- a/tools/generate-runtime-tests.py +++ b/tools/generate-runtime-tests.py @@ -47,11 +47,11 @@ EXPAND_MACROS = [ # that the parser doesn't bit-rot. Change the values as needed when you add, # remove or change runtime functions, but make sure we don't lose our ability # to parse them! -EXPECTED_FUNCTION_COUNT = 431 -EXPECTED_FUZZABLE_COUNT = 332 +EXPECTED_FUNCTION_COUNT = 432 +EXPECTED_FUZZABLE_COUNT = 333 EXPECTED_CCTEST_COUNT = 7 EXPECTED_UNKNOWN_COUNT = 17 -EXPECTED_BUILTINS_COUNT = 808 +EXPECTED_BUILTINS_COUNT = 810 # Don't call these at all. -- 2.0.4
