private void EmitRegExpInit(ClassFileWriter cfw) { // precompile all regexp literals int totalRegCount = 0; for (int i = 0; i != scriptOrFnNodes.Length; ++i) { totalRegCount += scriptOrFnNodes[i].GetRegexpCount(); } if (totalRegCount == 0) { return; } cfw.StartMethod(REGEXP_INIT_METHOD_NAME, REGEXP_INIT_METHOD_SIGNATURE, (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE)); cfw.AddField("_reInitDone", "Z", (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE | ClassFileWriter.ACC_VOLATILE)); cfw.Add(ByteCode.GETSTATIC, mainClassName, "_reInitDone", "Z"); int doInit = cfw.AcquireLabel(); cfw.Add(ByteCode.IFEQ, doInit); cfw.Add(ByteCode.RETURN); cfw.MarkLabel(doInit); // get regexp proxy and store it in local slot 1 cfw.AddALoad(0); // context cfw.AddInvoke(ByteCode.INVOKESTATIC, "org/mozilla/javascript/ScriptRuntime", "checkRegExpProxy", "(Lorg/mozilla/javascript/Context;" + ")Lorg/mozilla/javascript/RegExpProxy;"); cfw.AddAStore(1); // proxy // We could apply double-checked locking here but concurrency // shouldn't be a problem in practice for (int i_1 = 0; i_1 != scriptOrFnNodes.Length; ++i_1) { ScriptNode n = scriptOrFnNodes[i_1]; int regCount = n.GetRegexpCount(); for (int j = 0; j != regCount; ++j) { string reFieldName = GetCompiledRegexpName(n, j); string reFieldType = "Ljava/lang/Object;"; string reString = n.GetRegexpString(j); string reFlags = n.GetRegexpFlags(j); cfw.AddField(reFieldName, reFieldType, (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE)); cfw.AddALoad(1); // proxy cfw.AddALoad(0); // context cfw.AddPush(reString); if (reFlags == null) { cfw.Add(ByteCode.ACONST_NULL); } else { cfw.AddPush(reFlags); } cfw.AddInvoke(ByteCode.INVOKEINTERFACE, "org/mozilla/javascript/RegExpProxy", "compileRegExp", "(Lorg/mozilla/javascript/Context;" + "Ljava/lang/String;Ljava/lang/String;" + ")Ljava/lang/Object;"); cfw.Add(ByteCode.PUTSTATIC, mainClassName, reFieldName, reFieldType); } } cfw.AddPush(1); cfw.Add(ByteCode.PUTSTATIC, mainClassName, "_reInitDone", "Z"); cfw.Add(ByteCode.RETURN); cfw.StopMethod((short)2); }
private void EmitDirectConstructor(ClassFileWriter cfw, OptFunctionNode ofn) { cfw.StartMethod(GetDirectCtorName(ofn.fnode), GetBodyMethodSignature(ofn.fnode), (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE)); int argCount = ofn.fnode.GetParamCount(); int firstLocal = (4 + argCount * 3) + 1; cfw.AddALoad(0); // this cfw.AddALoad(1); // cx cfw.AddALoad(2); // scope cfw.AddInvoke(ByteCode.INVOKEVIRTUAL, "org/mozilla/javascript/BaseFunction", "createObject", "(Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + ")Lorg/mozilla/javascript/Scriptable;"); cfw.AddAStore(firstLocal); cfw.AddALoad(0); cfw.AddALoad(1); cfw.AddALoad(2); cfw.AddALoad(firstLocal); for (int i = 0; i < argCount; i++) { cfw.AddALoad(4 + (i * 3)); cfw.AddDLoad(5 + (i * 3)); } cfw.AddALoad(4 + argCount * 3); cfw.AddInvoke(ByteCode.INVOKESTATIC, mainClassName, GetBodyMethodName(ofn.fnode), GetBodyMethodSignature(ofn.fnode)); int exitLabel = cfw.AcquireLabel(); cfw.Add(ByteCode.DUP); // make a copy of direct call result cfw.Add(ByteCode.INSTANCEOF, "org/mozilla/javascript/Scriptable"); cfw.Add(ByteCode.IFEQ, exitLabel); // cast direct call result cfw.Add(ByteCode.CHECKCAST, "org/mozilla/javascript/Scriptable"); cfw.Add(ByteCode.ARETURN); cfw.MarkLabel(exitLabel); cfw.AddALoad(firstLocal); cfw.Add(ByteCode.ARETURN); cfw.StopMethod((short)(firstLocal + 1)); }