Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How IonMonkey analyze javascript codes which type from console.

97 views
Skip to first unread message

井関正也

unread,
Apr 1, 2013, 10:32:28 AM4/1/13
to
I'm interested in IonMonkey.
I read some code in js/src/ion.But I can't understand how IonMonkey analyze the code.
When type javascript code in console or commnad line , What function call firstly?

Nicolas B. Pierron

unread,
Apr 1, 2013, 3:40:42 PM4/1/13
to
Hi,
I don't know how the js-shell command line is feeding commands into
IonMonkey, but IonMonkey check if it can be used for compilation in

js::ion::CanEnter
js::ion::CanEnterAtBranch (for OSR)

Then compiles the bytecode to assembly under

IonCompile<SequentialCompileContext>
CompileBackEnd (potentially called from a separated thread)
js::ion::CodeGenerator::link

And the produced assembly is then executed under

EnterIon
callers of js::mjit::Compiler::ionCompileHelper (from JäegerMonkey
generated code)


--
Nicolas B. Pierron

井関正也

unread,
Apr 2, 2013, 9:56:00 PM4/2/13
to
Thanks Nicolas.

> I don't know how the js-shell command line is feeding commands into
>
> IonMonkey, but IonMonkey check if it can be used for compilation in
>
> js::ion::CanEnter
>
> js::ion::CanEnterAtBranch (for OSR)
>
I found main function which locate js/src/shell/js.cpp:5103.
It call Shell(JSContext *cx, OptionParser *op, char **envp).
I understand function flow.
----
int main(int argc, char **argv, char **envp)

int
Shell(JSContext *cx, OptionParser *op, char **envp)

static int
ProcessArgs(JSContext *cx, JSObject *obj_, OptionParser *op)

static void
Process(JSContext *cx, JSObject *obj_, const char *filename, bool forceTTY)

JS_NEVER_INLINE JS_PUBLIC_API(JSBool)
JS_ExecuteScript(JSContext *cx, JSObject *objArg, JSScript *scriptArg, jsval *rval)
in js/src/jsapi.cpp

bool
js::Execute(JSContext *cx, HandleScript script, JSObject &scopeChainArg, Value *rval)
in js/src/jsinterp

bool
js::ExecuteKernel(JSContext *cx, HandleScript script, JSObject &scopeChainArg, const Value &thisv,
ExecuteType type, AbstractFramePtr evalInFrame, Value *result)

bool
js::RunScript(JSContext *cx, StackFrame *fp)

JS_NEVER_INLINE InterpretStatus
js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode)
---

Last call function execute js-operation such as add or sub.
I found js::ion::CanEnter in js::RunScript.

I can't understand how call foldsTo function in js/src/ion/MIR.cpp.
I'd like to know how call foldsTo function from js::ion::CanEnter to fix this bug(https://bugzilla.mozilla.org/show_bug.cgi?id=852791)
--
Masaya Iseki

Péricles Alves

unread,
Apr 2, 2013, 11:03:53 PM4/2/13
to 井関正也, dev-tech-js-en...@lists.mozilla.org
>
> I can't understand how call foldsTo function in js/src/ion/MIR.cpp.
> I'd like to know how call foldsTo function from js::ion::CanEnter to fix
> this bug(https://bugzilla.mozilla.org/show_bug.cgi?id=852791)
>

The *foldsTo* method can only be called on MDefinitions, which are
instructions in the program being executed. These instructions are in the
program graph (MIRGraph). The problem is that at *CanEnter* you don't have
the program graph (at *CanEnter* you are only asking IonMonkey if he can
compile a function. The compilation process actually starts when you call *
Cannon* or *SideCannon*, which are called near *CanEnter*).

A good place to call *foldsTo* would be at the *OptimizeMIR* function in
Ion.cpp, where you have the program graph. There is the place where Ion
actually optimizes the program.

The following simple example iterates over the instructions in the program
graph calling *foldsTo* on every instruction.

*for (MBasicBlockIterator block(graph.begin()); block != graph.end();
block++) {
for (MInstructionIterator i = block->begin(); i != block->end(); i++) {
*
* MInstruction *ins = *i;
MDefinition *result = ins->foldsTo(false);
}
*
*}
*
The variable *result* in the loop body will have the simplified
instruction, if it was possible to simplify it. Then you can use methods
like *replaceWithInstruction* to insert the simplified instruction back in
the graph.

In doubt, copy one of the compiler passes like LICM and try to modify the
code :)


Hope it helps,

--
Pericles Alves

井関正也

unread,
Apr 3, 2013, 8:41:53 AM4/3/13
to
2013年4月1日月曜日 23時32分28秒 UTC+9 井関正也:
> I'm interested in IonMonkey.
>
> I read some code in js/src/ion.But I can't understand how IonMonkey analyze the code.
>
> When type javascript code in console or commnad line , What function call firstly?

Thanks Pericles.

I found ion::CanEnter and ion::Cannon near js/src/jsinterp.cpp:314.
When I type
* var x = "hoge" + s + "fuga";*
ion::CanEnter return Method_Skipped. (s is pre-declared)

I trace ion::CanEnter.

*MethodStatus
*ion::CanEnter(JSContext *cx, JSScript *script, AbstractFramePtr fp, bool isConstructing)

*template <typename CompileContext>
*static MethodStatus
*Compile(JSContext *cx, HandleScript script, HandleFunction fun, jsbytecode *osrPc, bool constructing,
* CompileContext &compileContext)

*if (script->getUseCount() < js_IonOptions.usesBeforeCompile){
* return Method_Skipped;

ion::CanEnter have to return Method_Compiled to call *OptimizeMIR*.
Why ion::CanEnter return Method_Compiled?
I can't execute ion::Cannon from Shell?

Please tell me.

Péricles Alves

unread,
Apr 3, 2013, 9:59:15 AM4/3/13
to 井関正也, dev-tech-js-en...@lists.mozilla.org
Maybe it is returning Method_Skipped because your test is too small or your
script isn't "hot" yet. Ion will compile functions, for instance, when they
iterate *usesBeforeCompile* times (which is currently 1000). You could use
eager mode (--ion-eager --baseline-eager), but that doesn't help if your
test case is too small. So, to get Ion to compile your script, make sure
that it has a loop that iterates at least 1000 times, like the one below.

for (var i = 0; i < 1000; i ++) {
var x = "hoge" + s + "fuga";
}

In this case, *CanEnter* and *CanEnterAtBranch* will keep returning
Method_Skipped a lot of times, but when the script gets near 1000
iterations, it will compile your test case and return Method_Compiled.
> _______________________________________________
> dev-tech-js-engine-internals mailing list
> dev-tech-js-en...@lists.mozilla.org
> https://lists.mozilla.org/listinfo/dev-tech-js-engine-internals
>



--
Pericles Alves

井関正也

unread,
Apr 4, 2013, 6:10:39 AM4/4/13
to 井関正也, dev-tech-js-en...@lists.mozilla.org
Thanks Pericles.

I know how to call foldsTo function thanks to Pericles and Nicolas.

I'd like to use iongraph(https://github.com/sstangl/iongraph) to analyze MIRGraph.
But when I type 'make' in this file,
./genpngs: line 10: dot: command not found
is diplayed.

I install gnu parallel.
what is dot command?

井関正也

unread,
Apr 4, 2013, 6:10:39 AM4/4/13
to mozilla.dev.tech.j...@googlegroups.com, 井関正也, dev-tech-js-en...@lists.mozilla.org

Péricles Alves

unread,
Apr 4, 2013, 7:27:17 AM4/4/13
to 井関正也, mozilla.dev.tech.j...@googlegroups.com, dev-tech-js-en...@lists.mozilla.org
Dot is the tool used to draw directed graphs. It comes when you install
Graphviz (http://www.graphviz.org/Download_linux_ubuntu.php).
> _______________________________________________
> dev-tech-js-engine-internals mailing list
> dev-tech-js-en...@lists.mozilla.org
> https://lists.mozilla.org/listinfo/dev-tech-js-engine-internals
>



--
Péricles <http://dcc.ufmg.br/%7Epericlesrafael>

井関正也

unread,
Apr 4, 2013, 8:47:48 AM4/4/13
to 井関正也, dev-tech-js-en...@lists.mozilla.org
Now, I understand how to call foldsTo function.

But I can't still fix this bug(https://bugzilla.mozilla.org/show_bug.cgi?id=852791)
When I type:
var s = "hoge" + x + "fuga"
,ValueNumberer::simplify or ValueNumberer::simplifyControlInstruction always call MDefinition::foldsTo(bool useValueNumbers).

I predict MStringLength::foldsTo is called when string constants is folded.
But MStringLength::foldsTo isn't call.

What function call when string constants is folded.

井関正也

unread,
Apr 4, 2013, 8:47:48 AM4/4/13
to mozilla.dev.tech.j...@googlegroups.com, 井関正也, dev-tech-js-en...@lists.mozilla.org

Péricles Alves

unread,
Apr 4, 2013, 10:13:23 AM4/4/13
to 井関正也, dev-tech-js-en...@lists.mozilla.org
Well, MStringLength::foldsTo won't be called unless you have a constant
string and you are explicitly using the length property of this string
somewhere in the code. Ex: *var s ="some str"; var l = s.length;*

The bug report is actually asking to simplify concatenation of constant
strings. In fact, your test case (*var s = "hoge" + x + "fuga";*) is not a
target for this bug, since you don't know nothing about *x* at compile time.

If you use iongraph to produce the code for the test case in the bug report
(*var s = "f" + "oo" + x + "b" + "ar";*), at some point you will see a
instruction like "concat constant constant". Since the operands are both
constants, you can simplify this instruction at compile time to a simple
"constant string", resulting from the concatenation of the two constant
operands. As the report says, to do so, you need to write a new
*foldsTo*method for the MConcat class to handle this simplification.
The
*foldsTo* method of the MStringLength class is a good base example.

井関正也

unread,
Apr 4, 2013, 2:51:46 PM4/4/13
to
2013年4月1日月曜日 23時32分28秒 UTC+9 井関正也:
> I'm interested in IonMonkey.
>
> I read some code in js/src/ion.But I can't understand how IonMonkey analyze the code.
>
> When type javascript code in console or commnad line , What function call firstly?

Oh ! I understand.
Thanks.

I make member function
MDefinition *
MConcat::foldsTo(bool useValueNumbers)
{
if ((type() == MIRType_String) && (rhs()->isConstant()))
{
if((type() == MIRType_String) && (lhs()->isConstant()))
{
return MConstant::New(MergeStrValue);
}
else
{
return MConstant::New(rhs()->toConstant()->value());
}
}
return this;
}
I'd like to merger JSString. I think I use js::ConcatStrings. But It doesn't have JSContext in this scope.
there are other way?

Nicolas B. Pierron

unread,
Apr 4, 2013, 5:01:15 PM4/4/13
to
Hi Masaya,

I'll suggest continuing this discussion on the bug. As bugzilla is made for
such discussion, and is better than mailing list for this purpose.
Hum …

the JSContext* has not been added here because this code can run in a
parallel thread when we are compiling, and we should not add a JSContext here.

The only case where we can allocate these GC object (new strings) is in the
link phase. So we need to store create a new MConstant MIR node which wrap
a buffer containing the content of the new string which would be allocated
in the link phase (CodeGenerator::link).

To do that you will have to add an index into the CodeGeneratorShared class
which will refer to locations which have to be patched during the link
phase, such as the constant index in the constant pool (see
CodeGeneratorShared::encodeSlots) can be updated after we have completed the
construction of the assembly.

tl;dr:
- Create a new type similar to MConstant. (MIR.h, MOpcode.h)
- Add it to the lowering. (LIR-Common.h & Lowering.cpp & LOpcode.h)
- Add a CodeGenerator function for it. (CodeGenerator.cpp)
- Allocate a slot in the snapshot for this new MIR type.
(CodeGeneratorShared::encodeSlots)
- Iterate on the vector of patch offset to allocate the new strings
(CodeGenerator::link)

--
Nicolas B. Pierron

井関正也

unread,
Apr 4, 2013, 10:51:31 PM4/4/13
to
>I'll suggest continuing this discussion on the bug. As bugzilla is made for
>such discussion, and is better than mailing list for this purpose.

I'm sorry.
In the future, I will post in bugzilla.
0 new messages