diff --git a/build/automation.py.in b/build/automation.py.in index ce62bf764e02..121461502c58 100644 --- a/build/automation.py.in +++ b/build/automation.py.in @@ -351,6 +351,7 @@ user_pref("layout.debug.enable_data_xbl", true); user_pref("browser.EULA.override", true); user_pref("javascript.options.tracejit.content", true); user_pref("javascript.options.methodjit.content", true); +user_pref("javascript.options.jitprofiling.content", true); user_pref("gfx.color_management.force_srgb", true); user_pref("network.manage-offline-status", false); user_pref("test.mousescroll", true); diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 49cb905f5731..9b262b88ab8b 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -1197,6 +1197,8 @@ static const char js_tracejit_content_str[] = JS_OPTIONS_DOT_STR "tracejit.con static const char js_tracejit_chrome_str[] = JS_OPTIONS_DOT_STR "tracejit.chrome"; static const char js_methodjit_content_str[] = JS_OPTIONS_DOT_STR "methodjit.content"; static const char js_methodjit_chrome_str[] = JS_OPTIONS_DOT_STR "methodjit.chrome"; +static const char js_profiling_content_str[] = JS_OPTIONS_DOT_STR "jitprofiling.content"; +static const char js_profiling_chrome_str[] = JS_OPTIONS_DOT_STR "jitprofiling.chrome"; int nsJSContext::JSOptionChangedCallback(const char *pref, void *data) @@ -1222,6 +1224,9 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data) PRBool useMethodJIT = nsContentUtils::GetBoolPref(chromeWindow ? js_methodjit_chrome_str : js_methodjit_content_str); + PRBool useProfiling = nsContentUtils::GetBoolPref(chromeWindow ? + js_profiling_chrome_str : + js_profiling_content_str); nsCOMPtr xr = do_GetService(XULRUNTIME_SERVICE_CONTRACTID); if (xr) { PRBool safeMode = PR_FALSE; @@ -1229,6 +1234,7 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data) if (safeMode) { useTraceJIT = PR_FALSE; useMethodJIT = PR_FALSE; + useProfiling = PR_FALSE; } } @@ -1245,6 +1251,11 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data) else newDefaultJSOptions &= ~JSOPTION_METHODJIT; + if (useProfiling) + newDefaultJSOptions |= JSOPTION_PROFILING; + else + newDefaultJSOptions &= ~JSOPTION_PROFILING; + #ifdef DEBUG // In debug builds, warnings are enabled in chrome context if javascript.options.strict.debug is true PRBool strictDebug = nsContentUtils::GetBoolPref(js_strict_debug_option_str); diff --git a/js/src/Makefile.in b/js/src/Makefile.in index 8b7a244a12ab..3721a9378d22 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -126,6 +126,7 @@ DIST_INSTALL = 1 VPATH = $(srcdir) CPPSRCS = \ + jsanalyze.cpp \ jsapi.cpp \ jsarena.cpp \ jsarray.cpp \ @@ -181,6 +182,7 @@ INSTALLED_HEADERS = \ jsautocfg.h \ $(CURDIR)/jsautokw.h \ js.msg \ + jsanalyze.h \ jsapi.h \ jsarray.h \ jsarena.h \ @@ -304,7 +306,6 @@ ifdef ENABLE_METHODJIT VPATH += $(srcdir)/methodjit CPPSRCS += MethodJIT.cpp \ - BytecodeAnalyzer.cpp \ StubCalls.cpp \ Compiler.cpp \ FrameState.cpp \ @@ -360,22 +361,6 @@ CPPSRCS += checks.cc \ utils.cc \ $(NONE) -INSTALLED_HEADERS += \ - cached-powers.h \ - checks.h \ - conversions.h \ - diy-fp.h \ - double.h \ - dtoa.h \ - fast-dtoa.h \ - globals.h \ - include-v8.h \ - platform.h \ - powers-ten.h \ - utils.h \ - v8.h \ - $(NULL) - # # END enclude sources for V8 dtoa ############################################# @@ -580,11 +565,11 @@ endif ifdef ENABLE_TRACEJIT ifndef WINCE check:: - $(wildcard $(RUN_TEST_PROGRAM)) $(PYTHON) -u $(srcdir)/trace-test/trace_test.py \ + $(wildcard $(RUN_TEST_PROGRAM)) $(PYTHON) -u $(srcdir)/jit-test/jit_test.py \ --no-slow --no-progress --tinderbox $(DIST)/bin/js$(BIN_SUFFIX) check-valgrind:: - $(wildcard $(RUN_TEST_PROGRAM)) $(PYTHON) -u $(srcdir)/trace-test/trace_test.py \ + $(wildcard $(RUN_TEST_PROGRAM)) $(PYTHON) -u $(srcdir)/jit-test/jit_test.py \ --valgrind --no-slow --no-progress --tinderbox $(DIST)/bin/js$(BIN_SUFFIX) endif endif diff --git a/js/src/assembler/assembler/ARMAssembler.h b/js/src/assembler/assembler/ARMAssembler.h index 7428c0e1717f..f8fee1f5c525 100644 --- a/js/src/assembler/assembler/ARMAssembler.h +++ b/js/src/assembler/assembler/ARMAssembler.h @@ -214,7 +214,7 @@ namespace JSC { FMSTAT = 0x0ef1fa10 #if WTF_ARM_ARCH_VERSION >= 5 ,CLZ = 0x016f0f10, - BKPT = 0xe120070, + BKPT = 0xe1200070, BLX = 0x012fff30 #endif #if WTF_ARM_ARCH_VERSION >= 7 @@ -253,9 +253,9 @@ namespace JSC { }; enum { - padForAlign8 = 0x00, - padForAlign16 = 0x0000, - padForAlign32 = 0xee120070 + padForAlign8 = (int)0x00, + padForAlign16 = (int)0x0000, + padForAlign32 = (int)0xe12fff7f // 'bkpt 0xffff' }; typedef enum { @@ -307,7 +307,7 @@ namespace JSC { } int m_offset : 31; - int m_used : 1; + bool m_used : 1; }; // Instruction formating @@ -1284,7 +1284,7 @@ namespace JSC { // Deal with special encodings. if ((type == LSL) && (imm == 0)) { // "LSL #0" doesn't shift at all (and is the default). - sprintf(out, rm); + sprintf(out, "%s", rm); return; } diff --git a/js/src/assembler/assembler/AssemblerBufferWithConstantPool.h b/js/src/assembler/assembler/AssemblerBufferWithConstantPool.h index b8020fa81050..66c927a2655c 100644 --- a/js/src/assembler/assembler/AssemblerBufferWithConstantPool.h +++ b/js/src/assembler/assembler/AssemblerBufferWithConstantPool.h @@ -221,7 +221,7 @@ public: void flushWithoutBarrier(bool isForced = false) { // Flush if constant pool is more than 60% full to avoid overuse of this function. - if (isForced || 5 * m_numConsts > 3 * maxPoolSize / sizeof(uint32_t)) + if (isForced || (5 * m_numConsts * sizeof(uint32_t)) > (3 * maxPoolSize)) flushConstantPool(false); } diff --git a/js/src/trace-test/README b/js/src/jit-test/README similarity index 90% rename from js/src/trace-test/README rename to js/src/jit-test/README index b5f87b137c5d..ddde38dc9626 100644 --- a/js/src/trace-test/README +++ b/js/src/jit-test/README @@ -13,7 +13,7 @@ Python 2.5. This is already a standard requirement for building our tree. Basic usage: - python trace_test.py + python jit_test.py The progress bar shows [#tests passed, #tests failed, #tests run] at the left. If all tests pass, the output is 'PASSED ALL'. The test suite can be interrupted @@ -21,11 +21,11 @@ at any time with Ctrl+C and partial results will be printed. To run only the basic tests, not including the slow tests: - python trace_test.py basic + python jit_test.py basic For more options: - python trace_test.py -h + python jit_test.py -h * CREATING NEW TESTS @@ -44,12 +44,12 @@ test case: The first line of a test case can contain a special comment controlling how the test is run. For example: - // |trace-test| allow-oom; + // |jit-test| allow-oom; The general format in EBNF is: metaline ::= cookie { item ";" } - cookie ::= "|trace-test|" + cookie ::= "|jit-test|" item ::= flag | attribute flag ::= "slow" | "allow-oom" diff --git a/js/src/trace-test/trace_test.py b/js/src/jit-test/jit_test.py similarity index 96% rename from js/src/trace-test/trace_test.py rename to js/src/jit-test/jit_test.py index e729ece0c6d7..c614273056a5 100644 --- a/js/src/trace-test/trace_test.py +++ b/js/src/jit-test/jit_test.py @@ -1,4 +1,4 @@ -# trace_test.py -- Python harness for JavaScript trace tests. +# jit_test.py -- Python harness for JavaScript trace tests. import datetime, os, re, sys, tempfile, traceback import subprocess @@ -60,7 +60,7 @@ class Test: t.error = self.error return t - COOKIE = '|trace-test|' + COOKIE = '|jit-test|' @classmethod def from_file(cls, path, options): @@ -83,7 +83,7 @@ class Test: elif name == 'error': test.error = value else: - print('warning: unrecognized |trace-test| attribute %s'%part) + print('warning: unrecognized |jit-test| attribute %s'%part) else: if name == 'slow': test.slow = True @@ -92,7 +92,7 @@ class Test: elif name == 'valgrind': test.valgrind = options.valgrind else: - print('warning: unrecognized |trace-test| attribute %s'%part) + print('warning: unrecognized |jit-test| attribute %s'%part) if options.valgrind_all: test.valgrind = True @@ -230,7 +230,7 @@ def run_tests(tests, test_dir, lib_dir): if OPTIONS.tinderbox: if ok: - print('TEST-PASS | trace_test.py | %s'%test.path) + print('TEST-PASS | jit_test.py | %s'%test.path) else: lines = [ _ for _ in out.split('\n') + err.split('\n') if _ != '' ] @@ -238,7 +238,7 @@ def run_tests(tests, test_dir, lib_dir): msg = lines[-1] else: msg = '' - print('TEST-UNEXPECTED-FAIL | trace_test.py | %s: %s'% + print('TEST-UNEXPECTED-FAIL | jit_test.py | %s: %s'% (test.path, msg)) n = i + 1 @@ -247,7 +247,7 @@ def run_tests(tests, test_dir, lib_dir): pb.update(n) complete = True except KeyboardInterrupt: - print('TEST-UNEXPECTED_FAIL | trace_test.py | %s'%test.path) + print('TEST-UNEXPECTED_FAIL | jit_test.py | %s'%test.path) if pb: pb.finish() @@ -289,7 +289,7 @@ def parse_jitflags(): for flags in OPTIONS.jitflags.split(',') ] for flags in jitflags: for flag in flags: - if flag not in ('-j', '-m', '-d'): + if flag not in ('-j', '-m', '-p', '-d'): print('Invalid jit flag: "%s"'%flag) sys.exit(1) return jitflags @@ -319,7 +319,7 @@ def main(argv): lib_dir = os.path.join(script_dir, 'lib') # The [TESTS] optional arguments are paths of test files relative - # to the trace-test/tests directory. + # to the jit-test/tests directory. from optparse import OptionParser op = OptionParser(usage='%prog [options] JS_SHELL [TESTS]') diff --git a/js/src/trace-test/lib/andTestHelper.js b/js/src/jit-test/lib/andTestHelper.js similarity index 100% rename from js/src/trace-test/lib/andTestHelper.js rename to js/src/jit-test/lib/andTestHelper.js diff --git a/js/src/trace-test/lib/array-compare.js b/js/src/jit-test/lib/array-compare.js similarity index 100% rename from js/src/trace-test/lib/array-compare.js rename to js/src/jit-test/lib/array-compare.js diff --git a/js/src/trace-test/lib/mandelbrot-results.js b/js/src/jit-test/lib/mandelbrot-results.js similarity index 100% rename from js/src/trace-test/lib/mandelbrot-results.js rename to js/src/jit-test/lib/mandelbrot-results.js diff --git a/js/src/trace-test/lib/orTestHelper.js b/js/src/jit-test/lib/orTestHelper.js similarity index 100% rename from js/src/trace-test/lib/orTestHelper.js rename to js/src/jit-test/lib/orTestHelper.js diff --git a/js/src/trace-test/lib/prolog.js b/js/src/jit-test/lib/prolog.js similarity index 100% rename from js/src/trace-test/lib/prolog.js rename to js/src/jit-test/lib/prolog.js diff --git a/js/src/trace-test/lib/range.js b/js/src/jit-test/lib/range.js similarity index 100% rename from js/src/trace-test/lib/range.js rename to js/src/jit-test/lib/range.js diff --git a/js/src/trace-test/progressbar.py b/js/src/jit-test/progressbar.py similarity index 100% rename from js/src/trace-test/progressbar.py rename to js/src/jit-test/progressbar.py diff --git a/js/src/trace-test/tests/arguments/args-createontrace.js b/js/src/jit-test/tests/arguments/args-createontrace.js similarity index 100% rename from js/src/trace-test/tests/arguments/args-createontrace.js rename to js/src/jit-test/tests/arguments/args-createontrace.js diff --git a/js/src/trace-test/tests/arguments/args-mochi-2.js b/js/src/jit-test/tests/arguments/args-mochi-2.js similarity index 100% rename from js/src/trace-test/tests/arguments/args-mochi-2.js rename to js/src/jit-test/tests/arguments/args-mochi-2.js diff --git a/js/src/trace-test/tests/arguments/args-mochi-2a.js b/js/src/jit-test/tests/arguments/args-mochi-2a.js similarity index 100% rename from js/src/trace-test/tests/arguments/args-mochi-2a.js rename to js/src/jit-test/tests/arguments/args-mochi-2a.js diff --git a/js/src/trace-test/tests/arguments/args-mochi.js b/js/src/jit-test/tests/arguments/args-mochi.js similarity index 100% rename from js/src/trace-test/tests/arguments/args-mochi.js rename to js/src/jit-test/tests/arguments/args-mochi.js diff --git a/js/src/trace-test/tests/arguments/args-mutate-length-1.js b/js/src/jit-test/tests/arguments/args-mutate-length-1.js similarity index 100% rename from js/src/trace-test/tests/arguments/args-mutate-length-1.js rename to js/src/jit-test/tests/arguments/args-mutate-length-1.js diff --git a/js/src/trace-test/tests/arguments/args-mutate-length-2.js b/js/src/jit-test/tests/arguments/args-mutate-length-2.js similarity index 100% rename from js/src/trace-test/tests/arguments/args-mutate-length-2.js rename to js/src/jit-test/tests/arguments/args-mutate-length-2.js diff --git a/js/src/trace-test/tests/arguments/args-range-2.js b/js/src/jit-test/tests/arguments/args-range-2.js similarity index 100% rename from js/src/trace-test/tests/arguments/args-range-2.js rename to js/src/jit-test/tests/arguments/args-range-2.js diff --git a/js/src/trace-test/tests/arguments/args-range-const.js b/js/src/jit-test/tests/arguments/args-range-const.js similarity index 100% rename from js/src/trace-test/tests/arguments/args-range-const.js rename to js/src/jit-test/tests/arguments/args-range-const.js diff --git a/js/src/trace-test/tests/arguments/args-range.js b/js/src/jit-test/tests/arguments/args-range.js similarity index 100% rename from js/src/trace-test/tests/arguments/args-range.js rename to js/src/jit-test/tests/arguments/args-range.js diff --git a/js/src/trace-test/tests/arguments/args-redefine-length-1.js b/js/src/jit-test/tests/arguments/args-redefine-length-1.js similarity index 100% rename from js/src/trace-test/tests/arguments/args-redefine-length-1.js rename to js/src/jit-test/tests/arguments/args-redefine-length-1.js diff --git a/js/src/trace-test/tests/arguments/args-redefine-length-2.js b/js/src/jit-test/tests/arguments/args-redefine-length-2.js similarity index 100% rename from js/src/trace-test/tests/arguments/args-redefine-length-2.js rename to js/src/jit-test/tests/arguments/args-redefine-length-2.js diff --git a/js/src/trace-test/tests/arguments/args-sum.js b/js/src/jit-test/tests/arguments/args-sum.js similarity index 100% rename from js/src/trace-test/tests/arguments/args-sum.js rename to js/src/jit-test/tests/arguments/args-sum.js diff --git a/js/src/trace-test/tests/arguments/args-vargc.js b/js/src/jit-test/tests/arguments/args-vargc.js similarity index 100% rename from js/src/trace-test/tests/arguments/args-vargc.js rename to js/src/jit-test/tests/arguments/args-vargc.js diff --git a/js/src/trace-test/tests/arguments/args1.js b/js/src/jit-test/tests/arguments/args1.js similarity index 100% rename from js/src/trace-test/tests/arguments/args1.js rename to js/src/jit-test/tests/arguments/args1.js diff --git a/js/src/trace-test/tests/arguments/args10.js b/js/src/jit-test/tests/arguments/args10.js similarity index 100% rename from js/src/trace-test/tests/arguments/args10.js rename to js/src/jit-test/tests/arguments/args10.js diff --git a/js/src/trace-test/tests/arguments/args11.js b/js/src/jit-test/tests/arguments/args11.js similarity index 100% rename from js/src/trace-test/tests/arguments/args11.js rename to js/src/jit-test/tests/arguments/args11.js diff --git a/js/src/trace-test/tests/arguments/args2.js b/js/src/jit-test/tests/arguments/args2.js similarity index 100% rename from js/src/trace-test/tests/arguments/args2.js rename to js/src/jit-test/tests/arguments/args2.js diff --git a/js/src/trace-test/tests/arguments/args2a.js b/js/src/jit-test/tests/arguments/args2a.js similarity index 100% rename from js/src/trace-test/tests/arguments/args2a.js rename to js/src/jit-test/tests/arguments/args2a.js diff --git a/js/src/trace-test/tests/arguments/args2b.js b/js/src/jit-test/tests/arguments/args2b.js similarity index 100% rename from js/src/trace-test/tests/arguments/args2b.js rename to js/src/jit-test/tests/arguments/args2b.js diff --git a/js/src/trace-test/tests/arguments/args2c.js b/js/src/jit-test/tests/arguments/args2c.js similarity index 100% rename from js/src/trace-test/tests/arguments/args2c.js rename to js/src/jit-test/tests/arguments/args2c.js diff --git a/js/src/trace-test/tests/arguments/args2d.js b/js/src/jit-test/tests/arguments/args2d.js similarity index 100% rename from js/src/trace-test/tests/arguments/args2d.js rename to js/src/jit-test/tests/arguments/args2d.js diff --git a/js/src/trace-test/tests/arguments/args3.js b/js/src/jit-test/tests/arguments/args3.js similarity index 100% rename from js/src/trace-test/tests/arguments/args3.js rename to js/src/jit-test/tests/arguments/args3.js diff --git a/js/src/trace-test/tests/arguments/args4.js b/js/src/jit-test/tests/arguments/args4.js similarity index 100% rename from js/src/trace-test/tests/arguments/args4.js rename to js/src/jit-test/tests/arguments/args4.js diff --git a/js/src/trace-test/tests/arguments/args5.js b/js/src/jit-test/tests/arguments/args5.js similarity index 100% rename from js/src/trace-test/tests/arguments/args5.js rename to js/src/jit-test/tests/arguments/args5.js diff --git a/js/src/trace-test/tests/arguments/args6.js b/js/src/jit-test/tests/arguments/args6.js similarity index 100% rename from js/src/trace-test/tests/arguments/args6.js rename to js/src/jit-test/tests/arguments/args6.js diff --git a/js/src/trace-test/tests/arguments/args6a.js b/js/src/jit-test/tests/arguments/args6a.js similarity index 100% rename from js/src/trace-test/tests/arguments/args6a.js rename to js/src/jit-test/tests/arguments/args6a.js diff --git a/js/src/trace-test/tests/arguments/args7.js b/js/src/jit-test/tests/arguments/args7.js similarity index 100% rename from js/src/trace-test/tests/arguments/args7.js rename to js/src/jit-test/tests/arguments/args7.js diff --git a/js/src/trace-test/tests/arguments/args8.js b/js/src/jit-test/tests/arguments/args8.js similarity index 100% rename from js/src/trace-test/tests/arguments/args8.js rename to js/src/jit-test/tests/arguments/args8.js diff --git a/js/src/trace-test/tests/arguments/args9.js b/js/src/jit-test/tests/arguments/args9.js similarity index 100% rename from js/src/trace-test/tests/arguments/args9.js rename to js/src/jit-test/tests/arguments/args9.js diff --git a/js/src/trace-test/tests/arguments/argsub.js b/js/src/jit-test/tests/arguments/argsub.js similarity index 100% rename from js/src/trace-test/tests/arguments/argsub.js rename to js/src/jit-test/tests/arguments/argsub.js diff --git a/js/src/trace-test/tests/arguments/argsx-1.js b/js/src/jit-test/tests/arguments/argsx-1.js similarity index 100% rename from js/src/trace-test/tests/arguments/argsx-1.js rename to js/src/jit-test/tests/arguments/argsx-1.js diff --git a/js/src/trace-test/tests/arguments/argsx-2.js b/js/src/jit-test/tests/arguments/argsx-2.js similarity index 100% rename from js/src/trace-test/tests/arguments/argsx-2.js rename to js/src/jit-test/tests/arguments/argsx-2.js diff --git a/js/src/trace-test/tests/arguments/argsx-3.js b/js/src/jit-test/tests/arguments/argsx-3.js similarity index 100% rename from js/src/trace-test/tests/arguments/argsx-3.js rename to js/src/jit-test/tests/arguments/argsx-3.js diff --git a/js/src/trace-test/tests/arguments/argsx-3a.js b/js/src/jit-test/tests/arguments/argsx-3a.js similarity index 100% rename from js/src/trace-test/tests/arguments/argsx-3a.js rename to js/src/jit-test/tests/arguments/argsx-3a.js diff --git a/js/src/trace-test/tests/arguments/argsx-4.js b/js/src/jit-test/tests/arguments/argsx-4.js similarity index 100% rename from js/src/trace-test/tests/arguments/argsx-4.js rename to js/src/jit-test/tests/arguments/argsx-4.js diff --git a/js/src/trace-test/tests/arguments/bug503772.js b/js/src/jit-test/tests/arguments/bug503772.js similarity index 100% rename from js/src/trace-test/tests/arguments/bug503772.js rename to js/src/jit-test/tests/arguments/bug503772.js diff --git a/js/src/trace-test/tests/arguments/bug508178.js b/js/src/jit-test/tests/arguments/bug508178.js similarity index 100% rename from js/src/trace-test/tests/arguments/bug508178.js rename to js/src/jit-test/tests/arguments/bug508178.js diff --git a/js/src/trace-test/tests/arguments/bug554670-1.js b/js/src/jit-test/tests/arguments/bug554670-1.js similarity index 100% rename from js/src/trace-test/tests/arguments/bug554670-1.js rename to js/src/jit-test/tests/arguments/bug554670-1.js diff --git a/js/src/trace-test/tests/arguments/bug554670-2.js b/js/src/jit-test/tests/arguments/bug554670-2.js similarity index 100% rename from js/src/trace-test/tests/arguments/bug554670-2.js rename to js/src/jit-test/tests/arguments/bug554670-2.js diff --git a/js/src/trace-test/tests/arguments/nonstrict-args.js b/js/src/jit-test/tests/arguments/nonstrict-args.js similarity index 100% rename from js/src/trace-test/tests/arguments/nonstrict-args.js rename to js/src/jit-test/tests/arguments/nonstrict-args.js diff --git a/js/src/trace-test/tests/arguments/nonstrict-assign-element-get-parameter.js b/js/src/jit-test/tests/arguments/nonstrict-assign-element-get-parameter.js similarity index 100% rename from js/src/trace-test/tests/arguments/nonstrict-assign-element-get-parameter.js rename to js/src/jit-test/tests/arguments/nonstrict-assign-element-get-parameter.js diff --git a/js/src/trace-test/tests/arguments/nonstrict-assign-parameter-get-element.js b/js/src/jit-test/tests/arguments/nonstrict-assign-parameter-get-element.js similarity index 100% rename from js/src/trace-test/tests/arguments/nonstrict-assign-parameter-get-element.js rename to js/src/jit-test/tests/arguments/nonstrict-assign-parameter-get-element.js diff --git a/js/src/trace-test/tests/arguments/nonstrict-assign.js b/js/src/jit-test/tests/arguments/nonstrict-assign.js similarity index 100% rename from js/src/trace-test/tests/arguments/nonstrict-assign.js rename to js/src/jit-test/tests/arguments/nonstrict-assign.js diff --git a/js/src/trace-test/tests/arguments/nonstrict-later-assign.js b/js/src/jit-test/tests/arguments/nonstrict-later-assign.js similarity index 100% rename from js/src/trace-test/tests/arguments/nonstrict-later-assign.js rename to js/src/jit-test/tests/arguments/nonstrict-later-assign.js diff --git a/js/src/trace-test/tests/arguments/nonstrict-noargs.js b/js/src/jit-test/tests/arguments/nonstrict-noargs.js similarity index 100% rename from js/src/trace-test/tests/arguments/nonstrict-noargs.js rename to js/src/jit-test/tests/arguments/nonstrict-noargs.js diff --git a/js/src/trace-test/tests/arguments/strict-args.js b/js/src/jit-test/tests/arguments/strict-args.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-args.js rename to js/src/jit-test/tests/arguments/strict-args.js diff --git a/js/src/trace-test/tests/arguments/strict-assign-after.js b/js/src/jit-test/tests/arguments/strict-assign-after.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-assign-after.js rename to js/src/jit-test/tests/arguments/strict-assign-after.js diff --git a/js/src/trace-test/tests/arguments/strict-assign-arguments-element.js b/js/src/jit-test/tests/arguments/strict-assign-arguments-element.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-assign-arguments-element.js rename to js/src/jit-test/tests/arguments/strict-assign-arguments-element.js diff --git a/js/src/trace-test/tests/arguments/strict-assign-outer-param-psych.js b/js/src/jit-test/tests/arguments/strict-assign-outer-param-psych.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-assign-outer-param-psych.js rename to js/src/jit-test/tests/arguments/strict-assign-outer-param-psych.js diff --git a/js/src/trace-test/tests/arguments/strict-assign-outer-param.js b/js/src/jit-test/tests/arguments/strict-assign-outer-param.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-assign-outer-param.js rename to js/src/jit-test/tests/arguments/strict-assign-outer-param.js diff --git a/js/src/trace-test/tests/arguments/strict-assign-parameter-get-element.js b/js/src/jit-test/tests/arguments/strict-assign-parameter-get-element.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-assign-parameter-get-element.js rename to js/src/jit-test/tests/arguments/strict-assign-parameter-get-element.js diff --git a/js/src/trace-test/tests/arguments/strict-assign.js b/js/src/jit-test/tests/arguments/strict-assign.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-assign.js rename to js/src/jit-test/tests/arguments/strict-assign.js diff --git a/js/src/trace-test/tests/arguments/strict-eval-mutation.js b/js/src/jit-test/tests/arguments/strict-eval-mutation.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-eval-mutation.js rename to js/src/jit-test/tests/arguments/strict-eval-mutation.js diff --git a/js/src/trace-test/tests/arguments/strict-eval.js b/js/src/jit-test/tests/arguments/strict-eval.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-eval.js rename to js/src/jit-test/tests/arguments/strict-eval.js diff --git a/js/src/trace-test/tests/arguments/strict-maybe-assign-outer.js b/js/src/jit-test/tests/arguments/strict-maybe-assign-outer.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-maybe-assign-outer.js rename to js/src/jit-test/tests/arguments/strict-maybe-assign-outer.js diff --git a/js/src/trace-test/tests/arguments/strict-maybe-nested-eval.js b/js/src/jit-test/tests/arguments/strict-maybe-nested-eval.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-maybe-nested-eval.js rename to js/src/jit-test/tests/arguments/strict-maybe-nested-eval.js diff --git a/js/src/trace-test/tests/arguments/strict-nested-assign-shadow-function-call.js b/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function-call.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-nested-assign-shadow-function-call.js rename to js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function-call.js diff --git a/js/src/trace-test/tests/arguments/strict-nested-assign-shadow-function-name.js b/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function-name.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-nested-assign-shadow-function-name.js rename to js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function-name.js diff --git a/js/src/trace-test/tests/arguments/strict-nested-assign-shadow-function.js b/js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-nested-assign-shadow-function.js rename to js/src/jit-test/tests/arguments/strict-nested-assign-shadow-function.js diff --git a/js/src/trace-test/tests/arguments/strict-nested-assign-shadowed-catch-call.js b/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-catch-call.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-nested-assign-shadowed-catch-call.js rename to js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-catch-call.js diff --git a/js/src/trace-test/tests/arguments/strict-nested-assign-shadowed-catch.js b/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-catch.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-nested-assign-shadowed-catch.js rename to js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-catch.js diff --git a/js/src/trace-test/tests/arguments/strict-nested-assign-shadowed-var.js b/js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-var.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-nested-assign-shadowed-var.js rename to js/src/jit-test/tests/arguments/strict-nested-assign-shadowed-var.js diff --git a/js/src/trace-test/tests/arguments/strict-nested-eval.js b/js/src/jit-test/tests/arguments/strict-nested-eval.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-nested-eval.js rename to js/src/jit-test/tests/arguments/strict-nested-eval.js diff --git a/js/src/trace-test/tests/arguments/strict-nested-shadow-eval.js b/js/src/jit-test/tests/arguments/strict-nested-shadow-eval.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-nested-shadow-eval.js rename to js/src/jit-test/tests/arguments/strict-nested-shadow-eval.js diff --git a/js/src/trace-test/tests/arguments/strict-nested-shadow-maybe-eval.js b/js/src/jit-test/tests/arguments/strict-nested-shadow-maybe-eval.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-nested-shadow-maybe-eval.js rename to js/src/jit-test/tests/arguments/strict-nested-shadow-maybe-eval.js diff --git a/js/src/trace-test/tests/arguments/strict-noargs.js b/js/src/jit-test/tests/arguments/strict-noargs.js similarity index 100% rename from js/src/trace-test/tests/arguments/strict-noargs.js rename to js/src/jit-test/tests/arguments/strict-noargs.js diff --git a/js/src/trace-test/tests/arguments/testDelArg1.js b/js/src/jit-test/tests/arguments/testDelArg1.js similarity index 100% rename from js/src/trace-test/tests/arguments/testDelArg1.js rename to js/src/jit-test/tests/arguments/testDelArg1.js diff --git a/js/src/trace-test/tests/arguments/testDelArg2.js b/js/src/jit-test/tests/arguments/testDelArg2.js similarity index 100% rename from js/src/trace-test/tests/arguments/testDelArg2.js rename to js/src/jit-test/tests/arguments/testDelArg2.js diff --git a/js/src/trace-test/tests/basic/FPQuadCmp.js b/js/src/jit-test/tests/basic/FPQuadCmp.js similarity index 100% rename from js/src/trace-test/tests/basic/FPQuadCmp.js rename to js/src/jit-test/tests/basic/FPQuadCmp.js diff --git a/js/src/trace-test/tests/basic/argumentsPassedToBuiltin.js b/js/src/jit-test/tests/basic/argumentsPassedToBuiltin.js similarity index 100% rename from js/src/trace-test/tests/basic/argumentsPassedToBuiltin.js rename to js/src/jit-test/tests/basic/argumentsPassedToBuiltin.js diff --git a/js/src/trace-test/tests/basic/arith.js b/js/src/jit-test/tests/basic/arith.js similarity index 74% rename from js/src/trace-test/tests/basic/arith.js rename to js/src/jit-test/tests/basic/arith.js index 7285e8b45193..b7f551dccd06 100644 --- a/js/src/trace-test/tests/basic/arith.js +++ b/js/src/jit-test/tests/basic/arith.js @@ -1,4 +1,4 @@ -// |trace-test| TMFLAGS: full,fragprofile,treevis +// |jit-test| TMFLAGS: full,fragprofile,treevis function arith() { diff --git a/js/src/trace-test/tests/basic/arityMismatchExtraArg.js b/js/src/jit-test/tests/basic/arityMismatchExtraArg.js similarity index 100% rename from js/src/trace-test/tests/basic/arityMismatchExtraArg.js rename to js/src/jit-test/tests/basic/arityMismatchExtraArg.js diff --git a/js/src/trace-test/tests/basic/arityMismatchMissingArg.js b/js/src/jit-test/tests/basic/arityMismatchMissingArg.js similarity index 100% rename from js/src/trace-test/tests/basic/arityMismatchMissingArg.js rename to js/src/jit-test/tests/basic/arityMismatchMissingArg.js diff --git a/js/src/trace-test/tests/basic/bigLoadStoreDisp.js b/js/src/jit-test/tests/basic/bigLoadStoreDisp.js similarity index 100% rename from js/src/trace-test/tests/basic/bigLoadStoreDisp.js rename to js/src/jit-test/tests/basic/bigLoadStoreDisp.js diff --git a/js/src/trace-test/tests/basic/bitwiseAnd.js b/js/src/jit-test/tests/basic/bitwiseAnd.js similarity index 100% rename from js/src/trace-test/tests/basic/bitwiseAnd.js rename to js/src/jit-test/tests/basic/bitwiseAnd.js diff --git a/js/src/trace-test/tests/basic/bitwiseGlobal.js b/js/src/jit-test/tests/basic/bitwiseGlobal.js similarity index 100% rename from js/src/trace-test/tests/basic/bitwiseGlobal.js rename to js/src/jit-test/tests/basic/bitwiseGlobal.js diff --git a/js/src/trace-test/tests/basic/bug464403.js b/js/src/jit-test/tests/basic/bug464403.js similarity index 100% rename from js/src/trace-test/tests/basic/bug464403.js rename to js/src/jit-test/tests/basic/bug464403.js diff --git a/js/src/trace-test/tests/basic/bug465902.js b/js/src/jit-test/tests/basic/bug465902.js similarity index 100% rename from js/src/trace-test/tests/basic/bug465902.js rename to js/src/jit-test/tests/basic/bug465902.js diff --git a/js/src/trace-test/tests/basic/bug489098.js b/js/src/jit-test/tests/basic/bug489098.js similarity index 100% rename from js/src/trace-test/tests/basic/bug489098.js rename to js/src/jit-test/tests/basic/bug489098.js diff --git a/js/src/trace-test/tests/basic/bug504587-1.js b/js/src/jit-test/tests/basic/bug504587-1.js similarity index 100% rename from js/src/trace-test/tests/basic/bug504587-1.js rename to js/src/jit-test/tests/basic/bug504587-1.js diff --git a/js/src/trace-test/tests/basic/bug507180.js b/js/src/jit-test/tests/basic/bug507180.js similarity index 100% rename from js/src/trace-test/tests/basic/bug507180.js rename to js/src/jit-test/tests/basic/bug507180.js diff --git a/js/src/trace-test/tests/basic/bug509639.js b/js/src/jit-test/tests/basic/bug509639.js similarity index 100% rename from js/src/trace-test/tests/basic/bug509639.js rename to js/src/jit-test/tests/basic/bug509639.js diff --git a/js/src/trace-test/tests/basic/bug509982.js b/js/src/jit-test/tests/basic/bug509982.js similarity index 100% rename from js/src/trace-test/tests/basic/bug509982.js rename to js/src/jit-test/tests/basic/bug509982.js diff --git a/js/src/trace-test/tests/basic/bug510434.js b/js/src/jit-test/tests/basic/bug510434.js similarity index 100% rename from js/src/trace-test/tests/basic/bug510434.js rename to js/src/jit-test/tests/basic/bug510434.js diff --git a/js/src/trace-test/tests/basic/bug510437-2.js b/js/src/jit-test/tests/basic/bug510437-2.js similarity index 100% rename from js/src/trace-test/tests/basic/bug510437-2.js rename to js/src/jit-test/tests/basic/bug510437-2.js diff --git a/js/src/trace-test/tests/basic/bug510437.js b/js/src/jit-test/tests/basic/bug510437.js similarity index 100% rename from js/src/trace-test/tests/basic/bug510437.js rename to js/src/jit-test/tests/basic/bug510437.js diff --git a/js/src/trace-test/tests/basic/bug510642.js b/js/src/jit-test/tests/basic/bug510642.js similarity index 100% rename from js/src/trace-test/tests/basic/bug510642.js rename to js/src/jit-test/tests/basic/bug510642.js diff --git a/js/src/trace-test/tests/basic/bug510655.js b/js/src/jit-test/tests/basic/bug510655.js similarity index 100% rename from js/src/trace-test/tests/basic/bug510655.js rename to js/src/jit-test/tests/basic/bug510655.js diff --git a/js/src/trace-test/tests/basic/bug511214.js b/js/src/jit-test/tests/basic/bug511214.js similarity index 100% rename from js/src/trace-test/tests/basic/bug511214.js rename to js/src/jit-test/tests/basic/bug511214.js diff --git a/js/src/trace-test/tests/basic/bug511241.js b/js/src/jit-test/tests/basic/bug511241.js similarity index 100% rename from js/src/trace-test/tests/basic/bug511241.js rename to js/src/jit-test/tests/basic/bug511241.js diff --git a/js/src/trace-test/tests/basic/bug513038.js b/js/src/jit-test/tests/basic/bug513038.js similarity index 100% rename from js/src/trace-test/tests/basic/bug513038.js rename to js/src/jit-test/tests/basic/bug513038.js diff --git a/js/src/trace-test/tests/basic/bug516009.js b/js/src/jit-test/tests/basic/bug516009.js similarity index 100% rename from js/src/trace-test/tests/basic/bug516009.js rename to js/src/jit-test/tests/basic/bug516009.js diff --git a/js/src/trace-test/tests/basic/bug517721.js b/js/src/jit-test/tests/basic/bug517721.js similarity index 100% rename from js/src/trace-test/tests/basic/bug517721.js rename to js/src/jit-test/tests/basic/bug517721.js diff --git a/js/src/trace-test/tests/basic/bug519129.js b/js/src/jit-test/tests/basic/bug519129.js similarity index 100% rename from js/src/trace-test/tests/basic/bug519129.js rename to js/src/jit-test/tests/basic/bug519129.js diff --git a/js/src/trace-test/tests/basic/bug520498.js b/js/src/jit-test/tests/basic/bug520498.js similarity index 100% rename from js/src/trace-test/tests/basic/bug520498.js rename to js/src/jit-test/tests/basic/bug520498.js diff --git a/js/src/trace-test/tests/basic/bug522136.js b/js/src/jit-test/tests/basic/bug522136.js similarity index 100% rename from js/src/trace-test/tests/basic/bug522136.js rename to js/src/jit-test/tests/basic/bug522136.js diff --git a/js/src/trace-test/tests/basic/bug522817.js b/js/src/jit-test/tests/basic/bug522817.js similarity index 100% rename from js/src/trace-test/tests/basic/bug522817.js rename to js/src/jit-test/tests/basic/bug522817.js diff --git a/js/src/trace-test/tests/basic/bug524826-2.js b/js/src/jit-test/tests/basic/bug524826-2.js similarity index 100% rename from js/src/trace-test/tests/basic/bug524826-2.js rename to js/src/jit-test/tests/basic/bug524826-2.js diff --git a/js/src/trace-test/tests/basic/bug524826.js b/js/src/jit-test/tests/basic/bug524826.js similarity index 100% rename from js/src/trace-test/tests/basic/bug524826.js rename to js/src/jit-test/tests/basic/bug524826.js diff --git a/js/src/trace-test/tests/basic/bug525028.js b/js/src/jit-test/tests/basic/bug525028.js similarity index 100% rename from js/src/trace-test/tests/basic/bug525028.js rename to js/src/jit-test/tests/basic/bug525028.js diff --git a/js/src/trace-test/tests/basic/bug527288.js b/js/src/jit-test/tests/basic/bug527288.js similarity index 100% rename from js/src/trace-test/tests/basic/bug527288.js rename to js/src/jit-test/tests/basic/bug527288.js diff --git a/js/src/trace-test/tests/basic/bug528116.js b/js/src/jit-test/tests/basic/bug528116.js similarity index 100% rename from js/src/trace-test/tests/basic/bug528116.js rename to js/src/jit-test/tests/basic/bug528116.js diff --git a/js/src/trace-test/tests/basic/bug528644.js b/js/src/jit-test/tests/basic/bug528644.js similarity index 100% rename from js/src/trace-test/tests/basic/bug528644.js rename to js/src/jit-test/tests/basic/bug528644.js diff --git a/js/src/trace-test/tests/basic/bug529130.js b/js/src/jit-test/tests/basic/bug529130.js similarity index 100% rename from js/src/trace-test/tests/basic/bug529130.js rename to js/src/jit-test/tests/basic/bug529130.js diff --git a/js/src/trace-test/tests/basic/bug532568-2.js b/js/src/jit-test/tests/basic/bug532568-2.js similarity index 100% rename from js/src/trace-test/tests/basic/bug532568-2.js rename to js/src/jit-test/tests/basic/bug532568-2.js diff --git a/js/src/trace-test/tests/basic/bug532568.js b/js/src/jit-test/tests/basic/bug532568.js similarity index 100% rename from js/src/trace-test/tests/basic/bug532568.js rename to js/src/jit-test/tests/basic/bug532568.js diff --git a/js/src/trace-test/tests/basic/bug532823.js b/js/src/jit-test/tests/basic/bug532823.js similarity index 100% rename from js/src/trace-test/tests/basic/bug532823.js rename to js/src/jit-test/tests/basic/bug532823.js diff --git a/js/src/trace-test/tests/basic/bug535474.js b/js/src/jit-test/tests/basic/bug535474.js similarity index 100% rename from js/src/trace-test/tests/basic/bug535474.js rename to js/src/jit-test/tests/basic/bug535474.js diff --git a/js/src/trace-test/tests/basic/bug535760.js b/js/src/jit-test/tests/basic/bug535760.js similarity index 100% rename from js/src/trace-test/tests/basic/bug535760.js rename to js/src/jit-test/tests/basic/bug535760.js diff --git a/js/src/trace-test/tests/basic/bug535930.js b/js/src/jit-test/tests/basic/bug535930.js similarity index 100% rename from js/src/trace-test/tests/basic/bug535930.js rename to js/src/jit-test/tests/basic/bug535930.js diff --git a/js/src/trace-test/tests/basic/bug536445.js b/js/src/jit-test/tests/basic/bug536445.js similarity index 100% rename from js/src/trace-test/tests/basic/bug536445.js rename to js/src/jit-test/tests/basic/bug536445.js diff --git a/js/src/trace-test/tests/basic/bug536748.js b/js/src/jit-test/tests/basic/bug536748.js similarity index 100% rename from js/src/trace-test/tests/basic/bug536748.js rename to js/src/jit-test/tests/basic/bug536748.js diff --git a/js/src/trace-test/tests/basic/bug539379.js b/js/src/jit-test/tests/basic/bug539379.js similarity index 100% rename from js/src/trace-test/tests/basic/bug539379.js rename to js/src/jit-test/tests/basic/bug539379.js diff --git a/js/src/trace-test/tests/basic/bug539553-2.js b/js/src/jit-test/tests/basic/bug539553-2.js similarity index 100% rename from js/src/trace-test/tests/basic/bug539553-2.js rename to js/src/jit-test/tests/basic/bug539553-2.js diff --git a/js/src/trace-test/tests/basic/bug539553-3.js b/js/src/jit-test/tests/basic/bug539553-3.js similarity index 100% rename from js/src/trace-test/tests/basic/bug539553-3.js rename to js/src/jit-test/tests/basic/bug539553-3.js diff --git a/js/src/trace-test/tests/basic/bug539553.js b/js/src/jit-test/tests/basic/bug539553.js similarity index 100% rename from js/src/trace-test/tests/basic/bug539553.js rename to js/src/jit-test/tests/basic/bug539553.js diff --git a/js/src/trace-test/tests/basic/bug541191-1.js b/js/src/jit-test/tests/basic/bug541191-1.js similarity index 100% rename from js/src/trace-test/tests/basic/bug541191-1.js rename to js/src/jit-test/tests/basic/bug541191-1.js diff --git a/js/src/trace-test/tests/basic/bug541191-2.js b/js/src/jit-test/tests/basic/bug541191-2.js similarity index 100% rename from js/src/trace-test/tests/basic/bug541191-2.js rename to js/src/jit-test/tests/basic/bug541191-2.js diff --git a/js/src/trace-test/tests/basic/bug541191-3.js b/js/src/jit-test/tests/basic/bug541191-3.js similarity index 100% rename from js/src/trace-test/tests/basic/bug541191-3.js rename to js/src/jit-test/tests/basic/bug541191-3.js diff --git a/js/src/trace-test/tests/basic/bug541191-4.js b/js/src/jit-test/tests/basic/bug541191-4.js similarity index 100% rename from js/src/trace-test/tests/basic/bug541191-4.js rename to js/src/jit-test/tests/basic/bug541191-4.js diff --git a/js/src/trace-test/tests/basic/bug541191-5.js b/js/src/jit-test/tests/basic/bug541191-5.js similarity index 100% rename from js/src/trace-test/tests/basic/bug541191-5.js rename to js/src/jit-test/tests/basic/bug541191-5.js diff --git a/js/src/trace-test/tests/basic/bug547911-1.js b/js/src/jit-test/tests/basic/bug547911-1.js similarity index 100% rename from js/src/trace-test/tests/basic/bug547911-1.js rename to js/src/jit-test/tests/basic/bug547911-1.js diff --git a/js/src/trace-test/tests/basic/bug547911-2.js b/js/src/jit-test/tests/basic/bug547911-2.js similarity index 100% rename from js/src/trace-test/tests/basic/bug547911-2.js rename to js/src/jit-test/tests/basic/bug547911-2.js diff --git a/js/src/trace-test/tests/basic/bug551705.js b/js/src/jit-test/tests/basic/bug551705.js similarity index 100% rename from js/src/trace-test/tests/basic/bug551705.js rename to js/src/jit-test/tests/basic/bug551705.js diff --git a/js/src/trace-test/tests/basic/bug552196.js b/js/src/jit-test/tests/basic/bug552196.js similarity index 100% rename from js/src/trace-test/tests/basic/bug552196.js rename to js/src/jit-test/tests/basic/bug552196.js diff --git a/js/src/trace-test/tests/basic/bug557168-1.js b/js/src/jit-test/tests/basic/bug557168-1.js similarity index 100% rename from js/src/trace-test/tests/basic/bug557168-1.js rename to js/src/jit-test/tests/basic/bug557168-1.js diff --git a/js/src/trace-test/tests/basic/bug557168-2.js b/js/src/jit-test/tests/basic/bug557168-2.js similarity index 100% rename from js/src/trace-test/tests/basic/bug557168-2.js rename to js/src/jit-test/tests/basic/bug557168-2.js diff --git a/js/src/trace-test/tests/basic/bug557168-3.js b/js/src/jit-test/tests/basic/bug557168-3.js similarity index 100% rename from js/src/trace-test/tests/basic/bug557168-3.js rename to js/src/jit-test/tests/basic/bug557168-3.js diff --git a/js/src/trace-test/tests/basic/bug557168.js b/js/src/jit-test/tests/basic/bug557168.js similarity index 100% rename from js/src/trace-test/tests/basic/bug557168.js rename to js/src/jit-test/tests/basic/bug557168.js diff --git a/js/src/trace-test/tests/basic/bug557841.js b/js/src/jit-test/tests/basic/bug557841.js similarity index 100% rename from js/src/trace-test/tests/basic/bug557841.js rename to js/src/jit-test/tests/basic/bug557841.js diff --git a/js/src/trace-test/tests/basic/bug558530.js b/js/src/jit-test/tests/basic/bug558530.js similarity index 100% rename from js/src/trace-test/tests/basic/bug558530.js rename to js/src/jit-test/tests/basic/bug558530.js diff --git a/js/src/trace-test/tests/basic/bug558814.js b/js/src/jit-test/tests/basic/bug558814.js similarity index 100% rename from js/src/trace-test/tests/basic/bug558814.js rename to js/src/jit-test/tests/basic/bug558814.js diff --git a/js/src/trace-test/tests/basic/bug560234.js b/js/src/jit-test/tests/basic/bug560234.js similarity index 100% rename from js/src/trace-test/tests/basic/bug560234.js rename to js/src/jit-test/tests/basic/bug560234.js diff --git a/js/src/trace-test/tests/basic/bug560234b.js b/js/src/jit-test/tests/basic/bug560234b.js similarity index 100% rename from js/src/trace-test/tests/basic/bug560234b.js rename to js/src/jit-test/tests/basic/bug560234b.js diff --git a/js/src/trace-test/tests/basic/bug561279.js b/js/src/jit-test/tests/basic/bug561279.js similarity index 100% rename from js/src/trace-test/tests/basic/bug561279.js rename to js/src/jit-test/tests/basic/bug561279.js diff --git a/js/src/trace-test/tests/basic/bug566637.js b/js/src/jit-test/tests/basic/bug566637.js similarity index 100% rename from js/src/trace-test/tests/basic/bug566637.js rename to js/src/jit-test/tests/basic/bug566637.js diff --git a/js/src/jit-test/tests/basic/bug568276.js b/js/src/jit-test/tests/basic/bug568276.js new file mode 100644 index 000000000000..4f3f6e7e5160 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug568276.js @@ -0,0 +1 @@ +function outer(a) { var b, c, d, e, f, g, h, i; function a() {} } diff --git a/js/src/trace-test/tests/basic/bug569651.js b/js/src/jit-test/tests/basic/bug569651.js similarity index 100% rename from js/src/trace-test/tests/basic/bug569651.js rename to js/src/jit-test/tests/basic/bug569651.js diff --git a/js/src/trace-test/tests/basic/bug569843.js b/js/src/jit-test/tests/basic/bug569843.js similarity index 100% rename from js/src/trace-test/tests/basic/bug569843.js rename to js/src/jit-test/tests/basic/bug569843.js diff --git a/js/src/trace-test/tests/basic/bug569849.js b/js/src/jit-test/tests/basic/bug569849.js similarity index 100% rename from js/src/trace-test/tests/basic/bug569849.js rename to js/src/jit-test/tests/basic/bug569849.js diff --git a/js/src/trace-test/tests/basic/bug570663-1.js b/js/src/jit-test/tests/basic/bug570663-1.js similarity index 100% rename from js/src/trace-test/tests/basic/bug570663-1.js rename to js/src/jit-test/tests/basic/bug570663-1.js diff --git a/js/src/trace-test/tests/basic/bug570663-2.js b/js/src/jit-test/tests/basic/bug570663-2.js similarity index 100% rename from js/src/trace-test/tests/basic/bug570663-2.js rename to js/src/jit-test/tests/basic/bug570663-2.js diff --git a/js/src/trace-test/tests/basic/bug572229.js b/js/src/jit-test/tests/basic/bug572229.js similarity index 100% rename from js/src/trace-test/tests/basic/bug572229.js rename to js/src/jit-test/tests/basic/bug572229.js diff --git a/js/src/trace-test/tests/basic/bug574280.js b/js/src/jit-test/tests/basic/bug574280.js similarity index 100% rename from js/src/trace-test/tests/basic/bug574280.js rename to js/src/jit-test/tests/basic/bug574280.js diff --git a/js/src/trace-test/tests/basic/bug576823-regexp.js b/js/src/jit-test/tests/basic/bug576823-regexp.js similarity index 100% rename from js/src/trace-test/tests/basic/bug576823-regexp.js rename to js/src/jit-test/tests/basic/bug576823-regexp.js diff --git a/js/src/trace-test/tests/basic/bug578041.js b/js/src/jit-test/tests/basic/bug578041.js similarity index 100% rename from js/src/trace-test/tests/basic/bug578041.js rename to js/src/jit-test/tests/basic/bug578041.js diff --git a/js/src/trace-test/tests/basic/bug579740.js b/js/src/jit-test/tests/basic/bug579740.js similarity index 100% rename from js/src/trace-test/tests/basic/bug579740.js rename to js/src/jit-test/tests/basic/bug579740.js diff --git a/js/src/trace-test/tests/basic/bug582479.js b/js/src/jit-test/tests/basic/bug582479.js similarity index 100% rename from js/src/trace-test/tests/basic/bug582479.js rename to js/src/jit-test/tests/basic/bug582479.js diff --git a/js/src/trace-test/tests/basic/bug583615.js b/js/src/jit-test/tests/basic/bug583615.js similarity index 84% rename from js/src/trace-test/tests/basic/bug583615.js rename to js/src/jit-test/tests/basic/bug583615.js index 4eca5ad57cae..10ba6033707e 100644 --- a/js/src/trace-test/tests/basic/bug583615.js +++ b/js/src/jit-test/tests/basic/bug583615.js @@ -1,4 +1,4 @@ -// |trace-test| slow; +// |jit-test| slow; try { x = diff --git a/js/src/trace-test/tests/basic/bug583757.js b/js/src/jit-test/tests/basic/bug583757.js similarity index 100% rename from js/src/trace-test/tests/basic/bug583757.js rename to js/src/jit-test/tests/basic/bug583757.js diff --git a/js/src/trace-test/tests/basic/bug584499-1.js b/js/src/jit-test/tests/basic/bug584499-1.js similarity index 67% rename from js/src/trace-test/tests/basic/bug584499-1.js rename to js/src/jit-test/tests/basic/bug584499-1.js index 75f346654a05..bc989537994e 100644 --- a/js/src/trace-test/tests/basic/bug584499-1.js +++ b/js/src/jit-test/tests/basic/bug584499-1.js @@ -1,4 +1,4 @@ -// |trace-test| error: TypeError +// |jit-test| error: TypeError var s = "12345"; for(var i=0; i<7; i++) { print(s[i].length); diff --git a/js/src/trace-test/tests/basic/bug584499-2.js b/js/src/jit-test/tests/basic/bug584499-2.js similarity index 100% rename from js/src/trace-test/tests/basic/bug584499-2.js rename to js/src/jit-test/tests/basic/bug584499-2.js diff --git a/js/src/trace-test/tests/basic/bug584565.js b/js/src/jit-test/tests/basic/bug584565.js similarity index 100% rename from js/src/trace-test/tests/basic/bug584565.js rename to js/src/jit-test/tests/basic/bug584565.js diff --git a/js/src/trace-test/tests/basic/bug586499-regexp.js b/js/src/jit-test/tests/basic/bug586499-regexp.js similarity index 100% rename from js/src/trace-test/tests/basic/bug586499-regexp.js rename to js/src/jit-test/tests/basic/bug586499-regexp.js diff --git a/js/src/trace-test/tests/basic/bug586917.js b/js/src/jit-test/tests/basic/bug586917.js similarity index 100% rename from js/src/trace-test/tests/basic/bug586917.js rename to js/src/jit-test/tests/basic/bug586917.js diff --git a/js/src/trace-test/tests/basic/bug587346-regexp-01.js b/js/src/jit-test/tests/basic/bug587346-regexp-01.js similarity index 100% rename from js/src/trace-test/tests/basic/bug587346-regexp-01.js rename to js/src/jit-test/tests/basic/bug587346-regexp-01.js diff --git a/js/src/trace-test/tests/basic/bug587366.js b/js/src/jit-test/tests/basic/bug587366.js similarity index 100% rename from js/src/trace-test/tests/basic/bug587366.js rename to js/src/jit-test/tests/basic/bug587366.js diff --git a/js/src/trace-test/tests/basic/bug589318.js b/js/src/jit-test/tests/basic/bug589318.js similarity index 100% rename from js/src/trace-test/tests/basic/bug589318.js rename to js/src/jit-test/tests/basic/bug589318.js diff --git a/js/src/trace-test/tests/basic/bug590006.js b/js/src/jit-test/tests/basic/bug590006.js similarity index 100% rename from js/src/trace-test/tests/basic/bug590006.js rename to js/src/jit-test/tests/basic/bug590006.js diff --git a/js/src/trace-test/tests/basic/bug592927.js b/js/src/jit-test/tests/basic/bug592927.js similarity index 100% rename from js/src/trace-test/tests/basic/bug592927.js rename to js/src/jit-test/tests/basic/bug592927.js diff --git a/js/src/trace-test/tests/basic/bug593663-regexp.js b/js/src/jit-test/tests/basic/bug593663-regexp.js similarity index 100% rename from js/src/trace-test/tests/basic/bug593663-regexp.js rename to js/src/jit-test/tests/basic/bug593663-regexp.js diff --git a/js/src/trace-test/tests/basic/bug594108.js b/js/src/jit-test/tests/basic/bug594108.js similarity index 100% rename from js/src/trace-test/tests/basic/bug594108.js rename to js/src/jit-test/tests/basic/bug594108.js diff --git a/js/src/trace-test/tests/basic/bug594205.js b/js/src/jit-test/tests/basic/bug594205.js similarity index 100% rename from js/src/trace-test/tests/basic/bug594205.js rename to js/src/jit-test/tests/basic/bug594205.js diff --git a/js/src/trace-test/tests/basic/bug595963-1.js b/js/src/jit-test/tests/basic/bug595963-1.js similarity index 100% rename from js/src/trace-test/tests/basic/bug595963-1.js rename to js/src/jit-test/tests/basic/bug595963-1.js diff --git a/js/src/trace-test/tests/basic/bug595963-2.js b/js/src/jit-test/tests/basic/bug595963-2.js similarity index 100% rename from js/src/trace-test/tests/basic/bug595963-2.js rename to js/src/jit-test/tests/basic/bug595963-2.js diff --git a/js/src/trace-test/tests/basic/bug596502-version.js b/js/src/jit-test/tests/basic/bug596502-version.js similarity index 100% rename from js/src/trace-test/tests/basic/bug596502-version.js rename to js/src/jit-test/tests/basic/bug596502-version.js diff --git a/js/src/jit-test/tests/basic/bug601395.js b/js/src/jit-test/tests/basic/bug601395.js new file mode 100644 index 000000000000..cdf61a3994d3 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug601395.js @@ -0,0 +1,2 @@ +// |jit-test| error: SyntaxError; +let(y = let(d = []) u, x diff --git a/js/src/trace-test/tests/basic/bug601398.js b/js/src/jit-test/tests/basic/bug601398.js similarity index 100% rename from js/src/trace-test/tests/basic/bug601398.js rename to js/src/jit-test/tests/basic/bug601398.js diff --git a/js/src/trace-test/tests/basic/bug601401.js b/js/src/jit-test/tests/basic/bug601401.js similarity index 100% rename from js/src/trace-test/tests/basic/bug601401.js rename to js/src/jit-test/tests/basic/bug601401.js diff --git a/js/src/trace-test/tests/basic/bug601402.js b/js/src/jit-test/tests/basic/bug601402.js similarity index 55% rename from js/src/trace-test/tests/basic/bug601402.js rename to js/src/jit-test/tests/basic/bug601402.js index bf0a79890252..33bda5a82c3a 100644 --- a/js/src/trace-test/tests/basic/bug601402.js +++ b/js/src/jit-test/tests/basic/bug601402.js @@ -1,2 +1,2 @@ -// |trace-test| error: SyntaxError; +// |jit-test| error: SyntaxError; for (let d in [(0)]) let(b = (let(e) {}), d diff --git a/js/src/jit-test/tests/basic/bug601428.js b/js/src/jit-test/tests/basic/bug601428.js new file mode 100644 index 000000000000..b9419f822c7c --- /dev/null +++ b/js/src/jit-test/tests/basic/bug601428.js @@ -0,0 +1,2 @@ +// |jit-test| error: SyntaxError; +let({}=[c for(x in[])]){let diff --git a/js/src/trace-test/tests/basic/bug602088.js b/js/src/jit-test/tests/basic/bug602088.js similarity index 79% rename from js/src/trace-test/tests/basic/bug602088.js rename to js/src/jit-test/tests/basic/bug602088.js index f868dd9b53ce..283b546acc3c 100644 --- a/js/src/trace-test/tests/basic/bug602088.js +++ b/js/src/jit-test/tests/basic/bug602088.js @@ -1,4 +1,4 @@ -// |trace-test| error: TypeError +// |jit-test| error: TypeError /* vim: set ts=4 sw=4 tw=99 et: */ var p = Proxy.createFunction({}, function(x, y) { undefined.x(); }); diff --git a/js/src/trace-test/tests/basic/call.js b/js/src/jit-test/tests/basic/call.js similarity index 100% rename from js/src/trace-test/tests/basic/call.js rename to js/src/jit-test/tests/basic/call.js diff --git a/js/src/trace-test/tests/basic/call2.js b/js/src/jit-test/tests/basic/call2.js similarity index 100% rename from js/src/trace-test/tests/basic/call2.js rename to js/src/jit-test/tests/basic/call2.js diff --git a/js/src/trace-test/tests/basic/createMandelSet.js b/js/src/jit-test/tests/basic/createMandelSet.js similarity index 99% rename from js/src/trace-test/tests/basic/createMandelSet.js rename to js/src/jit-test/tests/basic/createMandelSet.js index d2e7c134e72f..9898b5dc9d38 100644 --- a/js/src/trace-test/tests/basic/createMandelSet.js +++ b/js/src/jit-test/tests/basic/createMandelSet.js @@ -1,4 +1,4 @@ -// |trace-test| slow; +// |jit-test| slow; // XXXbz I would dearly like to wrap it up into a function to avoid polluting // the global scope, but the function ends up heavyweight, and then we lose on diff --git a/js/src/trace-test/tests/basic/deep2.js b/js/src/jit-test/tests/basic/deep2.js similarity index 100% rename from js/src/trace-test/tests/basic/deep2.js rename to js/src/jit-test/tests/basic/deep2.js diff --git a/js/src/trace-test/tests/basic/deepForInLoop.js b/js/src/jit-test/tests/basic/deepForInLoop.js similarity index 100% rename from js/src/trace-test/tests/basic/deepForInLoop.js rename to js/src/jit-test/tests/basic/deepForInLoop.js diff --git a/js/src/trace-test/tests/basic/delete-array-elements.js b/js/src/jit-test/tests/basic/delete-array-elements.js similarity index 100% rename from js/src/trace-test/tests/basic/delete-array-elements.js rename to js/src/jit-test/tests/basic/delete-array-elements.js diff --git a/js/src/trace-test/tests/basic/delete-indexed-names.js b/js/src/jit-test/tests/basic/delete-indexed-names.js similarity index 100% rename from js/src/trace-test/tests/basic/delete-indexed-names.js rename to js/src/jit-test/tests/basic/delete-indexed-names.js diff --git a/js/src/jit-test/tests/basic/delete-integer-nonid.js b/js/src/jit-test/tests/basic/delete-integer-nonid.js new file mode 100644 index 000000000000..e016227cbab5 --- /dev/null +++ b/js/src/jit-test/tests/basic/delete-integer-nonid.js @@ -0,0 +1,24 @@ +var JSID_INT_MIN = -(1 << 30); +var JSID_INT_MAX = (1 << 30) - 1; + +var o = {}; + + +for (var i = 0; i < 10; i++) + delete o[JSID_INT_MIN - 1]; + +for (var i = 0; i < 10; i++) + delete o[JSID_INT_MIN]; + +for (var i = 0; i < 10; i++) + delete o[JSID_INT_MIN + 1]; + + +for (var i = 0; i < 10; i++) + delete o[JSID_INT_MAX - 1]; + +for (var i = 0; i < 10; i++) + delete o[JSID_INT_MAX]; + +for (var i = 0; i < 10; i++) + delete o[JSID_INT_MAX + 1]; diff --git a/js/src/trace-test/tests/basic/delete-named-names.js b/js/src/jit-test/tests/basic/delete-named-names.js similarity index 100% rename from js/src/trace-test/tests/basic/delete-named-names.js rename to js/src/jit-test/tests/basic/delete-named-names.js diff --git a/js/src/trace-test/tests/basic/delete-non-config.js b/js/src/jit-test/tests/basic/delete-non-config.js similarity index 100% rename from js/src/trace-test/tests/basic/delete-non-config.js rename to js/src/jit-test/tests/basic/delete-non-config.js diff --git a/js/src/trace-test/tests/basic/dependentStrings.js b/js/src/jit-test/tests/basic/dependentStrings.js similarity index 100% rename from js/src/trace-test/tests/basic/dependentStrings.js rename to js/src/jit-test/tests/basic/dependentStrings.js diff --git a/js/src/trace-test/tests/basic/doMath.js b/js/src/jit-test/tests/basic/doMath.js similarity index 100% rename from js/src/trace-test/tests/basic/doMath.js rename to js/src/jit-test/tests/basic/doMath.js diff --git a/js/src/trace-test/tests/basic/equalInt.js b/js/src/jit-test/tests/basic/equalInt.js similarity index 100% rename from js/src/trace-test/tests/basic/equalInt.js rename to js/src/jit-test/tests/basic/equalInt.js diff --git a/js/src/trace-test/tests/basic/fannkuch.js b/js/src/jit-test/tests/basic/fannkuch.js similarity index 100% rename from js/src/trace-test/tests/basic/fannkuch.js rename to js/src/jit-test/tests/basic/fannkuch.js diff --git a/js/src/trace-test/tests/basic/firstSlotConflict.js b/js/src/jit-test/tests/basic/firstSlotConflict.js similarity index 100% rename from js/src/trace-test/tests/basic/firstSlotConflict.js rename to js/src/jit-test/tests/basic/firstSlotConflict.js diff --git a/js/src/trace-test/tests/basic/forVarInWith.js b/js/src/jit-test/tests/basic/forVarInWith.js similarity index 100% rename from js/src/trace-test/tests/basic/forVarInWith.js rename to js/src/jit-test/tests/basic/forVarInWith.js diff --git a/js/src/trace-test/tests/basic/function-bind.js b/js/src/jit-test/tests/basic/function-bind.js similarity index 100% rename from js/src/trace-test/tests/basic/function-bind.js rename to js/src/jit-test/tests/basic/function-bind.js diff --git a/js/src/trace-test/tests/basic/getelem.js b/js/src/jit-test/tests/basic/getelem.js similarity index 100% rename from js/src/trace-test/tests/basic/getelem.js rename to js/src/jit-test/tests/basic/getelem.js diff --git a/js/src/trace-test/tests/basic/getprop.js b/js/src/jit-test/tests/basic/getprop.js similarity index 100% rename from js/src/trace-test/tests/basic/getprop.js rename to js/src/jit-test/tests/basic/getprop.js diff --git a/js/src/trace-test/tests/basic/globalGet.js b/js/src/jit-test/tests/basic/globalGet.js similarity index 100% rename from js/src/trace-test/tests/basic/globalGet.js rename to js/src/jit-test/tests/basic/globalGet.js diff --git a/js/src/trace-test/tests/basic/globalOptimize-1.js b/js/src/jit-test/tests/basic/globalOptimize-1.js similarity index 100% rename from js/src/trace-test/tests/basic/globalOptimize-1.js rename to js/src/jit-test/tests/basic/globalOptimize-1.js diff --git a/js/src/trace-test/tests/basic/globalSet.js b/js/src/jit-test/tests/basic/globalSet.js similarity index 100% rename from js/src/trace-test/tests/basic/globalSet.js rename to js/src/jit-test/tests/basic/globalSet.js diff --git a/js/src/trace-test/tests/basic/ifInsideLoop.js b/js/src/jit-test/tests/basic/ifInsideLoop.js similarity index 100% rename from js/src/trace-test/tests/basic/ifInsideLoop.js rename to js/src/jit-test/tests/basic/ifInsideLoop.js diff --git a/js/src/trace-test/tests/basic/inArrayTest.js b/js/src/jit-test/tests/basic/inArrayTest.js similarity index 100% rename from js/src/trace-test/tests/basic/inArrayTest.js rename to js/src/jit-test/tests/basic/inArrayTest.js diff --git a/js/src/trace-test/tests/basic/inObjectTest.js b/js/src/jit-test/tests/basic/inObjectTest.js similarity index 100% rename from js/src/trace-test/tests/basic/inObjectTest.js rename to js/src/jit-test/tests/basic/inObjectTest.js diff --git a/js/src/trace-test/tests/basic/innerLoopIntOuterDouble.js b/js/src/jit-test/tests/basic/innerLoopIntOuterDouble.js similarity index 100% rename from js/src/trace-test/tests/basic/innerLoopIntOuterDouble.js rename to js/src/jit-test/tests/basic/innerLoopIntOuterDouble.js diff --git a/js/src/trace-test/tests/basic/inner_double_outer_int.js b/js/src/jit-test/tests/basic/inner_double_outer_int.js similarity index 100% rename from js/src/trace-test/tests/basic/inner_double_outer_int.js rename to js/src/jit-test/tests/basic/inner_double_outer_int.js diff --git a/js/src/trace-test/tests/basic/jitstatsArchFlags.js b/js/src/jit-test/tests/basic/jitstatsArchFlags.js similarity index 100% rename from js/src/trace-test/tests/basic/jitstatsArchFlags.js rename to js/src/jit-test/tests/basic/jitstatsArchFlags.js diff --git a/js/src/trace-test/tests/basic/joinTest.js b/js/src/jit-test/tests/basic/joinTest.js similarity index 100% rename from js/src/trace-test/tests/basic/joinTest.js rename to js/src/jit-test/tests/basic/joinTest.js diff --git a/js/src/trace-test/tests/basic/matchInLoop.js b/js/src/jit-test/tests/basic/matchInLoop.js similarity index 100% rename from js/src/trace-test/tests/basic/matchInLoop.js rename to js/src/jit-test/tests/basic/matchInLoop.js diff --git a/js/src/trace-test/tests/basic/math-trace-tests.js b/js/src/jit-test/tests/basic/math-jit-tests.js similarity index 100% rename from js/src/trace-test/tests/basic/math-trace-tests.js rename to js/src/jit-test/tests/basic/math-jit-tests.js diff --git a/js/src/trace-test/tests/basic/merge_type_maps.js b/js/src/jit-test/tests/basic/merge_type_maps.js similarity index 100% rename from js/src/trace-test/tests/basic/merge_type_maps.js rename to js/src/jit-test/tests/basic/merge_type_maps.js diff --git a/js/src/trace-test/tests/basic/missingArgTest.js b/js/src/jit-test/tests/basic/missingArgTest.js similarity index 100% rename from js/src/trace-test/tests/basic/missingArgTest.js rename to js/src/jit-test/tests/basic/missingArgTest.js diff --git a/js/src/trace-test/tests/basic/missingArgTest2.js b/js/src/jit-test/tests/basic/missingArgTest2.js similarity index 100% rename from js/src/trace-test/tests/basic/missingArgTest2.js rename to js/src/jit-test/tests/basic/missingArgTest2.js diff --git a/js/src/trace-test/tests/basic/mod.js b/js/src/jit-test/tests/basic/mod.js similarity index 100% rename from js/src/trace-test/tests/basic/mod.js rename to js/src/jit-test/tests/basic/mod.js diff --git a/js/src/trace-test/tests/basic/name-inactive-del.js b/js/src/jit-test/tests/basic/name-inactive-del.js similarity index 100% rename from js/src/trace-test/tests/basic/name-inactive-del.js rename to js/src/jit-test/tests/basic/name-inactive-del.js diff --git a/js/src/trace-test/tests/basic/name-inactive-eval-del.js b/js/src/jit-test/tests/basic/name-inactive-eval-del.js similarity index 100% rename from js/src/trace-test/tests/basic/name-inactive-eval-del.js rename to js/src/jit-test/tests/basic/name-inactive-eval-del.js diff --git a/js/src/trace-test/tests/basic/name-inactive-inferflags.js b/js/src/jit-test/tests/basic/name-inactive-inferflags.js similarity index 100% rename from js/src/trace-test/tests/basic/name-inactive-inferflags.js rename to js/src/jit-test/tests/basic/name-inactive-inferflags.js diff --git a/js/src/trace-test/tests/basic/name-inactive.js b/js/src/jit-test/tests/basic/name-inactive.js similarity index 100% rename from js/src/trace-test/tests/basic/name-inactive.js rename to js/src/jit-test/tests/basic/name-inactive.js diff --git a/js/src/trace-test/tests/basic/name.js b/js/src/jit-test/tests/basic/name.js similarity index 100% rename from js/src/trace-test/tests/basic/name.js rename to js/src/jit-test/tests/basic/name.js diff --git a/js/src/trace-test/tests/basic/nestedExit2.js b/js/src/jit-test/tests/basic/nestedExit2.js similarity index 100% rename from js/src/trace-test/tests/basic/nestedExit2.js rename to js/src/jit-test/tests/basic/nestedExit2.js diff --git a/js/src/trace-test/tests/basic/nestedExitLoop.js b/js/src/jit-test/tests/basic/nestedExitLoop.js similarity index 100% rename from js/src/trace-test/tests/basic/nestedExitLoop.js rename to js/src/jit-test/tests/basic/nestedExitLoop.js diff --git a/js/src/trace-test/tests/basic/newArrayTest.js b/js/src/jit-test/tests/basic/newArrayTest.js similarity index 100% rename from js/src/trace-test/tests/basic/newArrayTest.js rename to js/src/jit-test/tests/basic/newArrayTest.js diff --git a/js/src/trace-test/tests/basic/newTest.js b/js/src/jit-test/tests/basic/newTest.js similarity index 100% rename from js/src/trace-test/tests/basic/newTest.js rename to js/src/jit-test/tests/basic/newTest.js diff --git a/js/src/trace-test/tests/basic/nonEmptyStack1.js b/js/src/jit-test/tests/basic/nonEmptyStack1.js similarity index 100% rename from js/src/trace-test/tests/basic/nonEmptyStack1.js rename to js/src/jit-test/tests/basic/nonEmptyStack1.js diff --git a/js/src/trace-test/tests/basic/nonEmptyStack2.js b/js/src/jit-test/tests/basic/nonEmptyStack2.js similarity index 100% rename from js/src/trace-test/tests/basic/nonEmptyStack2.js rename to js/src/jit-test/tests/basic/nonEmptyStack2.js diff --git a/js/src/trace-test/tests/basic/orNaNTest1.js b/js/src/jit-test/tests/basic/orNaNTest1.js similarity index 100% rename from js/src/trace-test/tests/basic/orNaNTest1.js rename to js/src/jit-test/tests/basic/orNaNTest1.js diff --git a/js/src/trace-test/tests/basic/orNaNTest2.js b/js/src/jit-test/tests/basic/orNaNTest2.js similarity index 100% rename from js/src/trace-test/tests/basic/orNaNTest2.js rename to js/src/jit-test/tests/basic/orNaNTest2.js diff --git a/js/src/trace-test/tests/basic/outerline.js b/js/src/jit-test/tests/basic/outerline.js similarity index 100% rename from js/src/trace-test/tests/basic/outerline.js rename to js/src/jit-test/tests/basic/outerline.js diff --git a/js/src/trace-test/tests/basic/parseIntTests.js b/js/src/jit-test/tests/basic/parseIntTests.js similarity index 100% rename from js/src/trace-test/tests/basic/parseIntTests.js rename to js/src/jit-test/tests/basic/parseIntTests.js diff --git a/js/src/trace-test/tests/basic/parsingNumbers.js b/js/src/jit-test/tests/basic/parsingNumbers.js similarity index 100% rename from js/src/trace-test/tests/basic/parsingNumbers.js rename to js/src/jit-test/tests/basic/parsingNumbers.js diff --git a/js/src/trace-test/tests/basic/perf-smoketest.js b/js/src/jit-test/tests/basic/perf-smoketest.js similarity index 100% rename from js/src/trace-test/tests/basic/perf-smoketest.js rename to js/src/jit-test/tests/basic/perf-smoketest.js diff --git a/js/src/trace-test/tests/basic/putargsNoReturn.js b/js/src/jit-test/tests/basic/putargsNoReturn.js similarity index 100% rename from js/src/trace-test/tests/basic/putargsNoReturn.js rename to js/src/jit-test/tests/basic/putargsNoReturn.js diff --git a/js/src/trace-test/tests/basic/putargsReturn.js b/js/src/jit-test/tests/basic/putargsReturn.js similarity index 100% rename from js/src/trace-test/tests/basic/putargsReturn.js rename to js/src/jit-test/tests/basic/putargsReturn.js diff --git a/js/src/trace-test/tests/basic/regexpLastIndex.js b/js/src/jit-test/tests/basic/regexpLastIndex.js similarity index 100% rename from js/src/trace-test/tests/basic/regexpLastIndex.js rename to js/src/jit-test/tests/basic/regexpLastIndex.js diff --git a/js/src/trace-test/tests/basic/setArgumentsLength.js b/js/src/jit-test/tests/basic/setArgumentsLength.js similarity index 100% rename from js/src/trace-test/tests/basic/setArgumentsLength.js rename to js/src/jit-test/tests/basic/setArgumentsLength.js diff --git a/js/src/trace-test/tests/basic/setArgumentsLength2.js b/js/src/jit-test/tests/basic/setArgumentsLength2.js similarity index 100% rename from js/src/trace-test/tests/basic/setArgumentsLength2.js rename to js/src/jit-test/tests/basic/setArgumentsLength2.js diff --git a/js/src/trace-test/tests/basic/setCall.js b/js/src/jit-test/tests/basic/setCall.js similarity index 100% rename from js/src/trace-test/tests/basic/setCall.js rename to js/src/jit-test/tests/basic/setCall.js diff --git a/js/src/trace-test/tests/basic/setCallEvalMiddle.js b/js/src/jit-test/tests/basic/setCallEvalMiddle.js similarity index 100% rename from js/src/trace-test/tests/basic/setCallEvalMiddle.js rename to js/src/jit-test/tests/basic/setCallEvalMiddle.js diff --git a/js/src/trace-test/tests/basic/setCallEvalMiddle2.js b/js/src/jit-test/tests/basic/setCallEvalMiddle2.js similarity index 100% rename from js/src/trace-test/tests/basic/setCallEvalMiddle2.js rename to js/src/jit-test/tests/basic/setCallEvalMiddle2.js diff --git a/js/src/trace-test/tests/basic/setCallGlobal.js b/js/src/jit-test/tests/basic/setCallGlobal.js similarity index 100% rename from js/src/trace-test/tests/basic/setCallGlobal.js rename to js/src/jit-test/tests/basic/setCallGlobal.js diff --git a/js/src/trace-test/tests/basic/setelem.js b/js/src/jit-test/tests/basic/setelem.js similarity index 100% rename from js/src/trace-test/tests/basic/setelem.js rename to js/src/jit-test/tests/basic/setelem.js diff --git a/js/src/trace-test/tests/basic/setprop.js b/js/src/jit-test/tests/basic/setprop.js similarity index 100% rename from js/src/trace-test/tests/basic/setprop.js rename to js/src/jit-test/tests/basic/setprop.js diff --git a/js/src/trace-test/tests/basic/shapelessCalleeTest.js b/js/src/jit-test/tests/basic/shapelessCalleeTest.js similarity index 100% rename from js/src/trace-test/tests/basic/shapelessCalleeTest.js rename to js/src/jit-test/tests/basic/shapelessCalleeTest.js diff --git a/js/src/trace-test/tests/basic/strictParseIntOctal.js b/js/src/jit-test/tests/basic/strictParseIntOctal.js similarity index 100% rename from js/src/trace-test/tests/basic/strictParseIntOctal.js rename to js/src/jit-test/tests/basic/strictParseIntOctal.js diff --git a/js/src/trace-test/tests/basic/stringConvert.js b/js/src/jit-test/tests/basic/stringConvert.js similarity index 100% rename from js/src/trace-test/tests/basic/stringConvert.js rename to js/src/jit-test/tests/basic/stringConvert.js diff --git a/js/src/trace-test/tests/basic/stringSplitIntoArrayTest.js b/js/src/jit-test/tests/basic/stringSplitIntoArrayTest.js similarity index 100% rename from js/src/trace-test/tests/basic/stringSplitIntoArrayTest.js rename to js/src/jit-test/tests/basic/stringSplitIntoArrayTest.js diff --git a/js/src/trace-test/tests/basic/stringSplitTest.js b/js/src/jit-test/tests/basic/stringSplitTest.js similarity index 100% rename from js/src/trace-test/tests/basic/stringSplitTest.js rename to js/src/jit-test/tests/basic/stringSplitTest.js diff --git a/js/src/trace-test/tests/basic/strings.js b/js/src/jit-test/tests/basic/strings.js similarity index 100% rename from js/src/trace-test/tests/basic/strings.js rename to js/src/jit-test/tests/basic/strings.js diff --git a/js/src/trace-test/tests/basic/test586387.js b/js/src/jit-test/tests/basic/test586387.js similarity index 100% rename from js/src/trace-test/tests/basic/test586387.js rename to js/src/jit-test/tests/basic/test586387.js diff --git a/js/src/trace-test/tests/basic/testAbortedImacroDecompilation.js b/js/src/jit-test/tests/basic/testAbortedImacroDecompilation.js similarity index 100% rename from js/src/trace-test/tests/basic/testAbortedImacroDecompilation.js rename to js/src/jit-test/tests/basic/testAbortedImacroDecompilation.js diff --git a/js/src/trace-test/tests/basic/testAccessCanonicalArgInGetElem.js b/js/src/jit-test/tests/basic/testAccessCanonicalArgInGetElem.js similarity index 100% rename from js/src/trace-test/tests/basic/testAccessCanonicalArgInGetElem.js rename to js/src/jit-test/tests/basic/testAccessCanonicalArgInGetElem.js diff --git a/js/src/trace-test/tests/basic/testAddAnyInconvertibleObject.js b/js/src/jit-test/tests/basic/testAddAnyInconvertibleObject.js similarity index 100% rename from js/src/trace-test/tests/basic/testAddAnyInconvertibleObject.js rename to js/src/jit-test/tests/basic/testAddAnyInconvertibleObject.js diff --git a/js/src/trace-test/tests/basic/testAddInconvertibleObjectAny.js b/js/src/jit-test/tests/basic/testAddInconvertibleObjectAny.js similarity index 100% rename from js/src/trace-test/tests/basic/testAddInconvertibleObjectAny.js rename to js/src/jit-test/tests/basic/testAddInconvertibleObjectAny.js diff --git a/js/src/trace-test/tests/basic/testAddInconvertibleObjectInconvertibleObject.js b/js/src/jit-test/tests/basic/testAddInconvertibleObjectInconvertibleObject.js similarity index 100% rename from js/src/trace-test/tests/basic/testAddInconvertibleObjectInconvertibleObject.js rename to js/src/jit-test/tests/basic/testAddInconvertibleObjectInconvertibleObject.js diff --git a/js/src/trace-test/tests/basic/testAddNull.js b/js/src/jit-test/tests/basic/testAddNull.js similarity index 100% rename from js/src/trace-test/tests/basic/testAddNull.js rename to js/src/jit-test/tests/basic/testAddNull.js diff --git a/js/src/trace-test/tests/basic/testAddUndefined.js b/js/src/jit-test/tests/basic/testAddUndefined.js similarity index 100% rename from js/src/trace-test/tests/basic/testAddUndefined.js rename to js/src/jit-test/tests/basic/testAddUndefined.js diff --git a/js/src/trace-test/tests/basic/testApply.js b/js/src/jit-test/tests/basic/testApply.js similarity index 100% rename from js/src/trace-test/tests/basic/testApply.js rename to js/src/jit-test/tests/basic/testApply.js diff --git a/js/src/trace-test/tests/basic/testApplyCall.js b/js/src/jit-test/tests/basic/testApplyCall.js similarity index 100% rename from js/src/trace-test/tests/basic/testApplyCall.js rename to js/src/jit-test/tests/basic/testApplyCall.js diff --git a/js/src/trace-test/tests/basic/testApplyUnbox.js b/js/src/jit-test/tests/basic/testApplyUnbox.js similarity index 100% rename from js/src/trace-test/tests/basic/testApplyUnbox.js rename to js/src/jit-test/tests/basic/testApplyUnbox.js diff --git a/js/src/trace-test/tests/basic/testArrayComp1.js b/js/src/jit-test/tests/basic/testArrayComp1.js similarity index 100% rename from js/src/trace-test/tests/basic/testArrayComp1.js rename to js/src/jit-test/tests/basic/testArrayComp1.js diff --git a/js/src/trace-test/tests/basic/testArrayComp2.js b/js/src/jit-test/tests/basic/testArrayComp2.js similarity index 100% rename from js/src/trace-test/tests/basic/testArrayComp2.js rename to js/src/jit-test/tests/basic/testArrayComp2.js diff --git a/js/src/trace-test/tests/basic/testArrayDensityChange.js b/js/src/jit-test/tests/basic/testArrayDensityChange.js similarity index 100% rename from js/src/trace-test/tests/basic/testArrayDensityChange.js rename to js/src/jit-test/tests/basic/testArrayDensityChange.js diff --git a/js/src/trace-test/tests/basic/testArrayNaNIndex.js b/js/src/jit-test/tests/basic/testArrayNaNIndex.js similarity index 100% rename from js/src/trace-test/tests/basic/testArrayNaNIndex.js rename to js/src/jit-test/tests/basic/testArrayNaNIndex.js diff --git a/js/src/trace-test/tests/basic/testArrayNamedProp.js b/js/src/jit-test/tests/basic/testArrayNamedProp.js similarity index 100% rename from js/src/trace-test/tests/basic/testArrayNamedProp.js rename to js/src/jit-test/tests/basic/testArrayNamedProp.js diff --git a/js/src/trace-test/tests/basic/testArrayPushPop.js b/js/src/jit-test/tests/basic/testArrayPushPop.js similarity index 100% rename from js/src/trace-test/tests/basic/testArrayPushPop.js rename to js/src/jit-test/tests/basic/testArrayPushPop.js diff --git a/js/src/trace-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js b/js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js similarity index 100% rename from js/src/trace-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js rename to js/src/jit-test/tests/basic/testAssignmentThatIgnoresSetterRetval.js diff --git a/js/src/trace-test/tests/basic/testAtomize.js b/js/src/jit-test/tests/basic/testAtomize.js similarity index 100% rename from js/src/trace-test/tests/basic/testAtomize.js rename to js/src/jit-test/tests/basic/testAtomize.js diff --git a/js/src/trace-test/tests/basic/testBitOrAnyInconvertibleObject.js b/js/src/jit-test/tests/basic/testBitOrAnyInconvertibleObject.js similarity index 100% rename from js/src/trace-test/tests/basic/testBitOrAnyInconvertibleObject.js rename to js/src/jit-test/tests/basic/testBitOrAnyInconvertibleObject.js diff --git a/js/src/trace-test/tests/basic/testBitOrInconvertibleObjectAny.js b/js/src/jit-test/tests/basic/testBitOrInconvertibleObjectAny.js similarity index 100% rename from js/src/trace-test/tests/basic/testBitOrInconvertibleObjectAny.js rename to js/src/jit-test/tests/basic/testBitOrInconvertibleObjectAny.js diff --git a/js/src/trace-test/tests/basic/testBitOrInconvertibleObjectInconvertibleObject.js b/js/src/jit-test/tests/basic/testBitOrInconvertibleObjectInconvertibleObject.js similarity index 100% rename from js/src/trace-test/tests/basic/testBitOrInconvertibleObjectInconvertibleObject.js rename to js/src/jit-test/tests/basic/testBitOrInconvertibleObjectInconvertibleObject.js diff --git a/js/src/trace-test/tests/basic/testBitwise.js b/js/src/jit-test/tests/basic/testBitwise.js similarity index 100% rename from js/src/trace-test/tests/basic/testBitwise.js rename to js/src/jit-test/tests/basic/testBitwise.js diff --git a/js/src/jit-test/tests/basic/testBoolToString.js b/js/src/jit-test/tests/basic/testBoolToString.js new file mode 100644 index 000000000000..9eeb40c5d5dd --- /dev/null +++ b/js/src/jit-test/tests/basic/testBoolToString.js @@ -0,0 +1,3 @@ +// |jit-test| error: TypeError; +var bts = true.toString; +bts(); diff --git a/js/src/trace-test/tests/basic/testBoxDoubleWithDoubleSizedInt.js b/js/src/jit-test/tests/basic/testBoxDoubleWithDoubleSizedInt.js similarity index 100% rename from js/src/trace-test/tests/basic/testBoxDoubleWithDoubleSizedInt.js rename to js/src/jit-test/tests/basic/testBoxDoubleWithDoubleSizedInt.js diff --git a/js/src/trace-test/tests/basic/testBranchCse.js b/js/src/jit-test/tests/basic/testBranchCse.js similarity index 100% rename from js/src/trace-test/tests/basic/testBranchCse.js rename to js/src/jit-test/tests/basic/testBranchCse.js diff --git a/js/src/trace-test/tests/basic/testBranchingLoop.js b/js/src/jit-test/tests/basic/testBranchingLoop.js similarity index 100% rename from js/src/trace-test/tests/basic/testBranchingLoop.js rename to js/src/jit-test/tests/basic/testBranchingLoop.js diff --git a/js/src/trace-test/tests/basic/testBranchingUnstableLoop.js b/js/src/jit-test/tests/basic/testBranchingUnstableLoop.js similarity index 100% rename from js/src/trace-test/tests/basic/testBranchingUnstableLoop.js rename to js/src/jit-test/tests/basic/testBranchingUnstableLoop.js diff --git a/js/src/trace-test/tests/basic/testBranchingUnstableLoopCounter.js b/js/src/jit-test/tests/basic/testBranchingUnstableLoopCounter.js similarity index 100% rename from js/src/trace-test/tests/basic/testBranchingUnstableLoopCounter.js rename to js/src/jit-test/tests/basic/testBranchingUnstableLoopCounter.js diff --git a/js/src/trace-test/tests/basic/testBranchingUnstableObject.js b/js/src/jit-test/tests/basic/testBranchingUnstableObject.js similarity index 100% rename from js/src/trace-test/tests/basic/testBranchingUnstableObject.js rename to js/src/jit-test/tests/basic/testBranchingUnstableObject.js diff --git a/js/src/trace-test/tests/basic/testBrandedVsGeneric.js b/js/src/jit-test/tests/basic/testBrandedVsGeneric.js similarity index 100% rename from js/src/trace-test/tests/basic/testBrandedVsGeneric.js rename to js/src/jit-test/tests/basic/testBrandedVsGeneric.js diff --git a/js/src/trace-test/tests/basic/testBreak.js b/js/src/jit-test/tests/basic/testBreak.js similarity index 100% rename from js/src/trace-test/tests/basic/testBreak.js rename to js/src/jit-test/tests/basic/testBreak.js diff --git a/js/src/trace-test/tests/basic/testBug458838.js b/js/src/jit-test/tests/basic/testBug458838.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug458838.js rename to js/src/jit-test/tests/basic/testBug458838.js diff --git a/js/src/trace-test/tests/basic/testBug462388.js b/js/src/jit-test/tests/basic/testBug462388.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug462388.js rename to js/src/jit-test/tests/basic/testBug462388.js diff --git a/js/src/trace-test/tests/basic/testBug462407.js b/js/src/jit-test/tests/basic/testBug462407.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug462407.js rename to js/src/jit-test/tests/basic/testBug462407.js diff --git a/js/src/trace-test/tests/basic/testBug463490.js b/js/src/jit-test/tests/basic/testBug463490.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug463490.js rename to js/src/jit-test/tests/basic/testBug463490.js diff --git a/js/src/trace-test/tests/basic/testBug465261.js b/js/src/jit-test/tests/basic/testBug465261.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug465261.js rename to js/src/jit-test/tests/basic/testBug465261.js diff --git a/js/src/trace-test/tests/basic/testBug465272.js b/js/src/jit-test/tests/basic/testBug465272.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug465272.js rename to js/src/jit-test/tests/basic/testBug465272.js diff --git a/js/src/trace-test/tests/basic/testBug465483.js b/js/src/jit-test/tests/basic/testBug465483.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug465483.js rename to js/src/jit-test/tests/basic/testBug465483.js diff --git a/js/src/trace-test/tests/basic/testBug465688.js b/js/src/jit-test/tests/basic/testBug465688.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug465688.js rename to js/src/jit-test/tests/basic/testBug465688.js diff --git a/js/src/trace-test/tests/basic/testBug466128.js b/js/src/jit-test/tests/basic/testBug466128.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug466128.js rename to js/src/jit-test/tests/basic/testBug466128.js diff --git a/js/src/trace-test/tests/basic/testBug466262.js b/js/src/jit-test/tests/basic/testBug466262.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug466262.js rename to js/src/jit-test/tests/basic/testBug466262.js diff --git a/js/src/trace-test/tests/basic/testBug474769.js b/js/src/jit-test/tests/basic/testBug474769.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug474769.js rename to js/src/jit-test/tests/basic/testBug474769.js diff --git a/js/src/trace-test/tests/basic/testBug501690.js b/js/src/jit-test/tests/basic/testBug501690.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug501690.js rename to js/src/jit-test/tests/basic/testBug501690.js diff --git a/js/src/trace-test/tests/basic/testBug502914.js b/js/src/jit-test/tests/basic/testBug502914.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug502914.js rename to js/src/jit-test/tests/basic/testBug502914.js diff --git a/js/src/trace-test/tests/basic/testBug504520.js b/js/src/jit-test/tests/basic/testBug504520.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug504520.js rename to js/src/jit-test/tests/basic/testBug504520.js diff --git a/js/src/trace-test/tests/basic/testBug504520Harder.js b/js/src/jit-test/tests/basic/testBug504520Harder.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug504520Harder.js rename to js/src/jit-test/tests/basic/testBug504520Harder.js diff --git a/js/src/trace-test/tests/basic/testBug507425.js b/js/src/jit-test/tests/basic/testBug507425.js similarity index 92% rename from js/src/trace-test/tests/basic/testBug507425.js rename to js/src/jit-test/tests/basic/testBug507425.js index d55d11f88ada..616bababdebd 100644 --- a/js/src/trace-test/tests/basic/testBug507425.js +++ b/js/src/jit-test/tests/basic/testBug507425.js @@ -1,4 +1,4 @@ -// |trace-test| allow-oom; +// |jit-test| allow-oom; function testBug507425() { var r = /x/; for (var i = 0; i < 3; i++) diff --git a/js/src/trace-test/tests/basic/testBug520503-1.js b/js/src/jit-test/tests/basic/testBug520503-1.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug520503-1.js rename to js/src/jit-test/tests/basic/testBug520503-1.js diff --git a/js/src/trace-test/tests/basic/testBug520503-2.js b/js/src/jit-test/tests/basic/testBug520503-2.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug520503-2.js rename to js/src/jit-test/tests/basic/testBug520503-2.js diff --git a/js/src/trace-test/tests/basic/testBug520503-3.js b/js/src/jit-test/tests/basic/testBug520503-3.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug520503-3.js rename to js/src/jit-test/tests/basic/testBug520503-3.js diff --git a/js/src/trace-test/tests/basic/testBug529147.js b/js/src/jit-test/tests/basic/testBug529147.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug529147.js rename to js/src/jit-test/tests/basic/testBug529147.js diff --git a/js/src/trace-test/tests/basic/testBug547791.js b/js/src/jit-test/tests/basic/testBug547791.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug547791.js rename to js/src/jit-test/tests/basic/testBug547791.js diff --git a/js/src/trace-test/tests/basic/testBug550210.js b/js/src/jit-test/tests/basic/testBug550210.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug550210.js rename to js/src/jit-test/tests/basic/testBug550210.js diff --git a/js/src/trace-test/tests/basic/testBug552248.js b/js/src/jit-test/tests/basic/testBug552248.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug552248.js rename to js/src/jit-test/tests/basic/testBug552248.js diff --git a/js/src/trace-test/tests/basic/testBug554043.js b/js/src/jit-test/tests/basic/testBug554043.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug554043.js rename to js/src/jit-test/tests/basic/testBug554043.js diff --git a/js/src/trace-test/tests/basic/testBug555484.js b/js/src/jit-test/tests/basic/testBug555484.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug555484.js rename to js/src/jit-test/tests/basic/testBug555484.js diff --git a/js/src/trace-test/tests/basic/testBug558446.js b/js/src/jit-test/tests/basic/testBug558446.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug558446.js rename to js/src/jit-test/tests/basic/testBug558446.js diff --git a/js/src/trace-test/tests/basic/testBug560098.js b/js/src/jit-test/tests/basic/testBug560098.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug560098.js rename to js/src/jit-test/tests/basic/testBug560098.js diff --git a/js/src/trace-test/tests/basic/testBug566556.js b/js/src/jit-test/tests/basic/testBug566556.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug566556.js rename to js/src/jit-test/tests/basic/testBug566556.js diff --git a/js/src/trace-test/tests/basic/testBug578044.js b/js/src/jit-test/tests/basic/testBug578044.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug578044.js rename to js/src/jit-test/tests/basic/testBug578044.js diff --git a/js/src/trace-test/tests/basic/testBug579602.js b/js/src/jit-test/tests/basic/testBug579602.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug579602.js rename to js/src/jit-test/tests/basic/testBug579602.js diff --git a/js/src/trace-test/tests/basic/testBug579646.js b/js/src/jit-test/tests/basic/testBug579646.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug579646.js rename to js/src/jit-test/tests/basic/testBug579646.js diff --git a/js/src/trace-test/tests/basic/testBug579647.js b/js/src/jit-test/tests/basic/testBug579647.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug579647.js rename to js/src/jit-test/tests/basic/testBug579647.js diff --git a/js/src/trace-test/tests/basic/testBug582766.js b/js/src/jit-test/tests/basic/testBug582766.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug582766.js rename to js/src/jit-test/tests/basic/testBug582766.js diff --git a/js/src/trace-test/tests/basic/testBug584650.js b/js/src/jit-test/tests/basic/testBug584650.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug584650.js rename to js/src/jit-test/tests/basic/testBug584650.js diff --git a/js/src/trace-test/tests/basic/testBug595916.js b/js/src/jit-test/tests/basic/testBug595916.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug595916.js rename to js/src/jit-test/tests/basic/testBug595916.js diff --git a/js/src/trace-test/tests/basic/testBug597736.js b/js/src/jit-test/tests/basic/testBug597736.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug597736.js rename to js/src/jit-test/tests/basic/testBug597736.js diff --git a/js/src/trace-test/tests/basic/testBug604210.js b/js/src/jit-test/tests/basic/testBug604210.js similarity index 100% rename from js/src/trace-test/tests/basic/testBug604210.js rename to js/src/jit-test/tests/basic/testBug604210.js diff --git a/js/src/trace-test/tests/basic/testCallElem.js b/js/src/jit-test/tests/basic/testCallElem.js similarity index 100% rename from js/src/trace-test/tests/basic/testCallElem.js rename to js/src/jit-test/tests/basic/testCallElem.js diff --git a/js/src/trace-test/tests/basic/testCallNull.js b/js/src/jit-test/tests/basic/testCallNull.js similarity index 100% rename from js/src/trace-test/tests/basic/testCallNull.js rename to js/src/jit-test/tests/basic/testCallNull.js diff --git a/js/src/trace-test/tests/basic/testCallPick.js b/js/src/jit-test/tests/basic/testCallPick.js similarity index 100% rename from js/src/trace-test/tests/basic/testCallPick.js rename to js/src/jit-test/tests/basic/testCallPick.js diff --git a/js/src/trace-test/tests/basic/testCallProtoMethod.js b/js/src/jit-test/tests/basic/testCallProtoMethod.js similarity index 100% rename from js/src/trace-test/tests/basic/testCallProtoMethod.js rename to js/src/jit-test/tests/basic/testCallProtoMethod.js diff --git a/js/src/trace-test/tests/basic/testCaseAbort.js b/js/src/jit-test/tests/basic/testCaseAbort.js similarity index 100% rename from js/src/trace-test/tests/basic/testCaseAbort.js rename to js/src/jit-test/tests/basic/testCaseAbort.js diff --git a/js/src/trace-test/tests/basic/testCaseTypeMismatchBadness.js b/js/src/jit-test/tests/basic/testCaseTypeMismatchBadness.js similarity index 100% rename from js/src/trace-test/tests/basic/testCaseTypeMismatchBadness.js rename to js/src/jit-test/tests/basic/testCaseTypeMismatchBadness.js diff --git a/js/src/trace-test/tests/basic/testChangingObjectWithLength.js b/js/src/jit-test/tests/basic/testChangingObjectWithLength.js similarity index 100% rename from js/src/trace-test/tests/basic/testChangingObjectWithLength.js rename to js/src/jit-test/tests/basic/testChangingObjectWithLength.js diff --git a/js/src/trace-test/tests/basic/testClosingRecursion.js b/js/src/jit-test/tests/basic/testClosingRecursion.js similarity index 100% rename from js/src/trace-test/tests/basic/testClosingRecursion.js rename to js/src/jit-test/tests/basic/testClosingRecursion.js diff --git a/js/src/trace-test/tests/basic/testClosureIncrSideExit.js b/js/src/jit-test/tests/basic/testClosureIncrSideExit.js similarity index 100% rename from js/src/trace-test/tests/basic/testClosureIncrSideExit.js rename to js/src/jit-test/tests/basic/testClosureIncrSideExit.js diff --git a/js/src/trace-test/tests/basic/testClosures.js b/js/src/jit-test/tests/basic/testClosures.js similarity index 100% rename from js/src/trace-test/tests/basic/testClosures.js rename to js/src/jit-test/tests/basic/testClosures.js diff --git a/js/src/trace-test/tests/basic/testComparisons.js b/js/src/jit-test/tests/basic/testComparisons.js similarity index 100% rename from js/src/trace-test/tests/basic/testComparisons.js rename to js/src/jit-test/tests/basic/testComparisons.js diff --git a/js/src/trace-test/tests/basic/testConcatNWithSideEffects.js b/js/src/jit-test/tests/basic/testConcatNWithSideEffects.js similarity index 100% rename from js/src/trace-test/tests/basic/testConcatNWithSideEffects.js rename to js/src/jit-test/tests/basic/testConcatNWithSideEffects.js diff --git a/js/src/trace-test/tests/basic/testConstIf.js b/js/src/jit-test/tests/basic/testConstIf.js similarity index 100% rename from js/src/trace-test/tests/basic/testConstIf.js rename to js/src/jit-test/tests/basic/testConstIf.js diff --git a/js/src/trace-test/tests/basic/testConstSwitch.js b/js/src/jit-test/tests/basic/testConstSwitch.js similarity index 100% rename from js/src/trace-test/tests/basic/testConstSwitch.js rename to js/src/jit-test/tests/basic/testConstSwitch.js diff --git a/js/src/trace-test/tests/basic/testConstSwitch2.js b/js/src/jit-test/tests/basic/testConstSwitch2.js similarity index 100% rename from js/src/trace-test/tests/basic/testConstSwitch2.js rename to js/src/jit-test/tests/basic/testConstSwitch2.js diff --git a/js/src/trace-test/tests/basic/testConstantBooleanExpr.js b/js/src/jit-test/tests/basic/testConstantBooleanExpr.js similarity index 100% rename from js/src/trace-test/tests/basic/testConstantBooleanExpr.js rename to js/src/jit-test/tests/basic/testConstantBooleanExpr.js diff --git a/js/src/trace-test/tests/basic/testConstructorBail.js b/js/src/jit-test/tests/basic/testConstructorBail.js similarity index 100% rename from js/src/trace-test/tests/basic/testConstructorBail.js rename to js/src/jit-test/tests/basic/testConstructorBail.js diff --git a/js/src/trace-test/tests/basic/testContinue.js b/js/src/jit-test/tests/basic/testContinue.js similarity index 100% rename from js/src/trace-test/tests/basic/testContinue.js rename to js/src/jit-test/tests/basic/testContinue.js diff --git a/js/src/trace-test/tests/basic/testContinueWithLabel.js b/js/src/jit-test/tests/basic/testContinueWithLabel.js similarity index 100% rename from js/src/trace-test/tests/basic/testContinueWithLabel.js rename to js/src/jit-test/tests/basic/testContinueWithLabel.js diff --git a/js/src/trace-test/tests/basic/testContinueWithLabel2.js b/js/src/jit-test/tests/basic/testContinueWithLabel2.js similarity index 100% rename from js/src/trace-test/tests/basic/testContinueWithLabel2.js rename to js/src/jit-test/tests/basic/testContinueWithLabel2.js diff --git a/js/src/trace-test/tests/basic/testContinueWithLabel3.js b/js/src/jit-test/tests/basic/testContinueWithLabel3.js similarity index 100% rename from js/src/trace-test/tests/basic/testContinueWithLabel3.js rename to js/src/jit-test/tests/basic/testContinueWithLabel3.js diff --git a/js/src/trace-test/tests/basic/testContinueWithLabel4.js b/js/src/jit-test/tests/basic/testContinueWithLabel4.js similarity index 100% rename from js/src/trace-test/tests/basic/testContinueWithLabel4.js rename to js/src/jit-test/tests/basic/testContinueWithLabel4.js diff --git a/js/src/trace-test/tests/basic/testConvertibleObjectEqUndefined.js b/js/src/jit-test/tests/basic/testConvertibleObjectEqUndefined.js similarity index 100% rename from js/src/trace-test/tests/basic/testConvertibleObjectEqUndefined.js rename to js/src/jit-test/tests/basic/testConvertibleObjectEqUndefined.js diff --git a/js/src/trace-test/tests/basic/testCustomIterator.js b/js/src/jit-test/tests/basic/testCustomIterator.js similarity index 100% rename from js/src/trace-test/tests/basic/testCustomIterator.js rename to js/src/jit-test/tests/basic/testCustomIterator.js diff --git a/js/src/trace-test/tests/basic/testDateNow.js b/js/src/jit-test/tests/basic/testDateNow.js similarity index 100% rename from js/src/trace-test/tests/basic/testDateNow.js rename to js/src/jit-test/tests/basic/testDateNow.js diff --git a/js/src/trace-test/tests/basic/testDecElem1.js b/js/src/jit-test/tests/basic/testDecElem1.js similarity index 100% rename from js/src/trace-test/tests/basic/testDecElem1.js rename to js/src/jit-test/tests/basic/testDecElem1.js diff --git a/js/src/trace-test/tests/basic/testDecElem2.js b/js/src/jit-test/tests/basic/testDecElem2.js similarity index 100% rename from js/src/trace-test/tests/basic/testDecElem2.js rename to js/src/jit-test/tests/basic/testDecElem2.js diff --git a/js/src/trace-test/tests/basic/testDecayingInnerLoop.js b/js/src/jit-test/tests/basic/testDecayingInnerLoop.js similarity index 100% rename from js/src/trace-test/tests/basic/testDecayingInnerLoop.js rename to js/src/jit-test/tests/basic/testDecayingInnerLoop.js diff --git a/js/src/trace-test/tests/basic/testDeepBail1.js b/js/src/jit-test/tests/basic/testDeepBail1.js similarity index 100% rename from js/src/trace-test/tests/basic/testDeepBail1.js rename to js/src/jit-test/tests/basic/testDeepBail1.js diff --git a/js/src/trace-test/tests/basic/testDeepBailFromHasInstance.js b/js/src/jit-test/tests/basic/testDeepBailFromHasInstance.js similarity index 100% rename from js/src/trace-test/tests/basic/testDeepBailFromHasInstance.js rename to js/src/jit-test/tests/basic/testDeepBailFromHasInstance.js diff --git a/js/src/trace-test/tests/basic/testDeepBailWhileRecording.js b/js/src/jit-test/tests/basic/testDeepBailWhileRecording.js similarity index 100% rename from js/src/trace-test/tests/basic/testDeepBailWhileRecording.js rename to js/src/jit-test/tests/basic/testDeepBailWhileRecording.js diff --git a/js/src/trace-test/tests/basic/testDeepPropertyShadowing.js b/js/src/jit-test/tests/basic/testDeepPropertyShadowing.js similarity index 100% rename from js/src/trace-test/tests/basic/testDeepPropertyShadowing.js rename to js/src/jit-test/tests/basic/testDeepPropertyShadowing.js diff --git a/js/src/trace-test/tests/basic/testDefinePropertyAcrossCompartment.js b/js/src/jit-test/tests/basic/testDefinePropertyAcrossCompartment.js similarity index 100% rename from js/src/trace-test/tests/basic/testDefinePropertyAcrossCompartment.js rename to js/src/jit-test/tests/basic/testDefinePropertyAcrossCompartment.js diff --git a/js/src/trace-test/tests/basic/testDenseArrayProp.js b/js/src/jit-test/tests/basic/testDenseArrayProp.js similarity index 100% rename from js/src/trace-test/tests/basic/testDenseArrayProp.js rename to js/src/jit-test/tests/basic/testDenseArrayProp.js diff --git a/js/src/trace-test/tests/basic/testDestructuring.js b/js/src/jit-test/tests/basic/testDestructuring.js similarity index 100% rename from js/src/trace-test/tests/basic/testDestructuring.js rename to js/src/jit-test/tests/basic/testDestructuring.js diff --git a/js/src/trace-test/tests/basic/testDifferingArgc.js b/js/src/jit-test/tests/basic/testDifferingArgc.js similarity index 100% rename from js/src/trace-test/tests/basic/testDifferingArgc.js rename to js/src/jit-test/tests/basic/testDifferingArgc.js diff --git a/js/src/trace-test/tests/basic/testDivOverflow.js b/js/src/jit-test/tests/basic/testDivOverflow.js similarity index 100% rename from js/src/trace-test/tests/basic/testDivOverflow.js rename to js/src/jit-test/tests/basic/testDivOverflow.js diff --git a/js/src/trace-test/tests/basic/testDivision.js b/js/src/jit-test/tests/basic/testDivision.js similarity index 100% rename from js/src/trace-test/tests/basic/testDivision.js rename to js/src/jit-test/tests/basic/testDivision.js diff --git a/js/src/trace-test/tests/basic/testDivisionFloat.js b/js/src/jit-test/tests/basic/testDivisionFloat.js similarity index 100% rename from js/src/trace-test/tests/basic/testDivisionFloat.js rename to js/src/jit-test/tests/basic/testDivisionFloat.js diff --git a/js/src/trace-test/tests/basic/testDivisionWithNegative1.js b/js/src/jit-test/tests/basic/testDivisionWithNegative1.js similarity index 100% rename from js/src/trace-test/tests/basic/testDivisionWithNegative1.js rename to js/src/jit-test/tests/basic/testDivisionWithNegative1.js diff --git a/js/src/trace-test/tests/basic/testDoubleComparison.js b/js/src/jit-test/tests/basic/testDoubleComparison.js similarity index 100% rename from js/src/trace-test/tests/basic/testDoubleComparison.js rename to js/src/jit-test/tests/basic/testDoubleComparison.js diff --git a/js/src/trace-test/tests/basic/testDoubleToStr.js b/js/src/jit-test/tests/basic/testDoubleToStr.js similarity index 100% rename from js/src/trace-test/tests/basic/testDoubleToStr.js rename to js/src/jit-test/tests/basic/testDoubleToStr.js diff --git a/js/src/trace-test/tests/basic/testDoubleZeroInSwitch1.js b/js/src/jit-test/tests/basic/testDoubleZeroInSwitch1.js similarity index 100% rename from js/src/trace-test/tests/basic/testDoubleZeroInSwitch1.js rename to js/src/jit-test/tests/basic/testDoubleZeroInSwitch1.js diff --git a/js/src/trace-test/tests/basic/testDoubleZeroInSwitch2.js b/js/src/jit-test/tests/basic/testDoubleZeroInSwitch2.js similarity index 100% rename from js/src/trace-test/tests/basic/testDoubleZeroInSwitch2.js rename to js/src/jit-test/tests/basic/testDoubleZeroInSwitch2.js diff --git a/js/src/trace-test/tests/basic/testElemDec1.js b/js/src/jit-test/tests/basic/testElemDec1.js similarity index 100% rename from js/src/trace-test/tests/basic/testElemDec1.js rename to js/src/jit-test/tests/basic/testElemDec1.js diff --git a/js/src/trace-test/tests/basic/testElemDec2.js b/js/src/jit-test/tests/basic/testElemDec2.js similarity index 100% rename from js/src/trace-test/tests/basic/testElemDec2.js rename to js/src/jit-test/tests/basic/testElemDec2.js diff --git a/js/src/trace-test/tests/basic/testElemInc1.js b/js/src/jit-test/tests/basic/testElemInc1.js similarity index 100% rename from js/src/trace-test/tests/basic/testElemInc1.js rename to js/src/jit-test/tests/basic/testElemInc1.js diff --git a/js/src/trace-test/tests/basic/testElemInc2.js b/js/src/jit-test/tests/basic/testElemInc2.js similarity index 100% rename from js/src/trace-test/tests/basic/testElemInc2.js rename to js/src/jit-test/tests/basic/testElemInc2.js diff --git a/js/src/trace-test/tests/basic/testEliminatedGuardWithinAnchor.js b/js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js similarity index 100% rename from js/src/trace-test/tests/basic/testEliminatedGuardWithinAnchor.js rename to js/src/jit-test/tests/basic/testEliminatedGuardWithinAnchor.js diff --git a/js/src/trace-test/tests/basic/testEqFalseEmptyString.js b/js/src/jit-test/tests/basic/testEqFalseEmptyString.js similarity index 100% rename from js/src/trace-test/tests/basic/testEqFalseEmptyString.js rename to js/src/jit-test/tests/basic/testEqFalseEmptyString.js diff --git a/js/src/trace-test/tests/basic/testErrorReportIn_getPrototypeOf.js b/js/src/jit-test/tests/basic/testErrorReportIn_getPrototypeOf.js similarity index 100% rename from js/src/trace-test/tests/basic/testErrorReportIn_getPrototypeOf.js rename to js/src/jit-test/tests/basic/testErrorReportIn_getPrototypeOf.js diff --git a/js/src/trace-test/tests/basic/testEvalCalledFromWatchOverSetter.js b/js/src/jit-test/tests/basic/testEvalCalledFromWatchOverSetter.js similarity index 100% rename from js/src/trace-test/tests/basic/testEvalCalledFromWatchOverSetter.js rename to js/src/jit-test/tests/basic/testEvalCalledFromWatchOverSetter.js diff --git a/js/src/trace-test/tests/basic/testEvalInFunctionCallee.js b/js/src/jit-test/tests/basic/testEvalInFunctionCallee.js similarity index 100% rename from js/src/trace-test/tests/basic/testEvalInFunctionCallee.js rename to js/src/jit-test/tests/basic/testEvalInFunctionCallee.js diff --git a/js/src/trace-test/tests/basic/testExistingPropToJoinedMethodAttempt.js b/js/src/jit-test/tests/basic/testExistingPropToJoinedMethodAttempt.js similarity index 100% rename from js/src/trace-test/tests/basic/testExistingPropToJoinedMethodAttempt.js rename to js/src/jit-test/tests/basic/testExistingPropToJoinedMethodAttempt.js diff --git a/js/src/trace-test/tests/basic/testFewerGlobalsInInnerTree.js b/js/src/jit-test/tests/basic/testFewerGlobalsInInnerTree.js similarity index 100% rename from js/src/trace-test/tests/basic/testFewerGlobalsInInnerTree.js rename to js/src/jit-test/tests/basic/testFewerGlobalsInInnerTree.js diff --git a/js/src/trace-test/tests/basic/testFloatArrayIndex.js b/js/src/jit-test/tests/basic/testFloatArrayIndex.js similarity index 100% rename from js/src/trace-test/tests/basic/testFloatArrayIndex.js rename to js/src/jit-test/tests/basic/testFloatArrayIndex.js diff --git a/js/src/trace-test/tests/basic/testForEach.js b/js/src/jit-test/tests/basic/testForEach.js similarity index 100% rename from js/src/trace-test/tests/basic/testForEach.js rename to js/src/jit-test/tests/basic/testForEach.js diff --git a/js/src/trace-test/tests/basic/testForInLoopChangeIteratorType.js b/js/src/jit-test/tests/basic/testForInLoopChangeIteratorType.js similarity index 100% rename from js/src/trace-test/tests/basic/testForInLoopChangeIteratorType.js rename to js/src/jit-test/tests/basic/testForInLoopChangeIteratorType.js diff --git a/js/src/trace-test/tests/basic/testFunctionIdentityChange.js b/js/src/jit-test/tests/basic/testFunctionIdentityChange.js similarity index 100% rename from js/src/trace-test/tests/basic/testFunctionIdentityChange.js rename to js/src/jit-test/tests/basic/testFunctionIdentityChange.js diff --git a/js/src/trace-test/tests/basic/testGCWhileRecording.js b/js/src/jit-test/tests/basic/testGCWhileRecording.js similarity index 100% rename from js/src/trace-test/tests/basic/testGCWhileRecording.js rename to js/src/jit-test/tests/basic/testGCWhileRecording.js diff --git a/js/src/trace-test/tests/basic/testGeneratorDeepBail.js b/js/src/jit-test/tests/basic/testGeneratorDeepBail.js similarity index 100% rename from js/src/trace-test/tests/basic/testGeneratorDeepBail.js rename to js/src/jit-test/tests/basic/testGeneratorDeepBail.js diff --git a/js/src/trace-test/tests/basic/testGetCallObj.js b/js/src/jit-test/tests/basic/testGetCallObj.js similarity index 100% rename from js/src/trace-test/tests/basic/testGetCallObj.js rename to js/src/jit-test/tests/basic/testGetCallObj.js diff --git a/js/src/trace-test/tests/basic/testGetThis.js b/js/src/jit-test/tests/basic/testGetThis.js similarity index 100% rename from js/src/trace-test/tests/basic/testGetThis.js rename to js/src/jit-test/tests/basic/testGetThis.js diff --git a/js/src/trace-test/tests/basic/testGlobalAsProto.js b/js/src/jit-test/tests/basic/testGlobalAsProto.js similarity index 100% rename from js/src/trace-test/tests/basic/testGlobalAsProto.js rename to js/src/jit-test/tests/basic/testGlobalAsProto.js diff --git a/js/src/trace-test/tests/basic/testGlobalMultitrees1.js b/js/src/jit-test/tests/basic/testGlobalMultitrees1.js similarity index 100% rename from js/src/trace-test/tests/basic/testGlobalMultitrees1.js rename to js/src/jit-test/tests/basic/testGlobalMultitrees1.js diff --git a/js/src/trace-test/tests/basic/testGlobalOptimize-2.js b/js/src/jit-test/tests/basic/testGlobalOptimize-2.js similarity index 100% rename from js/src/trace-test/tests/basic/testGlobalOptimize-2.js rename to js/src/jit-test/tests/basic/testGlobalOptimize-2.js diff --git a/js/src/trace-test/tests/basic/testGlobalOptimize-3.js b/js/src/jit-test/tests/basic/testGlobalOptimize-3.js similarity index 100% rename from js/src/trace-test/tests/basic/testGlobalOptimize-3.js rename to js/src/jit-test/tests/basic/testGlobalOptimize-3.js diff --git a/js/src/trace-test/tests/basic/testGlobalOptimize-4.js b/js/src/jit-test/tests/basic/testGlobalOptimize-4.js similarity index 100% rename from js/src/trace-test/tests/basic/testGlobalOptimize-4.js rename to js/src/jit-test/tests/basic/testGlobalOptimize-4.js diff --git a/js/src/trace-test/tests/basic/testGlobalOptimize-5.js b/js/src/jit-test/tests/basic/testGlobalOptimize-5.js similarity index 100% rename from js/src/trace-test/tests/basic/testGlobalOptimize-5.js rename to js/src/jit-test/tests/basic/testGlobalOptimize-5.js diff --git a/js/src/trace-test/tests/basic/testGlobalOptimize-6.js b/js/src/jit-test/tests/basic/testGlobalOptimize-6.js similarity index 100% rename from js/src/trace-test/tests/basic/testGlobalOptimize-6.js rename to js/src/jit-test/tests/basic/testGlobalOptimize-6.js diff --git a/js/src/trace-test/tests/basic/testGlobalProtoAccess.js b/js/src/jit-test/tests/basic/testGlobalProtoAccess.js similarity index 100% rename from js/src/trace-test/tests/basic/testGlobalProtoAccess.js rename to js/src/jit-test/tests/basic/testGlobalProtoAccess.js diff --git a/js/src/trace-test/tests/basic/testGlobalShapeChangeAfterDeepBail.js b/js/src/jit-test/tests/basic/testGlobalShapeChangeAfterDeepBail.js similarity index 100% rename from js/src/trace-test/tests/basic/testGlobalShapeChangeAfterDeepBail.js rename to js/src/jit-test/tests/basic/testGlobalShapeChangeAfterDeepBail.js diff --git a/js/src/trace-test/tests/basic/testGroupAssignment.js b/js/src/jit-test/tests/basic/testGroupAssignment.js similarity index 100% rename from js/src/trace-test/tests/basic/testGroupAssignment.js rename to js/src/jit-test/tests/basic/testGroupAssignment.js diff --git a/js/src/trace-test/tests/basic/testGrowDenseArray.js b/js/src/jit-test/tests/basic/testGrowDenseArray.js similarity index 100% rename from js/src/trace-test/tests/basic/testGrowDenseArray.js rename to js/src/jit-test/tests/basic/testGrowDenseArray.js diff --git a/js/src/trace-test/tests/basic/testGuardCalleeSneakAttack.js b/js/src/jit-test/tests/basic/testGuardCalleeSneakAttack.js similarity index 100% rename from js/src/trace-test/tests/basic/testGuardCalleeSneakAttack.js rename to js/src/jit-test/tests/basic/testGuardCalleeSneakAttack.js diff --git a/js/src/trace-test/tests/basic/testGuardCalleeSneakAttack2.js b/js/src/jit-test/tests/basic/testGuardCalleeSneakAttack2.js similarity index 100% rename from js/src/trace-test/tests/basic/testGuardCalleeSneakAttack2.js rename to js/src/jit-test/tests/basic/testGuardCalleeSneakAttack2.js diff --git a/js/src/trace-test/tests/basic/testHOTLOOPCorrectness.js b/js/src/jit-test/tests/basic/testHOTLOOPCorrectness.js similarity index 100% rename from js/src/trace-test/tests/basic/testHOTLOOPCorrectness.js rename to js/src/jit-test/tests/basic/testHOTLOOPCorrectness.js diff --git a/js/src/trace-test/tests/basic/testHOTLOOPSize.js b/js/src/jit-test/tests/basic/testHOTLOOPSize.js similarity index 100% rename from js/src/trace-test/tests/basic/testHOTLOOPSize.js rename to js/src/jit-test/tests/basic/testHOTLOOPSize.js diff --git a/js/src/trace-test/tests/basic/testHeavy.js b/js/src/jit-test/tests/basic/testHeavy.js similarity index 100% rename from js/src/trace-test/tests/basic/testHeavy.js rename to js/src/jit-test/tests/basic/testHeavy.js diff --git a/js/src/trace-test/tests/basic/testHeavy2.js b/js/src/jit-test/tests/basic/testHeavy2.js similarity index 100% rename from js/src/trace-test/tests/basic/testHeavy2.js rename to js/src/jit-test/tests/basic/testHeavy2.js diff --git a/js/src/trace-test/tests/basic/testHoleInDenseArray.js b/js/src/jit-test/tests/basic/testHoleInDenseArray.js similarity index 100% rename from js/src/trace-test/tests/basic/testHoleInDenseArray.js rename to js/src/jit-test/tests/basic/testHoleInDenseArray.js diff --git a/js/src/trace-test/tests/basic/testHolePushing.js b/js/src/jit-test/tests/basic/testHolePushing.js similarity index 100% rename from js/src/trace-test/tests/basic/testHolePushing.js rename to js/src/jit-test/tests/basic/testHolePushing.js diff --git a/js/src/trace-test/tests/basic/testINITELEM.js b/js/src/jit-test/tests/basic/testINITELEM.js similarity index 100% rename from js/src/trace-test/tests/basic/testINITELEM.js rename to js/src/jit-test/tests/basic/testINITELEM.js diff --git a/js/src/trace-test/tests/basic/testIn.js b/js/src/jit-test/tests/basic/testIn.js similarity index 100% rename from js/src/trace-test/tests/basic/testIn.js rename to js/src/jit-test/tests/basic/testIn.js diff --git a/js/src/trace-test/tests/basic/testIncDec.js b/js/src/jit-test/tests/basic/testIncDec.js similarity index 100% rename from js/src/trace-test/tests/basic/testIncDec.js rename to js/src/jit-test/tests/basic/testIncDec.js diff --git a/js/src/trace-test/tests/basic/testIncElem1.js b/js/src/jit-test/tests/basic/testIncElem1.js similarity index 100% rename from js/src/trace-test/tests/basic/testIncElem1.js rename to js/src/jit-test/tests/basic/testIncElem1.js diff --git a/js/src/trace-test/tests/basic/testIncElem2.js b/js/src/jit-test/tests/basic/testIncElem2.js similarity index 100% rename from js/src/trace-test/tests/basic/testIncElem2.js rename to js/src/jit-test/tests/basic/testIncElem2.js diff --git a/js/src/trace-test/tests/basic/testInitMethod.js b/js/src/jit-test/tests/basic/testInitMethod.js similarity index 100% rename from js/src/trace-test/tests/basic/testInitMethod.js rename to js/src/jit-test/tests/basic/testInitMethod.js diff --git a/js/src/trace-test/tests/basic/testInitelemWithFloatIndex.js b/js/src/jit-test/tests/basic/testInitelemWithFloatIndex.js similarity index 100% rename from js/src/trace-test/tests/basic/testInitelemWithFloatIndex.js rename to js/src/jit-test/tests/basic/testInitelemWithFloatIndex.js diff --git a/js/src/trace-test/tests/basic/testInitelemWithSetter.js b/js/src/jit-test/tests/basic/testInitelemWithSetter.js similarity index 100% rename from js/src/trace-test/tests/basic/testInitelemWithSetter.js rename to js/src/jit-test/tests/basic/testInitelemWithSetter.js diff --git a/js/src/trace-test/tests/basic/testInnerMissingArgs.js b/js/src/jit-test/tests/basic/testInnerMissingArgs.js similarity index 100% rename from js/src/trace-test/tests/basic/testInnerMissingArgs.js rename to js/src/jit-test/tests/basic/testInnerMissingArgs.js diff --git a/js/src/trace-test/tests/basic/testInnerSwitchBreak.js b/js/src/jit-test/tests/basic/testInnerSwitchBreak.js similarity index 100% rename from js/src/trace-test/tests/basic/testInnerSwitchBreak.js rename to js/src/jit-test/tests/basic/testInnerSwitchBreak.js diff --git a/js/src/trace-test/tests/basic/testInt32ToId.js b/js/src/jit-test/tests/basic/testInt32ToId.js similarity index 100% rename from js/src/trace-test/tests/basic/testInt32ToId.js rename to js/src/jit-test/tests/basic/testInt32ToId.js diff --git a/js/src/trace-test/tests/basic/testIntFloor.js b/js/src/jit-test/tests/basic/testIntFloor.js similarity index 100% rename from js/src/trace-test/tests/basic/testIntFloor.js rename to js/src/jit-test/tests/basic/testIntFloor.js diff --git a/js/src/trace-test/tests/basic/testIntOverflow.js b/js/src/jit-test/tests/basic/testIntOverflow.js similarity index 100% rename from js/src/trace-test/tests/basic/testIntOverflow.js rename to js/src/jit-test/tests/basic/testIntOverflow.js diff --git a/js/src/trace-test/tests/basic/testIntUnderflow.js b/js/src/jit-test/tests/basic/testIntUnderflow.js similarity index 100% rename from js/src/trace-test/tests/basic/testIntUnderflow.js rename to js/src/jit-test/tests/basic/testIntUnderflow.js diff --git a/js/src/trace-test/tests/basic/testInterpreterReentery8.js b/js/src/jit-test/tests/basic/testInterpreterReentery8.js similarity index 100% rename from js/src/trace-test/tests/basic/testInterpreterReentery8.js rename to js/src/jit-test/tests/basic/testInterpreterReentery8.js diff --git a/js/src/trace-test/tests/basic/testInterpreterReentry.js b/js/src/jit-test/tests/basic/testInterpreterReentry.js similarity index 100% rename from js/src/trace-test/tests/basic/testInterpreterReentry.js rename to js/src/jit-test/tests/basic/testInterpreterReentry.js diff --git a/js/src/trace-test/tests/basic/testInterpreterReentry2.js b/js/src/jit-test/tests/basic/testInterpreterReentry2.js similarity index 100% rename from js/src/trace-test/tests/basic/testInterpreterReentry2.js rename to js/src/jit-test/tests/basic/testInterpreterReentry2.js diff --git a/js/src/trace-test/tests/basic/testInterpreterReentry3.js b/js/src/jit-test/tests/basic/testInterpreterReentry3.js similarity index 100% rename from js/src/trace-test/tests/basic/testInterpreterReentry3.js rename to js/src/jit-test/tests/basic/testInterpreterReentry3.js diff --git a/js/src/trace-test/tests/basic/testInterpreterReentry4.js b/js/src/jit-test/tests/basic/testInterpreterReentry4.js similarity index 100% rename from js/src/trace-test/tests/basic/testInterpreterReentry4.js rename to js/src/jit-test/tests/basic/testInterpreterReentry4.js diff --git a/js/src/trace-test/tests/basic/testInterpreterReentry5.js b/js/src/jit-test/tests/basic/testInterpreterReentry5.js similarity index 100% rename from js/src/trace-test/tests/basic/testInterpreterReentry5.js rename to js/src/jit-test/tests/basic/testInterpreterReentry5.js diff --git a/js/src/trace-test/tests/basic/testInterpreterReentry6.js b/js/src/jit-test/tests/basic/testInterpreterReentry6.js similarity index 100% rename from js/src/trace-test/tests/basic/testInterpreterReentry6.js rename to js/src/jit-test/tests/basic/testInterpreterReentry6.js diff --git a/js/src/trace-test/tests/basic/testInterpreterReentry7.js b/js/src/jit-test/tests/basic/testInterpreterReentry7.js similarity index 100% rename from js/src/trace-test/tests/basic/testInterpreterReentry7.js rename to js/src/jit-test/tests/basic/testInterpreterReentry7.js diff --git a/js/src/trace-test/tests/basic/testInvalidCharCodeAt.js b/js/src/jit-test/tests/basic/testInvalidCharCodeAt.js similarity index 100% rename from js/src/trace-test/tests/basic/testInvalidCharCodeAt.js rename to js/src/jit-test/tests/basic/testInvalidCharCodeAt.js diff --git a/js/src/trace-test/tests/basic/testInvertNullAfterNegateNull.js b/js/src/jit-test/tests/basic/testInvertNullAfterNegateNull.js similarity index 100% rename from js/src/trace-test/tests/basic/testInvertNullAfterNegateNull.js rename to js/src/jit-test/tests/basic/testInvertNullAfterNegateNull.js diff --git a/js/src/trace-test/tests/basic/testIteratorReification.js b/js/src/jit-test/tests/basic/testIteratorReification.js similarity index 100% rename from js/src/trace-test/tests/basic/testIteratorReification.js rename to js/src/jit-test/tests/basic/testIteratorReification.js diff --git a/js/src/trace-test/tests/basic/testLambdaCtor.js b/js/src/jit-test/tests/basic/testLambdaCtor.js similarity index 100% rename from js/src/trace-test/tests/basic/testLambdaCtor.js rename to js/src/jit-test/tests/basic/testLambdaCtor.js diff --git a/js/src/trace-test/tests/basic/testLambdaInitedVar.js b/js/src/jit-test/tests/basic/testLambdaInitedVar.js similarity index 100% rename from js/src/trace-test/tests/basic/testLambdaInitedVar.js rename to js/src/jit-test/tests/basic/testLambdaInitedVar.js diff --git a/js/src/trace-test/tests/basic/testLengthInString.js b/js/src/jit-test/tests/basic/testLengthInString.js similarity index 100% rename from js/src/trace-test/tests/basic/testLengthInString.js rename to js/src/jit-test/tests/basic/testLengthInString.js diff --git a/js/src/trace-test/tests/basic/testLengthOnNonNativeProto.js b/js/src/jit-test/tests/basic/testLengthOnNonNativeProto.js similarity index 100% rename from js/src/trace-test/tests/basic/testLengthOnNonNativeProto.js rename to js/src/jit-test/tests/basic/testLengthOnNonNativeProto.js diff --git a/js/src/trace-test/tests/basic/testLetWithUnstableGlobal.js b/js/src/jit-test/tests/basic/testLetWithUnstableGlobal.js similarity index 100% rename from js/src/trace-test/tests/basic/testLetWithUnstableGlobal.js rename to js/src/jit-test/tests/basic/testLetWithUnstableGlobal.js diff --git a/js/src/trace-test/tests/basic/testLirBufOOM.js b/js/src/jit-test/tests/basic/testLirBufOOM.js similarity index 100% rename from js/src/trace-test/tests/basic/testLirBufOOM.js rename to js/src/jit-test/tests/basic/testLirBufOOM.js diff --git a/js/src/trace-test/tests/basic/testLogicalNotNaN.js b/js/src/jit-test/tests/basic/testLogicalNotNaN.js similarity index 100% rename from js/src/trace-test/tests/basic/testLogicalNotNaN.js rename to js/src/jit-test/tests/basic/testLogicalNotNaN.js diff --git a/js/src/trace-test/tests/basic/testLongNumToString.js b/js/src/jit-test/tests/basic/testLongNumToString.js similarity index 100% rename from js/src/trace-test/tests/basic/testLongNumToString.js rename to js/src/jit-test/tests/basic/testLongNumToString.js diff --git a/js/src/trace-test/tests/basic/testLoopWithUndefined1.js b/js/src/jit-test/tests/basic/testLoopWithUndefined1.js similarity index 100% rename from js/src/trace-test/tests/basic/testLoopWithUndefined1.js rename to js/src/jit-test/tests/basic/testLoopWithUndefined1.js diff --git a/js/src/trace-test/tests/basic/testLoopWithUndefined2.js b/js/src/jit-test/tests/basic/testLoopWithUndefined2.js similarity index 100% rename from js/src/trace-test/tests/basic/testLoopWithUndefined2.js rename to js/src/jit-test/tests/basic/testLoopWithUndefined2.js diff --git a/js/src/trace-test/tests/basic/testLoopingAccumulator.js b/js/src/jit-test/tests/basic/testLoopingAccumulator.js similarity index 100% rename from js/src/trace-test/tests/basic/testLoopingAccumulator.js rename to js/src/jit-test/tests/basic/testLoopingAccumulator.js diff --git a/js/src/trace-test/tests/basic/testMatchAsCondition.js b/js/src/jit-test/tests/basic/testMatchAsCondition.js similarity index 100% rename from js/src/trace-test/tests/basic/testMatchAsCondition.js rename to js/src/jit-test/tests/basic/testMatchAsCondition.js diff --git a/js/src/trace-test/tests/basic/testMatchStringObject.js b/js/src/jit-test/tests/basic/testMatchStringObject.js similarity index 100% rename from js/src/trace-test/tests/basic/testMatchStringObject.js rename to js/src/jit-test/tests/basic/testMatchStringObject.js diff --git a/js/src/trace-test/tests/basic/testMethodInc.js b/js/src/jit-test/tests/basic/testMethodInc.js similarity index 100% rename from js/src/trace-test/tests/basic/testMethodInc.js rename to js/src/jit-test/tests/basic/testMethodInc.js diff --git a/js/src/trace-test/tests/basic/testMethodInit.js b/js/src/jit-test/tests/basic/testMethodInit.js similarity index 100% rename from js/src/trace-test/tests/basic/testMethodInit.js rename to js/src/jit-test/tests/basic/testMethodInit.js diff --git a/js/src/trace-test/tests/basic/testMethodInitDeref.js b/js/src/jit-test/tests/basic/testMethodInitDeref.js similarity index 100% rename from js/src/trace-test/tests/basic/testMethodInitDeref.js rename to js/src/jit-test/tests/basic/testMethodInitDeref.js diff --git a/js/src/trace-test/tests/basic/testMethodInitSafety.js b/js/src/jit-test/tests/basic/testMethodInitSafety.js similarity index 100% rename from js/src/trace-test/tests/basic/testMethodInitSafety.js rename to js/src/jit-test/tests/basic/testMethodInitSafety.js diff --git a/js/src/trace-test/tests/basic/testMethodInitUneval.js b/js/src/jit-test/tests/basic/testMethodInitUneval.js similarity index 100% rename from js/src/trace-test/tests/basic/testMethodInitUneval.js rename to js/src/jit-test/tests/basic/testMethodInitUneval.js diff --git a/js/src/trace-test/tests/basic/testMethodOverride.js b/js/src/jit-test/tests/basic/testMethodOverride.js similarity index 100% rename from js/src/trace-test/tests/basic/testMethodOverride.js rename to js/src/jit-test/tests/basic/testMethodOverride.js diff --git a/js/src/trace-test/tests/basic/testMethodSet.js b/js/src/jit-test/tests/basic/testMethodSet.js similarity index 100% rename from js/src/trace-test/tests/basic/testMethodSet.js rename to js/src/jit-test/tests/basic/testMethodSet.js diff --git a/js/src/trace-test/tests/basic/testMissingMethod.js b/js/src/jit-test/tests/basic/testMissingMethod.js similarity index 100% rename from js/src/trace-test/tests/basic/testMissingMethod.js rename to js/src/jit-test/tests/basic/testMissingMethod.js diff --git a/js/src/trace-test/tests/basic/testMissingMethod2.js b/js/src/jit-test/tests/basic/testMissingMethod2.js similarity index 100% rename from js/src/trace-test/tests/basic/testMissingMethod2.js rename to js/src/jit-test/tests/basic/testMissingMethod2.js diff --git a/js/src/trace-test/tests/basic/testModuloWithNegative1.js b/js/src/jit-test/tests/basic/testModuloWithNegative1.js similarity index 100% rename from js/src/trace-test/tests/basic/testModuloWithNegative1.js rename to js/src/jit-test/tests/basic/testModuloWithNegative1.js diff --git a/js/src/trace-test/tests/basic/testModuloWithNegative2.js b/js/src/jit-test/tests/basic/testModuloWithNegative2.js similarity index 100% rename from js/src/trace-test/tests/basic/testModuloWithNegative2.js rename to js/src/jit-test/tests/basic/testModuloWithNegative2.js diff --git a/js/src/trace-test/tests/basic/testMoreArgcThanNargs.js b/js/src/jit-test/tests/basic/testMoreArgcThanNargs.js similarity index 100% rename from js/src/trace-test/tests/basic/testMoreArgcThanNargs.js rename to js/src/jit-test/tests/basic/testMoreArgcThanNargs.js diff --git a/js/src/trace-test/tests/basic/testMoreClosures.js b/js/src/jit-test/tests/basic/testMoreClosures.js similarity index 100% rename from js/src/trace-test/tests/basic/testMoreClosures.js rename to js/src/jit-test/tests/basic/testMoreClosures.js diff --git a/js/src/trace-test/tests/basic/testMulOverflow.js b/js/src/jit-test/tests/basic/testMulOverflow.js similarity index 100% rename from js/src/trace-test/tests/basic/testMulOverflow.js rename to js/src/jit-test/tests/basic/testMulOverflow.js diff --git a/js/src/trace-test/tests/basic/testMultipleArgumentsObjects.js b/js/src/jit-test/tests/basic/testMultipleArgumentsObjects.js similarity index 100% rename from js/src/trace-test/tests/basic/testMultipleArgumentsObjects.js rename to js/src/jit-test/tests/basic/testMultipleArgumentsObjects.js diff --git a/js/src/trace-test/tests/basic/testNEWINIT.js b/js/src/jit-test/tests/basic/testNEWINIT.js similarity index 100% rename from js/src/trace-test/tests/basic/testNEWINIT.js rename to js/src/jit-test/tests/basic/testNEWINIT.js diff --git a/js/src/trace-test/tests/basic/testNEWINIT_DOUBLE.js b/js/src/jit-test/tests/basic/testNEWINIT_DOUBLE.js similarity index 100% rename from js/src/trace-test/tests/basic/testNEWINIT_DOUBLE.js rename to js/src/jit-test/tests/basic/testNEWINIT_DOUBLE.js diff --git a/js/src/trace-test/tests/basic/testNativeArgsRooting.js b/js/src/jit-test/tests/basic/testNativeArgsRooting.js similarity index 100% rename from js/src/trace-test/tests/basic/testNativeArgsRooting.js rename to js/src/jit-test/tests/basic/testNativeArgsRooting.js diff --git a/js/src/trace-test/tests/basic/testNativeLog.js b/js/src/jit-test/tests/basic/testNativeLog.js similarity index 100% rename from js/src/trace-test/tests/basic/testNativeLog.js rename to js/src/jit-test/tests/basic/testNativeLog.js diff --git a/js/src/trace-test/tests/basic/testNativeMax.js b/js/src/jit-test/tests/basic/testNativeMax.js similarity index 100% rename from js/src/trace-test/tests/basic/testNativeMax.js rename to js/src/jit-test/tests/basic/testNativeMax.js diff --git a/js/src/trace-test/tests/basic/testNativeSetter.js b/js/src/jit-test/tests/basic/testNativeSetter.js similarity index 100% rename from js/src/trace-test/tests/basic/testNativeSetter.js rename to js/src/jit-test/tests/basic/testNativeSetter.js diff --git a/js/src/trace-test/tests/basic/testNegZero1.js b/js/src/jit-test/tests/basic/testNegZero1.js similarity index 100% rename from js/src/trace-test/tests/basic/testNegZero1.js rename to js/src/jit-test/tests/basic/testNegZero1.js diff --git a/js/src/trace-test/tests/basic/testNegativeArrayLength.js b/js/src/jit-test/tests/basic/testNegativeArrayLength.js similarity index 100% rename from js/src/trace-test/tests/basic/testNegativeArrayLength.js rename to js/src/jit-test/tests/basic/testNegativeArrayLength.js diff --git a/js/src/trace-test/tests/basic/testNegativeGETELEMIndex.js b/js/src/jit-test/tests/basic/testNegativeGETELEMIndex.js similarity index 100% rename from js/src/trace-test/tests/basic/testNegativeGETELEMIndex.js rename to js/src/jit-test/tests/basic/testNegativeGETELEMIndex.js diff --git a/js/src/trace-test/tests/basic/testNestedClosures.js b/js/src/jit-test/tests/basic/testNestedClosures.js similarity index 100% rename from js/src/trace-test/tests/basic/testNestedClosures.js rename to js/src/jit-test/tests/basic/testNestedClosures.js diff --git a/js/src/trace-test/tests/basic/testNestedDeepBail.js b/js/src/jit-test/tests/basic/testNestedDeepBail.js similarity index 100% rename from js/src/trace-test/tests/basic/testNestedDeepBail.js rename to js/src/jit-test/tests/basic/testNestedDeepBail.js diff --git a/js/src/trace-test/tests/basic/testNestedEscapingLambdas.js b/js/src/jit-test/tests/basic/testNestedEscapingLambdas.js similarity index 100% rename from js/src/trace-test/tests/basic/testNestedEscapingLambdas.js rename to js/src/jit-test/tests/basic/testNestedEscapingLambdas.js diff --git a/js/src/trace-test/tests/basic/testNestedExitStackOuter.js b/js/src/jit-test/tests/basic/testNestedExitStackOuter.js similarity index 100% rename from js/src/trace-test/tests/basic/testNestedExitStackOuter.js rename to js/src/jit-test/tests/basic/testNestedExitStackOuter.js diff --git a/js/src/trace-test/tests/basic/testNestedForIn.js b/js/src/jit-test/tests/basic/testNestedForIn.js similarity index 100% rename from js/src/trace-test/tests/basic/testNestedForIn.js rename to js/src/jit-test/tests/basic/testNestedForIn.js diff --git a/js/src/trace-test/tests/basic/testNewArrayCount.js b/js/src/jit-test/tests/basic/testNewArrayCount.js similarity index 100% rename from js/src/trace-test/tests/basic/testNewArrayCount.js rename to js/src/jit-test/tests/basic/testNewArrayCount.js diff --git a/js/src/trace-test/tests/basic/testNewArrayCount2.js b/js/src/jit-test/tests/basic/testNewArrayCount2.js similarity index 100% rename from js/src/trace-test/tests/basic/testNewArrayCount2.js rename to js/src/jit-test/tests/basic/testNewArrayCount2.js diff --git a/js/src/trace-test/tests/basic/testNewDate.js b/js/src/jit-test/tests/basic/testNewDate.js similarity index 100% rename from js/src/trace-test/tests/basic/testNewDate.js rename to js/src/jit-test/tests/basic/testNewDate.js diff --git a/js/src/trace-test/tests/basic/testNewObject.js b/js/src/jit-test/tests/basic/testNewObject.js similarity index 100% rename from js/src/trace-test/tests/basic/testNewObject.js rename to js/src/jit-test/tests/basic/testNewObject.js diff --git a/js/src/trace-test/tests/basic/testNewString.js b/js/src/jit-test/tests/basic/testNewString.js similarity index 100% rename from js/src/trace-test/tests/basic/testNewString.js rename to js/src/jit-test/tests/basic/testNewString.js diff --git a/js/src/trace-test/tests/basic/testNewWithNonNativeProto.js b/js/src/jit-test/tests/basic/testNewWithNonNativeProto.js similarity index 100% rename from js/src/trace-test/tests/basic/testNewWithNonNativeProto.js rename to js/src/jit-test/tests/basic/testNewWithNonNativeProto.js diff --git a/js/src/trace-test/tests/basic/testNonStubGetter.js b/js/src/jit-test/tests/basic/testNonStubGetter.js similarity index 100% rename from js/src/trace-test/tests/basic/testNonStubGetter.js rename to js/src/jit-test/tests/basic/testNonStubGetter.js diff --git a/js/src/trace-test/tests/basic/testNot.js b/js/src/jit-test/tests/basic/testNot.js similarity index 100% rename from js/src/trace-test/tests/basic/testNot.js rename to js/src/jit-test/tests/basic/testNot.js diff --git a/js/src/trace-test/tests/basic/testNullCallee.js b/js/src/jit-test/tests/basic/testNullCallee.js similarity index 100% rename from js/src/trace-test/tests/basic/testNullCallee.js rename to js/src/jit-test/tests/basic/testNullCallee.js diff --git a/js/src/trace-test/tests/basic/testNullRelCmp.js b/js/src/jit-test/tests/basic/testNullRelCmp.js similarity index 100% rename from js/src/trace-test/tests/basic/testNullRelCmp.js rename to js/src/jit-test/tests/basic/testNullRelCmp.js diff --git a/js/src/trace-test/tests/basic/testNullToString.js b/js/src/jit-test/tests/basic/testNullToString.js similarity index 100% rename from js/src/trace-test/tests/basic/testNullToString.js rename to js/src/jit-test/tests/basic/testNullToString.js diff --git a/js/src/trace-test/tests/basic/testNumToString.js b/js/src/jit-test/tests/basic/testNumToString.js similarity index 100% rename from js/src/trace-test/tests/basic/testNumToString.js rename to js/src/jit-test/tests/basic/testNumToString.js diff --git a/js/src/trace-test/tests/basic/testNumberToString.js b/js/src/jit-test/tests/basic/testNumberToString.js similarity index 100% rename from js/src/trace-test/tests/basic/testNumberToString.js rename to js/src/jit-test/tests/basic/testNumberToString.js diff --git a/js/src/trace-test/tests/basic/testObjectConstructorReturningObject.js b/js/src/jit-test/tests/basic/testObjectConstructorReturningObject.js similarity index 100% rename from js/src/trace-test/tests/basic/testObjectConstructorReturningObject.js rename to js/src/jit-test/tests/basic/testObjectConstructorReturningObject.js diff --git a/js/src/trace-test/tests/basic/testObjectLength.js b/js/src/jit-test/tests/basic/testObjectLength.js similarity index 100% rename from js/src/trace-test/tests/basic/testObjectLength.js rename to js/src/jit-test/tests/basic/testObjectLength.js diff --git a/js/src/trace-test/tests/basic/testObjectOrderedCmp.js b/js/src/jit-test/tests/basic/testObjectOrderedCmp.js similarity index 100% rename from js/src/trace-test/tests/basic/testObjectOrderedCmp.js rename to js/src/jit-test/tests/basic/testObjectOrderedCmp.js diff --git a/js/src/trace-test/tests/basic/testObjectOrderedCmp2.js b/js/src/jit-test/tests/basic/testObjectOrderedCmp2.js similarity index 100% rename from js/src/trace-test/tests/basic/testObjectOrderedCmp2.js rename to js/src/jit-test/tests/basic/testObjectOrderedCmp2.js diff --git a/js/src/trace-test/tests/basic/testObjectToNumber.js b/js/src/jit-test/tests/basic/testObjectToNumber.js similarity index 100% rename from js/src/trace-test/tests/basic/testObjectToNumber.js rename to js/src/jit-test/tests/basic/testObjectToNumber.js diff --git a/js/src/trace-test/tests/basic/testObjectToString.js b/js/src/jit-test/tests/basic/testObjectToString.js similarity index 100% rename from js/src/trace-test/tests/basic/testObjectToString.js rename to js/src/jit-test/tests/basic/testObjectToString.js diff --git a/js/src/trace-test/tests/basic/testObjectVsPrototype.js b/js/src/jit-test/tests/basic/testObjectVsPrototype.js similarity index 100% rename from js/src/trace-test/tests/basic/testObjectVsPrototype.js rename to js/src/jit-test/tests/basic/testObjectVsPrototype.js diff --git a/js/src/trace-test/tests/basic/testOwnPropertyWithInOperator.js b/js/src/jit-test/tests/basic/testOwnPropertyWithInOperator.js similarity index 100% rename from js/src/trace-test/tests/basic/testOwnPropertyWithInOperator.js rename to js/src/jit-test/tests/basic/testOwnPropertyWithInOperator.js diff --git a/js/src/trace-test/tests/basic/testPartialFlatClosure.js b/js/src/jit-test/tests/basic/testPartialFlatClosure.js similarity index 100% rename from js/src/trace-test/tests/basic/testPartialFlatClosure.js rename to js/src/jit-test/tests/basic/testPartialFlatClosure.js diff --git a/js/src/trace-test/tests/basic/testPrimitiveConstructorPrototype.js b/js/src/jit-test/tests/basic/testPrimitiveConstructorPrototype.js similarity index 100% rename from js/src/trace-test/tests/basic/testPrimitiveConstructorPrototype.js rename to js/src/jit-test/tests/basic/testPrimitiveConstructorPrototype.js diff --git a/js/src/trace-test/tests/basic/testPropagatedFunArgs.js b/js/src/jit-test/tests/basic/testPropagatedFunArgs.js similarity index 100% rename from js/src/trace-test/tests/basic/testPropagatedFunArgs.js rename to js/src/jit-test/tests/basic/testPropagatedFunArgs.js diff --git a/js/src/trace-test/tests/basic/testProxyConstructors.js b/js/src/jit-test/tests/basic/testProxyConstructors.js similarity index 100% rename from js/src/trace-test/tests/basic/testProxyConstructors.js rename to js/src/jit-test/tests/basic/testProxyConstructors.js diff --git a/js/src/trace-test/tests/basic/testProxyDefinePropertyWithMissingSetter.js b/js/src/jit-test/tests/basic/testProxyDefinePropertyWithMissingSetter.js similarity index 100% rename from js/src/trace-test/tests/basic/testProxyDefinePropertyWithMissingSetter.js rename to js/src/jit-test/tests/basic/testProxyDefinePropertyWithMissingSetter.js diff --git a/js/src/trace-test/tests/basic/testPutOnEmptyArgsObject.js b/js/src/jit-test/tests/basic/testPutOnEmptyArgsObject.js similarity index 100% rename from js/src/trace-test/tests/basic/testPutOnEmptyArgsObject.js rename to js/src/jit-test/tests/basic/testPutOnEmptyArgsObject.js diff --git a/js/src/trace-test/tests/basic/testRUNLOOPCorrectness.js b/js/src/jit-test/tests/basic/testRUNLOOPCorrectness.js similarity index 100% rename from js/src/trace-test/tests/basic/testRUNLOOPCorrectness.js rename to js/src/jit-test/tests/basic/testRUNLOOPCorrectness.js diff --git a/js/src/trace-test/tests/basic/testReallyDeepNestedExit.js b/js/src/jit-test/tests/basic/testReallyDeepNestedExit.js similarity index 100% rename from js/src/trace-test/tests/basic/testReallyDeepNestedExit.js rename to js/src/jit-test/tests/basic/testReallyDeepNestedExit.js diff --git a/js/src/trace-test/tests/basic/testRebranding.js b/js/src/jit-test/tests/basic/testRebranding.js similarity index 100% rename from js/src/trace-test/tests/basic/testRebranding.js rename to js/src/jit-test/tests/basic/testRebranding.js diff --git a/js/src/trace-test/tests/basic/testRebranding2.js b/js/src/jit-test/tests/basic/testRebranding2.js similarity index 100% rename from js/src/trace-test/tests/basic/testRebranding2.js rename to js/src/jit-test/tests/basic/testRebranding2.js diff --git a/js/src/trace-test/tests/basic/testReconstructImacroPCStack.js b/js/src/jit-test/tests/basic/testReconstructImacroPCStack.js similarity index 100% rename from js/src/trace-test/tests/basic/testReconstructImacroPCStack.js rename to js/src/jit-test/tests/basic/testReconstructImacroPCStack.js diff --git a/js/src/trace-test/tests/basic/testRegExpLiteral.js b/js/src/jit-test/tests/basic/testRegExpLiteral.js similarity index 100% rename from js/src/trace-test/tests/basic/testRegExpLiteral.js rename to js/src/jit-test/tests/basic/testRegExpLiteral.js diff --git a/js/src/trace-test/tests/basic/testRegExpTest.js b/js/src/jit-test/tests/basic/testRegExpTest.js similarity index 75% rename from js/src/trace-test/tests/basic/testRegExpTest.js rename to js/src/jit-test/tests/basic/testRegExpTest.js index 664c125612c0..78917ba9be33 100644 --- a/js/src/trace-test/tests/basic/testRegExpTest.js +++ b/js/src/jit-test/tests/basic/testRegExpTest.js @@ -1,4 +1,4 @@ -// |trace-test| TMFLAGS: full,fragprofile,treevis; valgrind +// |jit-test| TMFLAGS: full,fragprofile,treevis; valgrind function testRegExpTest() { var r = /abc/; diff --git a/js/src/trace-test/tests/basic/testRegexpGet.js b/js/src/jit-test/tests/basic/testRegexpGet.js similarity index 100% rename from js/src/trace-test/tests/basic/testRegexpGet.js rename to js/src/jit-test/tests/basic/testRegexpGet.js diff --git a/js/src/trace-test/tests/basic/testReplace2.js b/js/src/jit-test/tests/basic/testReplace2.js similarity index 100% rename from js/src/trace-test/tests/basic/testReplace2.js rename to js/src/jit-test/tests/basic/testReplace2.js diff --git a/js/src/trace-test/tests/basic/testResumeOp.js b/js/src/jit-test/tests/basic/testResumeOp.js similarity index 100% rename from js/src/trace-test/tests/basic/testResumeOp.js rename to js/src/jit-test/tests/basic/testResumeOp.js diff --git a/js/src/trace-test/tests/basic/testReverseArgTypes.js b/js/src/jit-test/tests/basic/testReverseArgTypes.js similarity index 100% rename from js/src/trace-test/tests/basic/testReverseArgTypes.js rename to js/src/jit-test/tests/basic/testReverseArgTypes.js diff --git a/js/src/trace-test/tests/basic/testScriptGetter_JSOP_CALLPROP-2.js b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP-2.js similarity index 100% rename from js/src/trace-test/tests/basic/testScriptGetter_JSOP_CALLPROP-2.js rename to js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP-2.js diff --git a/js/src/trace-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js similarity index 100% rename from js/src/trace-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js rename to js/src/jit-test/tests/basic/testScriptGetter_JSOP_CALLPROP.js diff --git a/js/src/trace-test/tests/basic/testScriptGetter_JSOP_GETARGPROP.js b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_GETARGPROP.js similarity index 100% rename from js/src/trace-test/tests/basic/testScriptGetter_JSOP_GETARGPROP.js rename to js/src/jit-test/tests/basic/testScriptGetter_JSOP_GETARGPROP.js diff --git a/js/src/trace-test/tests/basic/testScriptGetter_JSOP_GETLOCALPROP.js b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_GETLOCALPROP.js similarity index 100% rename from js/src/trace-test/tests/basic/testScriptGetter_JSOP_GETLOCALPROP.js rename to js/src/jit-test/tests/basic/testScriptGetter_JSOP_GETLOCALPROP.js diff --git a/js/src/trace-test/tests/basic/testScriptGetter_JSOP_GETPROP.js b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_GETPROP.js similarity index 100% rename from js/src/trace-test/tests/basic/testScriptGetter_JSOP_GETPROP.js rename to js/src/jit-test/tests/basic/testScriptGetter_JSOP_GETPROP.js diff --git a/js/src/trace-test/tests/basic/testScriptGetter_JSOP_GETTHISPROP.js b/js/src/jit-test/tests/basic/testScriptGetter_JSOP_GETTHISPROP.js similarity index 100% rename from js/src/trace-test/tests/basic/testScriptGetter_JSOP_GETTHISPROP.js rename to js/src/jit-test/tests/basic/testScriptGetter_JSOP_GETTHISPROP.js diff --git a/js/src/trace-test/tests/basic/testSetGetterOnlyProperty.js b/js/src/jit-test/tests/basic/testSetGetterOnlyProperty.js similarity index 100% rename from js/src/trace-test/tests/basic/testSetGetterOnlyProperty.js rename to js/src/jit-test/tests/basic/testSetGetterOnlyProperty.js diff --git a/js/src/trace-test/tests/basic/testSetMethod.js b/js/src/jit-test/tests/basic/testSetMethod.js similarity index 100% rename from js/src/trace-test/tests/basic/testSetMethod.js rename to js/src/jit-test/tests/basic/testSetMethod.js diff --git a/js/src/trace-test/tests/basic/testSetPropNeitherMissNorHit.js b/js/src/jit-test/tests/basic/testSetPropNeitherMissNorHit.js similarity index 100% rename from js/src/trace-test/tests/basic/testSetPropNeitherMissNorHit.js rename to js/src/jit-test/tests/basic/testSetPropNeitherMissNorHit.js diff --git a/js/src/trace-test/tests/basic/testSetPropertyFail.js b/js/src/jit-test/tests/basic/testSetPropertyFail.js similarity index 100% rename from js/src/trace-test/tests/basic/testSetPropertyFail.js rename to js/src/jit-test/tests/basic/testSetPropertyFail.js diff --git a/js/src/trace-test/tests/basic/testSetProtoRegeneratesObjectShape.js b/js/src/jit-test/tests/basic/testSetProtoRegeneratesObjectShape.js similarity index 100% rename from js/src/trace-test/tests/basic/testSetProtoRegeneratesObjectShape.js rename to js/src/jit-test/tests/basic/testSetProtoRegeneratesObjectShape.js diff --git a/js/src/trace-test/tests/basic/testSetelemWithFloatIndex.js b/js/src/jit-test/tests/basic/testSetelemWithFloatIndex.js similarity index 100% rename from js/src/trace-test/tests/basic/testSetelemWithFloatIndex.js rename to js/src/jit-test/tests/basic/testSetelemWithFloatIndex.js diff --git a/js/src/trace-test/tests/basic/testSettingWatchPointOnReadOnlyProp.js b/js/src/jit-test/tests/basic/testSettingWatchPointOnReadOnlyProp.js similarity index 100% rename from js/src/trace-test/tests/basic/testSettingWatchPointOnReadOnlyProp.js rename to js/src/jit-test/tests/basic/testSettingWatchPointOnReadOnlyProp.js diff --git a/js/src/trace-test/tests/basic/testShiftLeft.js b/js/src/jit-test/tests/basic/testShiftLeft.js similarity index 94% rename from js/src/trace-test/tests/basic/testShiftLeft.js rename to js/src/jit-test/tests/basic/testShiftLeft.js index d94976798f21..4a7f5d982897 100644 --- a/js/src/trace-test/tests/basic/testShiftLeft.js +++ b/js/src/jit-test/tests/basic/testShiftLeft.js @@ -1,4 +1,4 @@ -// |trace-test| TMFLAGS: full,fragprofile,treevis; valgrind +// |jit-test| TMFLAGS: full,fragprofile,treevis; valgrind /* Test the proper operation of the left shift operator. This is especially * important on ARM as an explicit mask is required at the native instruction diff --git a/js/src/trace-test/tests/basic/testShiftRightArithmetic.js b/js/src/jit-test/tests/basic/testShiftRightArithmetic.js similarity index 100% rename from js/src/trace-test/tests/basic/testShiftRightArithmetic.js rename to js/src/jit-test/tests/basic/testShiftRightArithmetic.js diff --git a/js/src/trace-test/tests/basic/testShiftRightLogical.js b/js/src/jit-test/tests/basic/testShiftRightLogical.js similarity index 100% rename from js/src/trace-test/tests/basic/testShiftRightLogical.js rename to js/src/jit-test/tests/basic/testShiftRightLogical.js diff --git a/js/src/trace-test/tests/basic/testSideExitInConstructor.js b/js/src/jit-test/tests/basic/testSideExitInConstructor.js similarity index 92% rename from js/src/trace-test/tests/basic/testSideExitInConstructor.js rename to js/src/jit-test/tests/basic/testSideExitInConstructor.js index 4dfddebf9e15..d46543ef7bd0 100644 --- a/js/src/trace-test/tests/basic/testSideExitInConstructor.js +++ b/js/src/jit-test/tests/basic/testSideExitInConstructor.js @@ -1,4 +1,4 @@ -// |trace-test| TMFLAGS: full,fragprofile,treevis; valgrind +// |jit-test| TMFLAGS: full,fragprofile,treevis; valgrind function testSideExitInConstructor() { var FCKConfig = {}; diff --git a/js/src/trace-test/tests/basic/testSlowArrayLength.js b/js/src/jit-test/tests/basic/testSlowArrayLength.js similarity index 100% rename from js/src/trace-test/tests/basic/testSlowArrayLength.js rename to js/src/jit-test/tests/basic/testSlowArrayLength.js diff --git a/js/src/trace-test/tests/basic/testSlowArrayPop.js b/js/src/jit-test/tests/basic/testSlowArrayPop.js similarity index 100% rename from js/src/trace-test/tests/basic/testSlowArrayPop.js rename to js/src/jit-test/tests/basic/testSlowArrayPop.js diff --git a/js/src/trace-test/tests/basic/testSlowArrayPopMultiFrame.js b/js/src/jit-test/tests/basic/testSlowArrayPopMultiFrame.js similarity index 100% rename from js/src/trace-test/tests/basic/testSlowArrayPopMultiFrame.js rename to js/src/jit-test/tests/basic/testSlowArrayPopMultiFrame.js diff --git a/js/src/trace-test/tests/basic/testSlowArrayPopNestedTrees.js b/js/src/jit-test/tests/basic/testSlowArrayPopNestedTrees.js similarity index 100% rename from js/src/trace-test/tests/basic/testSlowArrayPopNestedTrees.js rename to js/src/jit-test/tests/basic/testSlowArrayPopNestedTrees.js diff --git a/js/src/trace-test/tests/basic/testSlowNativeBail.js b/js/src/jit-test/tests/basic/testSlowNativeBail.js similarity index 100% rename from js/src/trace-test/tests/basic/testSlowNativeBail.js rename to js/src/jit-test/tests/basic/testSlowNativeBail.js diff --git a/js/src/trace-test/tests/basic/testSlowNativeCtor.js b/js/src/jit-test/tests/basic/testSlowNativeCtor.js similarity index 100% rename from js/src/trace-test/tests/basic/testSlowNativeCtor.js rename to js/src/jit-test/tests/basic/testSlowNativeCtor.js diff --git a/js/src/trace-test/tests/basic/testSlowNativeWithNullThis.js b/js/src/jit-test/tests/basic/testSlowNativeWithNullThis.js similarity index 100% rename from js/src/trace-test/tests/basic/testSlowNativeWithNullThis.js rename to js/src/jit-test/tests/basic/testSlowNativeWithNullThis.js diff --git a/js/src/trace-test/tests/basic/testStackQuotaExhausted.js b/js/src/jit-test/tests/basic/testStackQuotaExhausted.js similarity index 100% rename from js/src/trace-test/tests/basic/testStackQuotaExhausted.js rename to js/src/jit-test/tests/basic/testStackQuotaExhausted.js diff --git a/js/src/trace-test/tests/basic/testStaticsInRegExp.js b/js/src/jit-test/tests/basic/testStaticsInRegExp.js similarity index 100% rename from js/src/trace-test/tests/basic/testStaticsInRegExp.js rename to js/src/jit-test/tests/basic/testStaticsInRegExp.js diff --git a/js/src/trace-test/tests/basic/testStrict.js b/js/src/jit-test/tests/basic/testStrict.js similarity index 100% rename from js/src/trace-test/tests/basic/testStrict.js rename to js/src/jit-test/tests/basic/testStrict.js diff --git a/js/src/trace-test/tests/basic/testString.js b/js/src/jit-test/tests/basic/testString.js similarity index 100% rename from js/src/trace-test/tests/basic/testString.js rename to js/src/jit-test/tests/basic/testString.js diff --git a/js/src/trace-test/tests/basic/testStringConstructorWithExtraArg.js b/js/src/jit-test/tests/basic/testStringConstructorWithExtraArg.js similarity index 100% rename from js/src/trace-test/tests/basic/testStringConstructorWithExtraArg.js rename to js/src/jit-test/tests/basic/testStringConstructorWithExtraArg.js diff --git a/js/src/trace-test/tests/basic/testStringLengthNoTinyId.js b/js/src/jit-test/tests/basic/testStringLengthNoTinyId.js similarity index 100% rename from js/src/trace-test/tests/basic/testStringLengthNoTinyId.js rename to js/src/jit-test/tests/basic/testStringLengthNoTinyId.js diff --git a/js/src/trace-test/tests/basic/testStringObjectLength.js b/js/src/jit-test/tests/basic/testStringObjectLength.js similarity index 100% rename from js/src/trace-test/tests/basic/testStringObjectLength.js rename to js/src/jit-test/tests/basic/testStringObjectLength.js diff --git a/js/src/trace-test/tests/basic/testStringResolve.js b/js/src/jit-test/tests/basic/testStringResolve.js similarity index 100% rename from js/src/trace-test/tests/basic/testStringResolve.js rename to js/src/jit-test/tests/basic/testStringResolve.js diff --git a/js/src/trace-test/tests/basic/testStringToInt32.js b/js/src/jit-test/tests/basic/testStringToInt32.js similarity index 100% rename from js/src/trace-test/tests/basic/testStringToInt32.js rename to js/src/jit-test/tests/basic/testStringToInt32.js diff --git a/js/src/trace-test/tests/basic/testStringToNumber.js b/js/src/jit-test/tests/basic/testStringToNumber.js similarity index 100% rename from js/src/trace-test/tests/basic/testStringToNumber.js rename to js/src/jit-test/tests/basic/testStringToNumber.js diff --git a/js/src/trace-test/tests/basic/testStringify.js b/js/src/jit-test/tests/basic/testStringify.js similarity index 100% rename from js/src/trace-test/tests/basic/testStringify.js rename to js/src/jit-test/tests/basic/testStringify.js diff --git a/js/src/trace-test/tests/basic/testSubstring.js b/js/src/jit-test/tests/basic/testSubstring.js similarity index 100% rename from js/src/trace-test/tests/basic/testSubstring.js rename to js/src/jit-test/tests/basic/testSubstring.js diff --git a/js/src/trace-test/tests/basic/testSuppressDeletedProperty.js b/js/src/jit-test/tests/basic/testSuppressDeletedProperty.js similarity index 100% rename from js/src/trace-test/tests/basic/testSuppressDeletedProperty.js rename to js/src/jit-test/tests/basic/testSuppressDeletedProperty.js diff --git a/js/src/trace-test/tests/basic/testSwitch.js b/js/src/jit-test/tests/basic/testSwitch.js similarity index 100% rename from js/src/trace-test/tests/basic/testSwitch.js rename to js/src/jit-test/tests/basic/testSwitch.js diff --git a/js/src/trace-test/tests/basic/testSwitchString.js b/js/src/jit-test/tests/basic/testSwitchString.js similarity index 100% rename from js/src/trace-test/tests/basic/testSwitchString.js rename to js/src/jit-test/tests/basic/testSwitchString.js diff --git a/js/src/trace-test/tests/basic/testSwitchUndefined.js b/js/src/jit-test/tests/basic/testSwitchUndefined.js similarity index 100% rename from js/src/trace-test/tests/basic/testSwitchUndefined.js rename to js/src/jit-test/tests/basic/testSwitchUndefined.js diff --git a/js/src/trace-test/tests/basic/testTableSwitch1.js b/js/src/jit-test/tests/basic/testTableSwitch1.js similarity index 100% rename from js/src/trace-test/tests/basic/testTableSwitch1.js rename to js/src/jit-test/tests/basic/testTableSwitch1.js diff --git a/js/src/trace-test/tests/basic/testTableSwitch2.js b/js/src/jit-test/tests/basic/testTableSwitch2.js similarity index 100% rename from js/src/trace-test/tests/basic/testTableSwitch2.js rename to js/src/jit-test/tests/basic/testTableSwitch2.js diff --git a/js/src/trace-test/tests/basic/testThinForEach.js b/js/src/jit-test/tests/basic/testThinForEach.js similarity index 100% rename from js/src/trace-test/tests/basic/testThinForEach.js rename to js/src/jit-test/tests/basic/testThinForEach.js diff --git a/js/src/trace-test/tests/basic/testThinLoopDemote.js b/js/src/jit-test/tests/basic/testThinLoopDemote.js similarity index 100% rename from js/src/trace-test/tests/basic/testThinLoopDemote.js rename to js/src/jit-test/tests/basic/testThinLoopDemote.js diff --git a/js/src/trace-test/tests/basic/testThrowingObjectEqUndefined.js b/js/src/jit-test/tests/basic/testThrowingObjectEqUndefined.js similarity index 100% rename from js/src/trace-test/tests/basic/testThrowingObjectEqUndefined.js rename to js/src/jit-test/tests/basic/testThrowingObjectEqUndefined.js diff --git a/js/src/trace-test/tests/basic/testToStringBeforeValueOf.js b/js/src/jit-test/tests/basic/testToStringBeforeValueOf.js similarity index 100% rename from js/src/trace-test/tests/basic/testToStringBeforeValueOf.js rename to js/src/jit-test/tests/basic/testToStringBeforeValueOf.js diff --git a/js/src/trace-test/tests/basic/testToUpperToLower.js b/js/src/jit-test/tests/basic/testToUpperToLower.js similarity index 100% rename from js/src/trace-test/tests/basic/testToUpperToLower.js rename to js/src/jit-test/tests/basic/testToUpperToLower.js diff --git a/js/src/trace-test/tests/basic/testTrueShiftTrue.js b/js/src/jit-test/tests/basic/testTrueShiftTrue.js similarity index 100% rename from js/src/trace-test/tests/basic/testTrueShiftTrue.js rename to js/src/jit-test/tests/basic/testTrueShiftTrue.js diff --git a/js/src/trace-test/tests/basic/testTypeUnstableForIn.js b/js/src/jit-test/tests/basic/testTypeUnstableForIn.js similarity index 100% rename from js/src/trace-test/tests/basic/testTypeUnstableForIn.js rename to js/src/jit-test/tests/basic/testTypeUnstableForIn.js diff --git a/js/src/trace-test/tests/basic/testTypedArrayPunning.js b/js/src/jit-test/tests/basic/testTypedArrayPunning.js similarity index 100% rename from js/src/trace-test/tests/basic/testTypedArrayPunning.js rename to js/src/jit-test/tests/basic/testTypedArrayPunning.js diff --git a/js/src/trace-test/tests/basic/testTypedArrays.js b/js/src/jit-test/tests/basic/testTypedArrays.js similarity index 100% rename from js/src/trace-test/tests/basic/testTypedArrays.js rename to js/src/jit-test/tests/basic/testTypedArrays.js diff --git a/js/src/trace-test/tests/basic/testTypeofHole.js b/js/src/jit-test/tests/basic/testTypeofHole.js similarity index 100% rename from js/src/trace-test/tests/basic/testTypeofHole.js rename to js/src/jit-test/tests/basic/testTypeofHole.js diff --git a/js/src/trace-test/tests/basic/testUnaryImacros.js b/js/src/jit-test/tests/basic/testUnaryImacros.js similarity index 100% rename from js/src/trace-test/tests/basic/testUnaryImacros.js rename to js/src/jit-test/tests/basic/testUnaryImacros.js diff --git a/js/src/trace-test/tests/basic/testUndefinedBooleanCmp.js b/js/src/jit-test/tests/basic/testUndefinedBooleanCmp.js similarity index 100% rename from js/src/trace-test/tests/basic/testUndefinedBooleanCmp.js rename to js/src/jit-test/tests/basic/testUndefinedBooleanCmp.js diff --git a/js/src/trace-test/tests/basic/testUndefinedCmp.js b/js/src/jit-test/tests/basic/testUndefinedCmp.js similarity index 100% rename from js/src/trace-test/tests/basic/testUndefinedCmp.js rename to js/src/jit-test/tests/basic/testUndefinedCmp.js diff --git a/js/src/trace-test/tests/basic/testUndefinedPropertyAccess.js b/js/src/jit-test/tests/basic/testUndefinedPropertyAccess.js similarity index 100% rename from js/src/trace-test/tests/basic/testUndefinedPropertyAccess.js rename to js/src/jit-test/tests/basic/testUndefinedPropertyAccess.js diff --git a/js/src/trace-test/tests/basic/testUndemotableBinaryOp.js b/js/src/jit-test/tests/basic/testUndemotableBinaryOp.js similarity index 100% rename from js/src/trace-test/tests/basic/testUndemotableBinaryOp.js rename to js/src/jit-test/tests/basic/testUndemotableBinaryOp.js diff --git a/js/src/trace-test/tests/basic/testUndemoteLateGlobalSlots.js b/js/src/jit-test/tests/basic/testUndemoteLateGlobalSlots.js similarity index 100% rename from js/src/trace-test/tests/basic/testUndemoteLateGlobalSlots.js rename to js/src/jit-test/tests/basic/testUndemoteLateGlobalSlots.js diff --git a/js/src/trace-test/tests/basic/testWeirdDateParse.js b/js/src/jit-test/tests/basic/testWeirdDateParse.js similarity index 100% rename from js/src/trace-test/tests/basic/testWeirdDateParse.js rename to js/src/jit-test/tests/basic/testWeirdDateParse.js diff --git a/js/src/trace-test/tests/basic/testWhileObjectOrNull.js b/js/src/jit-test/tests/basic/testWhileObjectOrNull.js similarity index 100% rename from js/src/trace-test/tests/basic/testWhileObjectOrNull.js rename to js/src/jit-test/tests/basic/testWhileObjectOrNull.js diff --git a/js/src/trace-test/tests/basic/testWithAndShadowing.js b/js/src/jit-test/tests/basic/testWithAndShadowing.js similarity index 100% rename from js/src/trace-test/tests/basic/testWithAndShadowing.js rename to js/src/jit-test/tests/basic/testWithAndShadowing.js diff --git a/js/src/trace-test/tests/basic/testXMLPropertyNames.js b/js/src/jit-test/tests/basic/testXMLPropertyNames.js similarity index 100% rename from js/src/trace-test/tests/basic/testXMLPropertyNames.js rename to js/src/jit-test/tests/basic/testXMLPropertyNames.js diff --git a/js/src/trace-test/tests/basic/test_JSOP_ARGCNT.js b/js/src/jit-test/tests/basic/test_JSOP_ARGCNT.js similarity index 100% rename from js/src/trace-test/tests/basic/test_JSOP_ARGCNT.js rename to js/src/jit-test/tests/basic/test_JSOP_ARGCNT.js diff --git a/js/src/trace-test/tests/basic/test_JSOP_ARGSUB.js b/js/src/jit-test/tests/basic/test_JSOP_ARGSUB.js similarity index 100% rename from js/src/trace-test/tests/basic/test_JSOP_ARGSUB.js rename to js/src/jit-test/tests/basic/test_JSOP_ARGSUB.js diff --git a/js/src/trace-test/tests/basic/testif.js b/js/src/jit-test/tests/basic/testif.js similarity index 100% rename from js/src/trace-test/tests/basic/testif.js rename to js/src/jit-test/tests/basic/testif.js diff --git a/js/src/trace-test/tests/basic/testincops.js b/js/src/jit-test/tests/basic/testincops.js similarity index 100% rename from js/src/trace-test/tests/basic/testincops.js rename to js/src/jit-test/tests/basic/testincops.js diff --git a/js/src/trace-test/tests/basic/trees.js b/js/src/jit-test/tests/basic/trees.js similarity index 100% rename from js/src/trace-test/tests/basic/trees.js rename to js/src/jit-test/tests/basic/trees.js diff --git a/js/src/trace-test/tests/basic/truthies.js b/js/src/jit-test/tests/basic/truthies.js similarity index 100% rename from js/src/trace-test/tests/basic/truthies.js rename to js/src/jit-test/tests/basic/truthies.js diff --git a/js/src/trace-test/tests/basic/typeofTest.js b/js/src/jit-test/tests/basic/typeofTest.js similarity index 100% rename from js/src/trace-test/tests/basic/typeofTest.js rename to js/src/jit-test/tests/basic/typeofTest.js diff --git a/js/src/trace-test/tests/basic/unboxint.js b/js/src/jit-test/tests/basic/unboxint.js similarity index 100% rename from js/src/trace-test/tests/basic/unboxint.js rename to js/src/jit-test/tests/basic/unboxint.js diff --git a/js/src/trace-test/tests/basic/wrap-primitive-this.js b/js/src/jit-test/tests/basic/wrap-primitive-this.js similarity index 100% rename from js/src/trace-test/tests/basic/wrap-primitive-this.js rename to js/src/jit-test/tests/basic/wrap-primitive-this.js diff --git a/js/src/trace-test/tests/basic/xprop.js b/js/src/jit-test/tests/basic/xprop.js similarity index 100% rename from js/src/trace-test/tests/basic/xprop.js rename to js/src/jit-test/tests/basic/xprop.js diff --git a/js/src/jit-test/tests/bug606083.js b/js/src/jit-test/tests/bug606083.js new file mode 100644 index 000000000000..fc2594b0ead3 --- /dev/null +++ b/js/src/jit-test/tests/bug606083.js @@ -0,0 +1,32 @@ +// vim: set ts=4 sw=4 tw=99 et: +function f(L) { + do { + L: for (var i = 0; i < L; i++) { + break L; + } + } while (0); +} +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); +f(1); diff --git a/js/src/trace-test/tests/closures/bug496922.js b/js/src/jit-test/tests/closures/bug496922.js similarity index 100% rename from js/src/trace-test/tests/closures/bug496922.js rename to js/src/jit-test/tests/closures/bug496922.js diff --git a/js/src/trace-test/tests/closures/bug496987.js b/js/src/jit-test/tests/closures/bug496987.js similarity index 100% rename from js/src/trace-test/tests/closures/bug496987.js rename to js/src/jit-test/tests/closures/bug496987.js diff --git a/js/src/trace-test/tests/closures/bug497015-1.js b/js/src/jit-test/tests/closures/bug497015-1.js similarity index 100% rename from js/src/trace-test/tests/closures/bug497015-1.js rename to js/src/jit-test/tests/closures/bug497015-1.js diff --git a/js/src/trace-test/tests/closures/bug497015-2.js b/js/src/jit-test/tests/closures/bug497015-2.js similarity index 100% rename from js/src/trace-test/tests/closures/bug497015-2.js rename to js/src/jit-test/tests/closures/bug497015-2.js diff --git a/js/src/trace-test/tests/closures/bug540131-2.js b/js/src/jit-test/tests/closures/bug540131-2.js similarity index 86% rename from js/src/trace-test/tests/closures/bug540131-2.js rename to js/src/jit-test/tests/closures/bug540131-2.js index a6235c10f689..ebd3e0203a8e 100644 --- a/js/src/trace-test/tests/closures/bug540131-2.js +++ b/js/src/jit-test/tests/closures/bug540131-2.js @@ -1,4 +1,4 @@ -// |trace-test| error: TypeError +// |jit-test| error: TypeError (function() { for (let z in [true]) { (new(eval("for(l in[0,0,0,0]){}")) diff --git a/js/src/trace-test/tests/closures/bug540131-3.js b/js/src/jit-test/tests/closures/bug540131-3.js similarity index 100% rename from js/src/trace-test/tests/closures/bug540131-3.js rename to js/src/jit-test/tests/closures/bug540131-3.js diff --git a/js/src/trace-test/tests/closures/bug540131.js b/js/src/jit-test/tests/closures/bug540131.js similarity index 100% rename from js/src/trace-test/tests/closures/bug540131.js rename to js/src/jit-test/tests/closures/bug540131.js diff --git a/js/src/trace-test/tests/closures/bug540133.js b/js/src/jit-test/tests/closures/bug540133.js similarity index 100% rename from js/src/trace-test/tests/closures/bug540133.js rename to js/src/jit-test/tests/closures/bug540133.js diff --git a/js/src/trace-test/tests/closures/bug540136.js b/js/src/jit-test/tests/closures/bug540136.js similarity index 87% rename from js/src/trace-test/tests/closures/bug540136.js rename to js/src/jit-test/tests/closures/bug540136.js index bf815fcf5f05..54b57713a7f9 100644 --- a/js/src/trace-test/tests/closures/bug540136.js +++ b/js/src/jit-test/tests/closures/bug540136.js @@ -1,4 +1,4 @@ -// |trace-test| error: TypeError +// |jit-test| error: TypeError (eval("\ (function () {\ diff --git a/js/src/trace-test/tests/closures/bug540242.js b/js/src/jit-test/tests/closures/bug540242.js similarity index 100% rename from js/src/trace-test/tests/closures/bug540242.js rename to js/src/jit-test/tests/closures/bug540242.js diff --git a/js/src/trace-test/tests/closures/bug540243.js b/js/src/jit-test/tests/closures/bug540243.js similarity index 100% rename from js/src/trace-test/tests/closures/bug540243.js rename to js/src/jit-test/tests/closures/bug540243.js diff --git a/js/src/trace-test/tests/closures/bug540348.js b/js/src/jit-test/tests/closures/bug540348.js similarity index 100% rename from js/src/trace-test/tests/closures/bug540348.js rename to js/src/jit-test/tests/closures/bug540348.js diff --git a/js/src/trace-test/tests/closures/bug540528.js b/js/src/jit-test/tests/closures/bug540528.js similarity index 100% rename from js/src/trace-test/tests/closures/bug540528.js rename to js/src/jit-test/tests/closures/bug540528.js diff --git a/js/src/trace-test/tests/closures/bug541239.js b/js/src/jit-test/tests/closures/bug541239.js similarity index 100% rename from js/src/trace-test/tests/closures/bug541239.js rename to js/src/jit-test/tests/closures/bug541239.js diff --git a/js/src/trace-test/tests/closures/bug543565.js b/js/src/jit-test/tests/closures/bug543565.js similarity index 100% rename from js/src/trace-test/tests/closures/bug543565.js rename to js/src/jit-test/tests/closures/bug543565.js diff --git a/js/src/trace-test/tests/closures/closure-pluseq.js b/js/src/jit-test/tests/closures/closure-pluseq.js similarity index 100% rename from js/src/trace-test/tests/closures/closure-pluseq.js rename to js/src/jit-test/tests/closures/closure-pluseq.js diff --git a/js/src/trace-test/tests/closures/closure-pluseq2.js b/js/src/jit-test/tests/closures/closure-pluseq2.js similarity index 100% rename from js/src/trace-test/tests/closures/closure-pluseq2.js rename to js/src/jit-test/tests/closures/closure-pluseq2.js diff --git a/js/src/trace-test/tests/closures/closure-plusplus.js b/js/src/jit-test/tests/closures/closure-plusplus.js similarity index 100% rename from js/src/trace-test/tests/closures/closure-plusplus.js rename to js/src/jit-test/tests/closures/closure-plusplus.js diff --git a/js/src/trace-test/tests/closures/closure-tests.js b/js/src/jit-test/tests/closures/closure-tests.js similarity index 100% rename from js/src/trace-test/tests/closures/closure-tests.js rename to js/src/jit-test/tests/closures/closure-tests.js diff --git a/js/src/trace-test/tests/closures/flat-closure-1.js b/js/src/jit-test/tests/closures/flat-closure-1.js similarity index 100% rename from js/src/trace-test/tests/closures/flat-closure-1.js rename to js/src/jit-test/tests/closures/flat-closure-1.js diff --git a/js/src/trace-test/tests/closures/flat-closure-2.js b/js/src/jit-test/tests/closures/flat-closure-2.js similarity index 100% rename from js/src/trace-test/tests/closures/flat-closure-2.js rename to js/src/jit-test/tests/closures/flat-closure-2.js diff --git a/js/src/trace-test/tests/closures/flat-closure-3.js b/js/src/jit-test/tests/closures/flat-closure-3.js similarity index 100% rename from js/src/trace-test/tests/closures/flat-closure-3.js rename to js/src/jit-test/tests/closures/flat-closure-3.js diff --git a/js/src/trace-test/tests/closures/flat-closure-4.js b/js/src/jit-test/tests/closures/flat-closure-4.js similarity index 100% rename from js/src/trace-test/tests/closures/flat-closure-4.js rename to js/src/jit-test/tests/closures/flat-closure-4.js diff --git a/js/src/trace-test/tests/closures/flat-closure-5.js b/js/src/jit-test/tests/closures/flat-closure-5.js similarity index 100% rename from js/src/trace-test/tests/closures/flat-closure-5.js rename to js/src/jit-test/tests/closures/flat-closure-5.js diff --git a/js/src/trace-test/tests/closures/flat-closure-6.js b/js/src/jit-test/tests/closures/flat-closure-6.js similarity index 100% rename from js/src/trace-test/tests/closures/flat-closure-6.js rename to js/src/jit-test/tests/closures/flat-closure-6.js diff --git a/js/src/trace-test/tests/closures/flat-closure-7.js b/js/src/jit-test/tests/closures/flat-closure-7.js similarity index 100% rename from js/src/trace-test/tests/closures/flat-closure-7.js rename to js/src/jit-test/tests/closures/flat-closure-7.js diff --git a/js/src/trace-test/tests/closures/flat-closure-8.js b/js/src/jit-test/tests/closures/flat-closure-8.js similarity index 100% rename from js/src/trace-test/tests/closures/flat-closure-8.js rename to js/src/jit-test/tests/closures/flat-closure-8.js diff --git a/js/src/trace-test/tests/closures/incr-exit-2.js b/js/src/jit-test/tests/closures/incr-exit-2.js similarity index 100% rename from js/src/trace-test/tests/closures/incr-exit-2.js rename to js/src/jit-test/tests/closures/incr-exit-2.js diff --git a/js/src/trace-test/tests/closures/incr-exit-3.js b/js/src/jit-test/tests/closures/incr-exit-3.js similarity index 100% rename from js/src/trace-test/tests/closures/incr-exit-3.js rename to js/src/jit-test/tests/closures/incr-exit-3.js diff --git a/js/src/trace-test/tests/closures/incr-exit.js b/js/src/jit-test/tests/closures/incr-exit.js similarity index 100% rename from js/src/trace-test/tests/closures/incr-exit.js rename to js/src/jit-test/tests/closures/incr-exit.js diff --git a/js/src/trace-test/tests/closures/lambda-inner-heavy.js b/js/src/jit-test/tests/closures/lambda-inner-heavy.js similarity index 100% rename from js/src/trace-test/tests/closures/lambda-inner-heavy.js rename to js/src/jit-test/tests/closures/lambda-inner-heavy.js diff --git a/js/src/trace-test/tests/closures/lambda-light-returned.js b/js/src/jit-test/tests/closures/lambda-light-returned.js similarity index 100% rename from js/src/trace-test/tests/closures/lambda-light-returned.js rename to js/src/jit-test/tests/closures/lambda-light-returned.js diff --git a/js/src/trace-test/tests/closures/lambda-light.js b/js/src/jit-test/tests/closures/lambda-light.js similarity index 100% rename from js/src/trace-test/tests/closures/lambda-light.js rename to js/src/jit-test/tests/closures/lambda-light.js diff --git a/js/src/trace-test/tests/closures/lambda.js b/js/src/jit-test/tests/closures/lambda.js similarity index 100% rename from js/src/trace-test/tests/closures/lambda.js rename to js/src/jit-test/tests/closures/lambda.js diff --git a/js/src/trace-test/tests/closures/lambdafc.js b/js/src/jit-test/tests/closures/lambdafc.js similarity index 100% rename from js/src/trace-test/tests/closures/lambdafc.js rename to js/src/jit-test/tests/closures/lambdafc.js diff --git a/js/src/trace-test/tests/closures/name-both-hvy.js b/js/src/jit-test/tests/closures/name-both-hvy.js similarity index 100% rename from js/src/trace-test/tests/closures/name-both-hvy.js rename to js/src/jit-test/tests/closures/name-both-hvy.js diff --git a/js/src/trace-test/tests/closures/name-inactive-missing.js b/js/src/jit-test/tests/closures/name-inactive-missing.js similarity index 79% rename from js/src/trace-test/tests/closures/name-inactive-missing.js rename to js/src/jit-test/tests/closures/name-inactive-missing.js index fce7d5d398e3..a0f68486a707 100644 --- a/js/src/trace-test/tests/closures/name-inactive-missing.js +++ b/js/src/jit-test/tests/closures/name-inactive-missing.js @@ -1,4 +1,4 @@ -// |trace-test| error: ReferenceError +// |jit-test| error: ReferenceError function f(k) { function g(j) { diff --git a/js/src/trace-test/tests/closures/name.js b/js/src/jit-test/tests/closures/name.js similarity index 100% rename from js/src/trace-test/tests/closures/name.js rename to js/src/jit-test/tests/closures/name.js diff --git a/js/src/trace-test/tests/closures/name2.js b/js/src/jit-test/tests/closures/name2.js similarity index 100% rename from js/src/trace-test/tests/closures/name2.js rename to js/src/jit-test/tests/closures/name2.js diff --git a/js/src/trace-test/tests/closures/name2a.js b/js/src/jit-test/tests/closures/name2a.js similarity index 100% rename from js/src/trace-test/tests/closures/name2a.js rename to js/src/jit-test/tests/closures/name2a.js diff --git a/js/src/trace-test/tests/closures/name2b.js b/js/src/jit-test/tests/closures/name2b.js similarity index 100% rename from js/src/trace-test/tests/closures/name2b.js rename to js/src/jit-test/tests/closures/name2b.js diff --git a/js/src/trace-test/tests/closures/name3.js b/js/src/jit-test/tests/closures/name3.js similarity index 100% rename from js/src/trace-test/tests/closures/name3.js rename to js/src/jit-test/tests/closures/name3.js diff --git a/js/src/trace-test/tests/closures/name4.js b/js/src/jit-test/tests/closures/name4.js similarity index 100% rename from js/src/trace-test/tests/closures/name4.js rename to js/src/jit-test/tests/closures/name4.js diff --git a/js/src/trace-test/tests/closures/namedLambda.js b/js/src/jit-test/tests/closures/namedLambda.js similarity index 100% rename from js/src/trace-test/tests/closures/namedLambda.js rename to js/src/jit-test/tests/closures/namedLambda.js diff --git a/js/src/trace-test/tests/closures/nameinc-loop-2.js b/js/src/jit-test/tests/closures/nameinc-loop-2.js similarity index 100% rename from js/src/trace-test/tests/closures/nameinc-loop-2.js rename to js/src/jit-test/tests/closures/nameinc-loop-2.js diff --git a/js/src/trace-test/tests/closures/nameinc-loop-3.js b/js/src/jit-test/tests/closures/nameinc-loop-3.js similarity index 100% rename from js/src/trace-test/tests/closures/nameinc-loop-3.js rename to js/src/jit-test/tests/closures/nameinc-loop-3.js diff --git a/js/src/trace-test/tests/closures/nameinc-loop-missing-2.js b/js/src/jit-test/tests/closures/nameinc-loop-missing-2.js similarity index 84% rename from js/src/trace-test/tests/closures/nameinc-loop-missing-2.js rename to js/src/jit-test/tests/closures/nameinc-loop-missing-2.js index 875faa413742..c37b3cc659c0 100644 --- a/js/src/trace-test/tests/closures/nameinc-loop-missing-2.js +++ b/js/src/jit-test/tests/closures/nameinc-loop-missing-2.js @@ -1,4 +1,4 @@ -// |trace-test| error: ReferenceError +// |jit-test| error: ReferenceError for (var i = 0; i < 10; ++i) { var f = function() { diff --git a/js/src/trace-test/tests/closures/nameinc-loop-missing.js b/js/src/jit-test/tests/closures/nameinc-loop-missing.js similarity index 84% rename from js/src/trace-test/tests/closures/nameinc-loop-missing.js rename to js/src/jit-test/tests/closures/nameinc-loop-missing.js index 50ef16e5a189..72eae0e40db1 100644 --- a/js/src/trace-test/tests/closures/nameinc-loop-missing.js +++ b/js/src/jit-test/tests/closures/nameinc-loop-missing.js @@ -1,4 +1,4 @@ -// |trace-test| error: ReferenceError +// |jit-test| error: ReferenceError for (var i = 0; i < 10; ++i) { var f = function() { diff --git a/js/src/trace-test/tests/closures/nameinc-loop.js b/js/src/jit-test/tests/closures/nameinc-loop.js similarity index 100% rename from js/src/trace-test/tests/closures/nameinc-loop.js rename to js/src/jit-test/tests/closures/nameinc-loop.js diff --git a/js/src/trace-test/tests/closures/nameinc.js b/js/src/jit-test/tests/closures/nameinc.js similarity index 100% rename from js/src/trace-test/tests/closures/nameinc.js rename to js/src/jit-test/tests/closures/nameinc.js diff --git a/js/src/trace-test/tests/closures/set-outer-trace-1.js b/js/src/jit-test/tests/closures/set-outer-trace-1.js similarity index 100% rename from js/src/trace-test/tests/closures/set-outer-trace-1.js rename to js/src/jit-test/tests/closures/set-outer-trace-1.js diff --git a/js/src/trace-test/tests/closures/set-outer-trace-2.js b/js/src/jit-test/tests/closures/set-outer-trace-2.js similarity index 100% rename from js/src/trace-test/tests/closures/set-outer-trace-2.js rename to js/src/jit-test/tests/closures/set-outer-trace-2.js diff --git a/js/src/trace-test/tests/closures/set-outer-trace-3.js b/js/src/jit-test/tests/closures/set-outer-trace-3.js similarity index 100% rename from js/src/trace-test/tests/closures/set-outer-trace-3.js rename to js/src/jit-test/tests/closures/set-outer-trace-3.js diff --git a/js/src/trace-test/tests/closures/set-outer-trace-4.js b/js/src/jit-test/tests/closures/set-outer-trace-4.js similarity index 100% rename from js/src/trace-test/tests/closures/set-outer-trace-4.js rename to js/src/jit-test/tests/closures/set-outer-trace-4.js diff --git a/js/src/trace-test/tests/closures/set-outer-trace.js b/js/src/jit-test/tests/closures/set-outer-trace.js similarity index 100% rename from js/src/trace-test/tests/closures/set-outer-trace.js rename to js/src/jit-test/tests/closures/set-outer-trace.js diff --git a/js/src/trace-test/tests/closures/setname-1.js b/js/src/jit-test/tests/closures/setname-1.js similarity index 100% rename from js/src/trace-test/tests/closures/setname-1.js rename to js/src/jit-test/tests/closures/setname-1.js diff --git a/js/src/trace-test/tests/closures/setname-closure-2.js b/js/src/jit-test/tests/closures/setname-closure-2.js similarity index 100% rename from js/src/trace-test/tests/closures/setname-closure-2.js rename to js/src/jit-test/tests/closures/setname-closure-2.js diff --git a/js/src/trace-test/tests/closures/setname-closure.js b/js/src/jit-test/tests/closures/setname-closure.js similarity index 100% rename from js/src/trace-test/tests/closures/setname-closure.js rename to js/src/jit-test/tests/closures/setname-closure.js diff --git a/js/src/trace-test/tests/closures/setname-inner-heavy.js b/js/src/jit-test/tests/closures/setname-inner-heavy.js similarity index 100% rename from js/src/trace-test/tests/closures/setname-inner-heavy.js rename to js/src/jit-test/tests/closures/setname-inner-heavy.js diff --git a/js/src/trace-test/tests/closures/setname-loop-2.js b/js/src/jit-test/tests/closures/setname-loop-2.js similarity index 100% rename from js/src/trace-test/tests/closures/setname-loop-2.js rename to js/src/jit-test/tests/closures/setname-loop-2.js diff --git a/js/src/trace-test/tests/closures/setname-loop.js b/js/src/jit-test/tests/closures/setname-loop.js similarity index 100% rename from js/src/trace-test/tests/closures/setname-loop.js rename to js/src/jit-test/tests/closures/setname-loop.js diff --git a/js/src/trace-test/tests/closures/setname-no-pop.js b/js/src/jit-test/tests/closures/setname-no-pop.js similarity index 100% rename from js/src/trace-test/tests/closures/setname-no-pop.js rename to js/src/jit-test/tests/closures/setname-no-pop.js diff --git a/js/src/trace-test/tests/closures/t001.js b/js/src/jit-test/tests/closures/t001.js similarity index 100% rename from js/src/trace-test/tests/closures/t001.js rename to js/src/jit-test/tests/closures/t001.js diff --git a/js/src/trace-test/tests/closures/t002.js b/js/src/jit-test/tests/closures/t002.js similarity index 100% rename from js/src/trace-test/tests/closures/t002.js rename to js/src/jit-test/tests/closures/t002.js diff --git a/js/src/trace-test/tests/closures/t003.js b/js/src/jit-test/tests/closures/t003.js similarity index 100% rename from js/src/trace-test/tests/closures/t003.js rename to js/src/jit-test/tests/closures/t003.js diff --git a/js/src/trace-test/tests/closures/t004.js b/js/src/jit-test/tests/closures/t004.js similarity index 100% rename from js/src/trace-test/tests/closures/t004.js rename to js/src/jit-test/tests/closures/t004.js diff --git a/js/src/trace-test/tests/closures/t005.js b/js/src/jit-test/tests/closures/t005.js similarity index 100% rename from js/src/trace-test/tests/closures/t005.js rename to js/src/jit-test/tests/closures/t005.js diff --git a/js/src/trace-test/tests/closures/t006.js b/js/src/jit-test/tests/closures/t006.js similarity index 100% rename from js/src/trace-test/tests/closures/t006.js rename to js/src/jit-test/tests/closures/t006.js diff --git a/js/src/trace-test/tests/closures/t007.js b/js/src/jit-test/tests/closures/t007.js similarity index 100% rename from js/src/trace-test/tests/closures/t007.js rename to js/src/jit-test/tests/closures/t007.js diff --git a/js/src/trace-test/tests/closures/t008.js b/js/src/jit-test/tests/closures/t008.js similarity index 100% rename from js/src/trace-test/tests/closures/t008.js rename to js/src/jit-test/tests/closures/t008.js diff --git a/js/src/trace-test/tests/closures/t009.js b/js/src/jit-test/tests/closures/t009.js similarity index 100% rename from js/src/trace-test/tests/closures/t009.js rename to js/src/jit-test/tests/closures/t009.js diff --git a/js/src/trace-test/tests/closures/t010.js b/js/src/jit-test/tests/closures/t010.js similarity index 100% rename from js/src/trace-test/tests/closures/t010.js rename to js/src/jit-test/tests/closures/t010.js diff --git a/js/src/trace-test/tests/closures/t011.js b/js/src/jit-test/tests/closures/t011.js similarity index 100% rename from js/src/trace-test/tests/closures/t011.js rename to js/src/jit-test/tests/closures/t011.js diff --git a/js/src/trace-test/tests/closures/t012.js b/js/src/jit-test/tests/closures/t012.js similarity index 100% rename from js/src/trace-test/tests/closures/t012.js rename to js/src/jit-test/tests/closures/t012.js diff --git a/js/src/trace-test/tests/closures/t013.js b/js/src/jit-test/tests/closures/t013.js similarity index 100% rename from js/src/trace-test/tests/closures/t013.js rename to js/src/jit-test/tests/closures/t013.js diff --git a/js/src/trace-test/tests/closures/t014.js b/js/src/jit-test/tests/closures/t014.js similarity index 100% rename from js/src/trace-test/tests/closures/t014.js rename to js/src/jit-test/tests/closures/t014.js diff --git a/js/src/trace-test/tests/closures/t015.js b/js/src/jit-test/tests/closures/t015.js similarity index 100% rename from js/src/trace-test/tests/closures/t015.js rename to js/src/jit-test/tests/closures/t015.js diff --git a/js/src/trace-test/tests/closures/t016.js b/js/src/jit-test/tests/closures/t016.js similarity index 100% rename from js/src/trace-test/tests/closures/t016.js rename to js/src/jit-test/tests/closures/t016.js diff --git a/js/src/trace-test/tests/closures/t017.js b/js/src/jit-test/tests/closures/t017.js similarity index 100% rename from js/src/trace-test/tests/closures/t017.js rename to js/src/jit-test/tests/closures/t017.js diff --git a/js/src/trace-test/tests/closures/t018.js b/js/src/jit-test/tests/closures/t018.js similarity index 100% rename from js/src/trace-test/tests/closures/t018.js rename to js/src/jit-test/tests/closures/t018.js diff --git a/js/src/trace-test/tests/closures/t019.js b/js/src/jit-test/tests/closures/t019.js similarity index 100% rename from js/src/trace-test/tests/closures/t019.js rename to js/src/jit-test/tests/closures/t019.js diff --git a/js/src/trace-test/tests/closures/t020.js b/js/src/jit-test/tests/closures/t020.js similarity index 100% rename from js/src/trace-test/tests/closures/t020.js rename to js/src/jit-test/tests/closures/t020.js diff --git a/js/src/trace-test/tests/closures/t021.js b/js/src/jit-test/tests/closures/t021.js similarity index 100% rename from js/src/trace-test/tests/closures/t021.js rename to js/src/jit-test/tests/closures/t021.js diff --git a/js/src/trace-test/tests/closures/t022.js b/js/src/jit-test/tests/closures/t022.js similarity index 100% rename from js/src/trace-test/tests/closures/t022.js rename to js/src/jit-test/tests/closures/t022.js diff --git a/js/src/trace-test/tests/closures/t023.js b/js/src/jit-test/tests/closures/t023.js similarity index 100% rename from js/src/trace-test/tests/closures/t023.js rename to js/src/jit-test/tests/closures/t023.js diff --git a/js/src/trace-test/tests/closures/t024.js b/js/src/jit-test/tests/closures/t024.js similarity index 100% rename from js/src/trace-test/tests/closures/t024.js rename to js/src/jit-test/tests/closures/t024.js diff --git a/js/src/trace-test/tests/closures/t025.js b/js/src/jit-test/tests/closures/t025.js similarity index 100% rename from js/src/trace-test/tests/closures/t025.js rename to js/src/jit-test/tests/closures/t025.js diff --git a/js/src/trace-test/tests/closures/t026.js b/js/src/jit-test/tests/closures/t026.js similarity index 100% rename from js/src/trace-test/tests/closures/t026.js rename to js/src/jit-test/tests/closures/t026.js diff --git a/js/src/trace-test/tests/closures/t027.js b/js/src/jit-test/tests/closures/t027.js similarity index 100% rename from js/src/trace-test/tests/closures/t027.js rename to js/src/jit-test/tests/closures/t027.js diff --git a/js/src/trace-test/tests/closures/t028.js b/js/src/jit-test/tests/closures/t028.js similarity index 100% rename from js/src/trace-test/tests/closures/t028.js rename to js/src/jit-test/tests/closures/t028.js diff --git a/js/src/trace-test/tests/closures/t029.js b/js/src/jit-test/tests/closures/t029.js similarity index 100% rename from js/src/trace-test/tests/closures/t029.js rename to js/src/jit-test/tests/closures/t029.js diff --git a/js/src/trace-test/tests/closures/t030.js b/js/src/jit-test/tests/closures/t030.js similarity index 100% rename from js/src/trace-test/tests/closures/t030.js rename to js/src/jit-test/tests/closures/t030.js diff --git a/js/src/trace-test/tests/closures/t031.js b/js/src/jit-test/tests/closures/t031.js similarity index 100% rename from js/src/trace-test/tests/closures/t031.js rename to js/src/jit-test/tests/closures/t031.js diff --git a/js/src/trace-test/tests/closures/t032.js b/js/src/jit-test/tests/closures/t032.js similarity index 100% rename from js/src/trace-test/tests/closures/t032.js rename to js/src/jit-test/tests/closures/t032.js diff --git a/js/src/trace-test/tests/closures/t033.js b/js/src/jit-test/tests/closures/t033.js similarity index 100% rename from js/src/trace-test/tests/closures/t033.js rename to js/src/jit-test/tests/closures/t033.js diff --git a/js/src/trace-test/tests/closures/t034.js b/js/src/jit-test/tests/closures/t034.js similarity index 100% rename from js/src/trace-test/tests/closures/t034.js rename to js/src/jit-test/tests/closures/t034.js diff --git a/js/src/trace-test/tests/closures/t035.js b/js/src/jit-test/tests/closures/t035.js similarity index 100% rename from js/src/trace-test/tests/closures/t035.js rename to js/src/jit-test/tests/closures/t035.js diff --git a/js/src/trace-test/tests/closures/t036.js b/js/src/jit-test/tests/closures/t036.js similarity index 100% rename from js/src/trace-test/tests/closures/t036.js rename to js/src/jit-test/tests/closures/t036.js diff --git a/js/src/trace-test/tests/closures/t037.js b/js/src/jit-test/tests/closures/t037.js similarity index 100% rename from js/src/trace-test/tests/closures/t037.js rename to js/src/jit-test/tests/closures/t037.js diff --git a/js/src/trace-test/tests/closures/test-inner-imports.js b/js/src/jit-test/tests/closures/test-inner-imports.js similarity index 100% rename from js/src/trace-test/tests/closures/test-inner-imports.js rename to js/src/jit-test/tests/closures/test-inner-imports.js diff --git a/js/src/trace-test/tests/closures/upvar-nest.js b/js/src/jit-test/tests/closures/upvar-nest.js similarity index 100% rename from js/src/trace-test/tests/closures/upvar-nest.js rename to js/src/jit-test/tests/closures/upvar-nest.js diff --git a/js/src/trace-test/tests/jaeger/bug549393-1.js b/js/src/jit-test/tests/jaeger/bug549393-1.js similarity index 96% rename from js/src/trace-test/tests/jaeger/bug549393-1.js rename to js/src/jit-test/tests/jaeger/bug549393-1.js index 695b438732ae..d98cc0b45ea8 100644 --- a/js/src/trace-test/tests/jaeger/bug549393-1.js +++ b/js/src/jit-test/tests/jaeger/bug549393-1.js @@ -1,4 +1,4 @@ -// |trace-test| error: TypeError +// |jit-test| error: TypeError function start() { MAX_TOTAL_TIME = startTime = new Date do { diff --git a/js/src/trace-test/tests/jaeger/bug549393-2.js b/js/src/jit-test/tests/jaeger/bug549393-2.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug549393-2.js rename to js/src/jit-test/tests/jaeger/bug549393-2.js diff --git a/js/src/trace-test/tests/jaeger/bug549396.js b/js/src/jit-test/tests/jaeger/bug549396.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug549396.js rename to js/src/jit-test/tests/jaeger/bug549396.js diff --git a/js/src/trace-test/tests/jaeger/bug549398.js b/js/src/jit-test/tests/jaeger/bug549398.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug549398.js rename to js/src/jit-test/tests/jaeger/bug549398.js diff --git a/js/src/trace-test/tests/jaeger/bug549521.js b/js/src/jit-test/tests/jaeger/bug549521.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug549521.js rename to js/src/jit-test/tests/jaeger/bug549521.js diff --git a/js/src/trace-test/tests/jaeger/bug549602.js b/js/src/jit-test/tests/jaeger/bug549602.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug549602.js rename to js/src/jit-test/tests/jaeger/bug549602.js diff --git a/js/src/jit-test/tests/jaeger/bug549603.js b/js/src/jit-test/tests/jaeger/bug549603.js new file mode 100644 index 000000000000..5d5dea67d74b --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug549603.js @@ -0,0 +1,3 @@ +// |jit-test| error: ReferenceError +x ? o : [] && x + diff --git a/js/src/trace-test/tests/jaeger/bug550490.js b/js/src/jit-test/tests/jaeger/bug550490.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug550490.js rename to js/src/jit-test/tests/jaeger/bug550490.js diff --git a/js/src/trace-test/tests/jaeger/bug550665.js b/js/src/jit-test/tests/jaeger/bug550665.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug550665.js rename to js/src/jit-test/tests/jaeger/bug550665.js diff --git a/js/src/trace-test/tests/jaeger/bug551603.js b/js/src/jit-test/tests/jaeger/bug551603.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug551603.js rename to js/src/jit-test/tests/jaeger/bug551603.js diff --git a/js/src/trace-test/tests/jaeger/bug552644.js b/js/src/jit-test/tests/jaeger/bug552644.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug552644.js rename to js/src/jit-test/tests/jaeger/bug552644.js diff --git a/js/src/trace-test/tests/jaeger/bug553781-2.js b/js/src/jit-test/tests/jaeger/bug553781-2.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug553781-2.js rename to js/src/jit-test/tests/jaeger/bug553781-2.js diff --git a/js/src/trace-test/tests/jaeger/bug553781.js b/js/src/jit-test/tests/jaeger/bug553781.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug553781.js rename to js/src/jit-test/tests/jaeger/bug553781.js diff --git a/js/src/trace-test/tests/jaeger/bug553784.js b/js/src/jit-test/tests/jaeger/bug553784.js similarity index 91% rename from js/src/trace-test/tests/jaeger/bug553784.js rename to js/src/jit-test/tests/jaeger/bug553784.js index 4898c8e128f9..6bd60f748fff 100644 --- a/js/src/trace-test/tests/jaeger/bug553784.js +++ b/js/src/jit-test/tests/jaeger/bug553784.js @@ -1,4 +1,4 @@ -// |trace-test| allow-oom +// |jit-test| allow-oom (function(){ (x)=> })() diff --git a/js/src/trace-test/tests/jaeger/bug554580-1.js b/js/src/jit-test/tests/jaeger/bug554580-1.js similarity index 69% rename from js/src/trace-test/tests/jaeger/bug554580-1.js rename to js/src/jit-test/tests/jaeger/bug554580-1.js index 1197af623ebd..0e8daade758c 100644 --- a/js/src/trace-test/tests/jaeger/bug554580-1.js +++ b/js/src/jit-test/tests/jaeger/bug554580-1.js @@ -1,4 +1,4 @@ -// |trace-test| error: TypeError +// |jit-test| error: TypeError for (var a = 0; a < 7; ++a) { if (a == 1) { Iterator() diff --git a/js/src/trace-test/tests/jaeger/bug554580-2.js b/js/src/jit-test/tests/jaeger/bug554580-2.js similarity index 77% rename from js/src/trace-test/tests/jaeger/bug554580-2.js rename to js/src/jit-test/tests/jaeger/bug554580-2.js index 6fc4cdadf806..d297f3a46306 100644 --- a/js/src/trace-test/tests/jaeger/bug554580-2.js +++ b/js/src/jit-test/tests/jaeger/bug554580-2.js @@ -1,4 +1,4 @@ -// |trace-test| error: RangeError +// |jit-test| error: RangeError (function() { for each(let a in [function() {}, Infinity]) { new Array(a) diff --git a/js/src/trace-test/tests/jaeger/bug554580-3.js b/js/src/jit-test/tests/jaeger/bug554580-3.js similarity index 81% rename from js/src/trace-test/tests/jaeger/bug554580-3.js rename to js/src/jit-test/tests/jaeger/bug554580-3.js index 78be30723b2c..cad0318e55fd 100644 --- a/js/src/trace-test/tests/jaeger/bug554580-3.js +++ b/js/src/jit-test/tests/jaeger/bug554580-3.js @@ -1,4 +1,4 @@ -// |trace-test| error: SyntaxError +// |jit-test| error: SyntaxError Function("\n\ for (a = 0; a < 3; a++) {\n\ if (a == 0) {} else {\n\ diff --git a/js/src/trace-test/tests/jaeger/bug554580-4.js b/js/src/jit-test/tests/jaeger/bug554580-4.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug554580-4.js rename to js/src/jit-test/tests/jaeger/bug554580-4.js diff --git a/js/src/trace-test/tests/jaeger/bug554580-5.js b/js/src/jit-test/tests/jaeger/bug554580-5.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug554580-5.js rename to js/src/jit-test/tests/jaeger/bug554580-5.js diff --git a/js/src/trace-test/tests/jaeger/bug554651.js b/js/src/jit-test/tests/jaeger/bug554651.js similarity index 88% rename from js/src/trace-test/tests/jaeger/bug554651.js rename to js/src/jit-test/tests/jaeger/bug554651.js index a02bebddb4d7..42eda813511e 100644 --- a/js/src/trace-test/tests/jaeger/bug554651.js +++ b/js/src/jit-test/tests/jaeger/bug554651.js @@ -1,4 +1,4 @@ -// |trace-test| error: InternalError +// |jit-test| error: InternalError (function() { try { (Function("__defineGetter__(\"x\",(Function(\"for(z=0;z<6;z++)(x)\")))"))() diff --git a/js/src/trace-test/tests/jaeger/bug554675-1.js b/js/src/jit-test/tests/jaeger/bug554675-1.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug554675-1.js rename to js/src/jit-test/tests/jaeger/bug554675-1.js diff --git a/js/src/trace-test/tests/jaeger/bug554675-2.js b/js/src/jit-test/tests/jaeger/bug554675-2.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug554675-2.js rename to js/src/jit-test/tests/jaeger/bug554675-2.js diff --git a/js/src/trace-test/tests/jaeger/bug554675-3.js b/js/src/jit-test/tests/jaeger/bug554675-3.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug554675-3.js rename to js/src/jit-test/tests/jaeger/bug554675-3.js diff --git a/js/src/trace-test/tests/jaeger/bug555152.js b/js/src/jit-test/tests/jaeger/bug555152.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug555152.js rename to js/src/jit-test/tests/jaeger/bug555152.js diff --git a/js/src/trace-test/tests/jaeger/bug555155.js b/js/src/jit-test/tests/jaeger/bug555155.js similarity index 84% rename from js/src/trace-test/tests/jaeger/bug555155.js rename to js/src/jit-test/tests/jaeger/bug555155.js index 3cae0e568a0d..db7b57aa1bc6 100644 --- a/js/src/trace-test/tests/jaeger/bug555155.js +++ b/js/src/jit-test/tests/jaeger/bug555155.js @@ -1,4 +1,4 @@ -// |trace-test| error: undefined +// |jit-test| error: undefined (function() { throw (function f(a, b) { if (a.h == b) { diff --git a/js/src/trace-test/tests/jaeger/bug555206.js b/js/src/jit-test/tests/jaeger/bug555206.js similarity index 60% rename from js/src/trace-test/tests/jaeger/bug555206.js rename to js/src/jit-test/tests/jaeger/bug555206.js index 0024ba291dad..859c7cc995b6 100644 --- a/js/src/trace-test/tests/jaeger/bug555206.js +++ b/js/src/jit-test/tests/jaeger/bug555206.js @@ -1,4 +1,4 @@ -// |trace-test| error: TypeError +// |jit-test| error: TypeError __defineGetter__("x",/a/) " ".replace(/\s/,"") x.b diff --git a/js/src/trace-test/tests/jaeger/bug555543.js b/js/src/jit-test/tests/jaeger/bug555543.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug555543.js rename to js/src/jit-test/tests/jaeger/bug555543.js diff --git a/js/src/trace-test/tests/jaeger/bug555922.js b/js/src/jit-test/tests/jaeger/bug555922.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug555922.js rename to js/src/jit-test/tests/jaeger/bug555922.js diff --git a/js/src/trace-test/tests/jaeger/bug556525.js b/js/src/jit-test/tests/jaeger/bug556525.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug556525.js rename to js/src/jit-test/tests/jaeger/bug556525.js diff --git a/js/src/trace-test/tests/jaeger/bug557063.js b/js/src/jit-test/tests/jaeger/bug557063.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug557063.js rename to js/src/jit-test/tests/jaeger/bug557063.js diff --git a/js/src/trace-test/tests/jaeger/bug557068.js b/js/src/jit-test/tests/jaeger/bug557068.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug557068.js rename to js/src/jit-test/tests/jaeger/bug557068.js diff --git a/js/src/trace-test/tests/jaeger/bug557070.js b/js/src/jit-test/tests/jaeger/bug557070.js similarity index 69% rename from js/src/trace-test/tests/jaeger/bug557070.js rename to js/src/jit-test/tests/jaeger/bug557070.js index 84b6dd08a3ad..a3e08cc910c1 100644 --- a/js/src/trace-test/tests/jaeger/bug557070.js +++ b/js/src/jit-test/tests/jaeger/bug557070.js @@ -1,4 +1,4 @@ -// |trace-test| error: InternalError +// |jit-test| error: InternalError for (e in (function x() { [eval()].some(x) } ())); diff --git a/js/src/trace-test/tests/jaeger/bug557075.js b/js/src/jit-test/tests/jaeger/bug557075.js similarity index 73% rename from js/src/trace-test/tests/jaeger/bug557075.js rename to js/src/jit-test/tests/jaeger/bug557075.js index 10178ebbb6b8..264924a1574e 100644 --- a/js/src/trace-test/tests/jaeger/bug557075.js +++ b/js/src/jit-test/tests/jaeger/bug557075.js @@ -1,4 +1,4 @@ -// |trace-test| error: TypeError +// |jit-test| error: TypeError for (l in [Math.h.h.h.h.h.I.h.h.h.h.h.h.h.I.h.I]) { t.x diff --git a/js/src/trace-test/tests/jaeger/bug560221.js b/js/src/jit-test/tests/jaeger/bug560221.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug560221.js rename to js/src/jit-test/tests/jaeger/bug560221.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/eif-call-newvar.js b/js/src/jit-test/tests/jaeger/bug563000/eif-call-newvar.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/eif-call-newvar.js rename to js/src/jit-test/tests/jaeger/bug563000/eif-call-newvar.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/eif-call-typechange.js b/js/src/jit-test/tests/jaeger/bug563000/eif-call-typechange.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/eif-call-typechange.js rename to js/src/jit-test/tests/jaeger/bug563000/eif-call-typechange.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/eif-call.js b/js/src/jit-test/tests/jaeger/bug563000/eif-call.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/eif-call.js rename to js/src/jit-test/tests/jaeger/bug563000/eif-call.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/eif-getter-newvar.js b/js/src/jit-test/tests/jaeger/bug563000/eif-getter-newvar.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/eif-getter-newvar.js rename to js/src/jit-test/tests/jaeger/bug563000/eif-getter-newvar.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/eif-getter-typechange.js b/js/src/jit-test/tests/jaeger/bug563000/eif-getter-typechange.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/eif-getter-typechange.js rename to js/src/jit-test/tests/jaeger/bug563000/eif-getter-typechange.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/eif-getter.js b/js/src/jit-test/tests/jaeger/bug563000/eif-getter.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/eif-getter.js rename to js/src/jit-test/tests/jaeger/bug563000/eif-getter.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/eif-trap-newvar.js b/js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/eif-trap-newvar.js rename to js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/eif-trap-typechange.js b/js/src/jit-test/tests/jaeger/bug563000/eif-trap-typechange.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/eif-trap-typechange.js rename to js/src/jit-test/tests/jaeger/bug563000/eif-trap-typechange.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/eif-trap.js b/js/src/jit-test/tests/jaeger/bug563000/eif-trap.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/eif-trap.js rename to js/src/jit-test/tests/jaeger/bug563000/eif-trap.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/simple-trap-1.js b/js/src/jit-test/tests/jaeger/bug563000/simple-trap-1.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/simple-trap-1.js rename to js/src/jit-test/tests/jaeger/bug563000/simple-trap-1.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/simple-trap-2.js b/js/src/jit-test/tests/jaeger/bug563000/simple-trap-2.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/simple-trap-2.js rename to js/src/jit-test/tests/jaeger/bug563000/simple-trap-2.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/simple-untrap.js b/js/src/jit-test/tests/jaeger/bug563000/simple-untrap.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/simple-untrap.js rename to js/src/jit-test/tests/jaeger/bug563000/simple-untrap.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/test-debugger-1.js b/js/src/jit-test/tests/jaeger/bug563000/test-debugger-1.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/test-debugger-1.js rename to js/src/jit-test/tests/jaeger/bug563000/test-debugger-1.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/test-debugger-2.js b/js/src/jit-test/tests/jaeger/bug563000/test-debugger-2.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/test-debugger-2.js rename to js/src/jit-test/tests/jaeger/bug563000/test-debugger-2.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/test-throwhook-1.js b/js/src/jit-test/tests/jaeger/bug563000/test-throwhook-1.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/test-throwhook-1.js rename to js/src/jit-test/tests/jaeger/bug563000/test-throwhook-1.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/test-throwhook-2.js b/js/src/jit-test/tests/jaeger/bug563000/test-throwhook-2.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/test-throwhook-2.js rename to js/src/jit-test/tests/jaeger/bug563000/test-throwhook-2.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/trap-force-return-1.js b/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-1.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/trap-force-return-1.js rename to js/src/jit-test/tests/jaeger/bug563000/trap-force-return-1.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/trap-force-return-2.js b/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-2.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/trap-force-return-2.js rename to js/src/jit-test/tests/jaeger/bug563000/trap-force-return-2.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/trap-own-callsite.js b/js/src/jit-test/tests/jaeger/bug563000/trap-own-callsite.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/trap-own-callsite.js rename to js/src/jit-test/tests/jaeger/bug563000/trap-own-callsite.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/trap-parent-from-trap.js b/js/src/jit-test/tests/jaeger/bug563000/trap-parent-from-trap.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/trap-parent-from-trap.js rename to js/src/jit-test/tests/jaeger/bug563000/trap-parent-from-trap.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/trap-parent.js b/js/src/jit-test/tests/jaeger/bug563000/trap-parent.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/trap-parent.js rename to js/src/jit-test/tests/jaeger/bug563000/trap-parent.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/trap-self-as-parent.js b/js/src/jit-test/tests/jaeger/bug563000/trap-self-as-parent.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/trap-self-as-parent.js rename to js/src/jit-test/tests/jaeger/bug563000/trap-self-as-parent.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/trap-self-from-trap.js b/js/src/jit-test/tests/jaeger/bug563000/trap-self-from-trap.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/trap-self-from-trap.js rename to js/src/jit-test/tests/jaeger/bug563000/trap-self-from-trap.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/trap-self.js b/js/src/jit-test/tests/jaeger/bug563000/trap-self.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/trap-self.js rename to js/src/jit-test/tests/jaeger/bug563000/trap-self.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/untrap-own-trapsite.js b/js/src/jit-test/tests/jaeger/bug563000/untrap-own-trapsite.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/untrap-own-trapsite.js rename to js/src/jit-test/tests/jaeger/bug563000/untrap-own-trapsite.js diff --git a/js/src/trace-test/tests/jaeger/bug563000/untrap-self.js b/js/src/jit-test/tests/jaeger/bug563000/untrap-self.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug563000/untrap-self.js rename to js/src/jit-test/tests/jaeger/bug563000/untrap-self.js diff --git a/js/src/trace-test/tests/jaeger/bug565198.js b/js/src/jit-test/tests/jaeger/bug565198.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug565198.js rename to js/src/jit-test/tests/jaeger/bug565198.js diff --git a/js/src/trace-test/tests/jaeger/bug565202.js b/js/src/jit-test/tests/jaeger/bug565202.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug565202.js rename to js/src/jit-test/tests/jaeger/bug565202.js diff --git a/js/src/trace-test/tests/jaeger/bug566022.js b/js/src/jit-test/tests/jaeger/bug566022.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug566022.js rename to js/src/jit-test/tests/jaeger/bug566022.js diff --git a/js/src/trace-test/tests/jaeger/bug573433.js b/js/src/jit-test/tests/jaeger/bug573433.js similarity index 70% rename from js/src/trace-test/tests/jaeger/bug573433.js rename to js/src/jit-test/tests/jaeger/bug573433.js index bf50585890cd..aa39022bb74a 100644 --- a/js/src/trace-test/tests/jaeger/bug573433.js +++ b/js/src/jit-test/tests/jaeger/bug573433.js @@ -1,4 +1,4 @@ -// |trace-test| error: TypeError +// |jit-test| error: TypeError function f() { eval("(function() \n{\nfor(x in[])\n{}\n})"); ("")() diff --git a/js/src/trace-test/tests/jaeger/bug576398.js b/js/src/jit-test/tests/jaeger/bug576398.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug576398.js rename to js/src/jit-test/tests/jaeger/bug576398.js diff --git a/js/src/trace-test/tests/jaeger/bug577580.js b/js/src/jit-test/tests/jaeger/bug577580.js similarity index 60% rename from js/src/trace-test/tests/jaeger/bug577580.js rename to js/src/jit-test/tests/jaeger/bug577580.js index 25fc42c57c24..6812a7da4841 100644 --- a/js/src/trace-test/tests/jaeger/bug577580.js +++ b/js/src/jit-test/tests/jaeger/bug577580.js @@ -1,4 +1,4 @@ -// |trace-test| error: ReferenceError +// |jit-test| error: ReferenceError (function() { for (; i;) { eval(/@/, "") diff --git a/js/src/trace-test/tests/jaeger/bug577646.js b/js/src/jit-test/tests/jaeger/bug577646.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug577646.js rename to js/src/jit-test/tests/jaeger/bug577646.js diff --git a/js/src/trace-test/tests/jaeger/bug577705.js b/js/src/jit-test/tests/jaeger/bug577705.js similarity index 96% rename from js/src/trace-test/tests/jaeger/bug577705.js rename to js/src/jit-test/tests/jaeger/bug577705.js index f3be0ed58f4f..e9e338130e5d 100644 --- a/js/src/trace-test/tests/jaeger/bug577705.js +++ b/js/src/jit-test/tests/jaeger/bug577705.js @@ -1,4 +1,4 @@ -// |trace-test| error: ReferenceError +// |jit-test| error: ReferenceError function f1() { N = 62; mt = Array diff --git a/js/src/trace-test/tests/jaeger/bug577996.js b/js/src/jit-test/tests/jaeger/bug577996.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug577996.js rename to js/src/jit-test/tests/jaeger/bug577996.js diff --git a/js/src/trace-test/tests/jaeger/bug580703.js b/js/src/jit-test/tests/jaeger/bug580703.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug580703.js rename to js/src/jit-test/tests/jaeger/bug580703.js diff --git a/js/src/trace-test/tests/jaeger/bug580712.js b/js/src/jit-test/tests/jaeger/bug580712.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug580712.js rename to js/src/jit-test/tests/jaeger/bug580712.js diff --git a/js/src/jit-test/tests/jaeger/bug580883.js b/js/src/jit-test/tests/jaeger/bug580883.js new file mode 100644 index 000000000000..90d8cb378ccc --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug580883.js @@ -0,0 +1,6 @@ +// |jit-test| error: invalid sharp variable use #1# +[] = #1# +with(7) { + var c +} + diff --git a/js/src/trace-test/tests/jaeger/bug580884-2.js b/js/src/jit-test/tests/jaeger/bug580884-2.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug580884-2.js rename to js/src/jit-test/tests/jaeger/bug580884-2.js diff --git a/js/src/trace-test/tests/jaeger/bug580884-3.js b/js/src/jit-test/tests/jaeger/bug580884-3.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug580884-3.js rename to js/src/jit-test/tests/jaeger/bug580884-3.js diff --git a/js/src/trace-test/tests/jaeger/bug580884.js b/js/src/jit-test/tests/jaeger/bug580884.js similarity index 64% rename from js/src/trace-test/tests/jaeger/bug580884.js rename to js/src/jit-test/tests/jaeger/bug580884.js index d05ccf680185..b7a26f705668 100644 --- a/js/src/trace-test/tests/jaeger/bug580884.js +++ b/js/src/jit-test/tests/jaeger/bug580884.js @@ -1,4 +1,4 @@ -// |trace-test| error: ReferenceError +// |jit-test| error: ReferenceError for (let a in [0]) a = e for (let a in [0]) diff --git a/js/src/trace-test/tests/jaeger/bug580931-2.js b/js/src/jit-test/tests/jaeger/bug580931-2.js similarity index 56% rename from js/src/trace-test/tests/jaeger/bug580931-2.js rename to js/src/jit-test/tests/jaeger/bug580931-2.js index 9377c8ce96ba..9f18f57e02d1 100644 --- a/js/src/trace-test/tests/jaeger/bug580931-2.js +++ b/js/src/jit-test/tests/jaeger/bug580931-2.js @@ -1,4 +1,4 @@ -// |trace-test| error: TypeError +// |jit-test| error: TypeError x = 0 'a'.replace(/a/, x.toLocaleString) diff --git a/js/src/trace-test/tests/jaeger/bug581871.js b/js/src/jit-test/tests/jaeger/bug581871.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug581871.js rename to js/src/jit-test/tests/jaeger/bug581871.js diff --git a/js/src/trace-test/tests/jaeger/bug581936.js b/js/src/jit-test/tests/jaeger/bug581936.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug581936.js rename to js/src/jit-test/tests/jaeger/bug581936.js diff --git a/js/src/trace-test/tests/jaeger/bug582185.js b/js/src/jit-test/tests/jaeger/bug582185.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug582185.js rename to js/src/jit-test/tests/jaeger/bug582185.js diff --git a/js/src/trace-test/tests/jaeger/bug582286.js b/js/src/jit-test/tests/jaeger/bug582286.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug582286.js rename to js/src/jit-test/tests/jaeger/bug582286.js diff --git a/js/src/trace-test/tests/jaeger/bug582392.js b/js/src/jit-test/tests/jaeger/bug582392.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug582392.js rename to js/src/jit-test/tests/jaeger/bug582392.js diff --git a/js/src/trace-test/tests/jaeger/bug582880.js b/js/src/jit-test/tests/jaeger/bug582880.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug582880.js rename to js/src/jit-test/tests/jaeger/bug582880.js diff --git a/js/src/trace-test/tests/jaeger/bug582882.js b/js/src/jit-test/tests/jaeger/bug582882.js similarity index 79% rename from js/src/trace-test/tests/jaeger/bug582882.js rename to js/src/jit-test/tests/jaeger/bug582882.js index 101d0a6a3705..2fafca5f43cd 100644 --- a/js/src/trace-test/tests/jaeger/bug582882.js +++ b/js/src/jit-test/tests/jaeger/bug582882.js @@ -1,4 +1,4 @@ -// |trace-test| error: ReferenceError +// |jit-test| error: ReferenceError function f1(code) { f = Function(code) f2() diff --git a/js/src/trace-test/tests/jaeger/bug582884.js b/js/src/jit-test/tests/jaeger/bug582884.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug582884.js rename to js/src/jit-test/tests/jaeger/bug582884.js diff --git a/js/src/trace-test/tests/jaeger/bug582894.js b/js/src/jit-test/tests/jaeger/bug582894.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug582894.js rename to js/src/jit-test/tests/jaeger/bug582894.js diff --git a/js/src/trace-test/tests/jaeger/bug582897.js b/js/src/jit-test/tests/jaeger/bug582897.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug582897.js rename to js/src/jit-test/tests/jaeger/bug582897.js diff --git a/js/src/trace-test/tests/jaeger/bug582898.js b/js/src/jit-test/tests/jaeger/bug582898.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug582898.js rename to js/src/jit-test/tests/jaeger/bug582898.js diff --git a/js/src/jit-test/tests/jaeger/bug582900.js b/js/src/jit-test/tests/jaeger/bug582900.js new file mode 100644 index 000000000000..1da55397af42 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug582900.js @@ -0,0 +1,3 @@ +// |jit-test| error: ReferenceError + +[].x >>= a | 0 diff --git a/js/src/trace-test/tests/jaeger/bug583158.js b/js/src/jit-test/tests/jaeger/bug583158.js similarity index 70% rename from js/src/trace-test/tests/jaeger/bug583158.js rename to js/src/jit-test/tests/jaeger/bug583158.js index ec533bfb3782..6d8c124487d5 100644 --- a/js/src/trace-test/tests/jaeger/bug583158.js +++ b/js/src/jit-test/tests/jaeger/bug583158.js @@ -1,4 +1,4 @@ -// |trace-test| error: ReferenceError +// |jit-test| error: ReferenceError function g() { var rv = (function() { this << 1 diff --git a/js/src/trace-test/tests/jaeger/bug583160.js b/js/src/jit-test/tests/jaeger/bug583160.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug583160.js rename to js/src/jit-test/tests/jaeger/bug583160.js diff --git a/js/src/trace-test/tests/jaeger/bug583672.js b/js/src/jit-test/tests/jaeger/bug583672.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug583672.js rename to js/src/jit-test/tests/jaeger/bug583672.js diff --git a/js/src/trace-test/tests/jaeger/bug583684.js b/js/src/jit-test/tests/jaeger/bug583684.js similarity index 72% rename from js/src/trace-test/tests/jaeger/bug583684.js rename to js/src/jit-test/tests/jaeger/bug583684.js index a9b0f69f74a0..c0343621182b 100644 --- a/js/src/trace-test/tests/jaeger/bug583684.js +++ b/js/src/jit-test/tests/jaeger/bug583684.js @@ -1,4 +1,4 @@ -// |trace-test| error: TypeError +// |jit-test| error: TypeError (function () { var b = e for (var [e] = b in w) c diff --git a/js/src/trace-test/tests/jaeger/bug583688.js b/js/src/jit-test/tests/jaeger/bug583688.js similarity index 77% rename from js/src/trace-test/tests/jaeger/bug583688.js rename to js/src/jit-test/tests/jaeger/bug583688.js index 07a3d7d52163..3996c1722aeb 100644 --- a/js/src/trace-test/tests/jaeger/bug583688.js +++ b/js/src/jit-test/tests/jaeger/bug583688.js @@ -1,4 +1,4 @@ -// |trace-test| error: ReferenceError +// |jit-test| error: ReferenceError __defineSetter__("x", function () {}) try { __defineGetter__("d", (Function("x"))) diff --git a/js/src/trace-test/tests/jaeger/bug583689.js b/js/src/jit-test/tests/jaeger/bug583689.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug583689.js rename to js/src/jit-test/tests/jaeger/bug583689.js diff --git a/js/src/trace-test/tests/jaeger/bug584644-2.js b/js/src/jit-test/tests/jaeger/bug584644-2.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug584644-2.js rename to js/src/jit-test/tests/jaeger/bug584644-2.js diff --git a/js/src/trace-test/tests/jaeger/bug584646.js b/js/src/jit-test/tests/jaeger/bug584646.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug584646.js rename to js/src/jit-test/tests/jaeger/bug584646.js diff --git a/js/src/trace-test/tests/jaeger/bug584647.js b/js/src/jit-test/tests/jaeger/bug584647.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug584647.js rename to js/src/jit-test/tests/jaeger/bug584647.js diff --git a/js/src/trace-test/tests/jaeger/bug585310.js b/js/src/jit-test/tests/jaeger/bug585310.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug585310.js rename to js/src/jit-test/tests/jaeger/bug585310.js diff --git a/js/src/trace-test/tests/jaeger/bug585341.js b/js/src/jit-test/tests/jaeger/bug585341.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug585341.js rename to js/src/jit-test/tests/jaeger/bug585341.js diff --git a/js/src/trace-test/tests/jaeger/bug585391.js b/js/src/jit-test/tests/jaeger/bug585391.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug585391.js rename to js/src/jit-test/tests/jaeger/bug585391.js diff --git a/js/src/trace-test/tests/jaeger/bug585408-2.js b/js/src/jit-test/tests/jaeger/bug585408-2.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug585408-2.js rename to js/src/jit-test/tests/jaeger/bug585408-2.js diff --git a/js/src/trace-test/tests/jaeger/bug585408-3.js b/js/src/jit-test/tests/jaeger/bug585408-3.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug585408-3.js rename to js/src/jit-test/tests/jaeger/bug585408-3.js diff --git a/js/src/trace-test/tests/jaeger/bug585408.js b/js/src/jit-test/tests/jaeger/bug585408.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug585408.js rename to js/src/jit-test/tests/jaeger/bug585408.js diff --git a/js/src/trace-test/tests/jaeger/bug585540.js b/js/src/jit-test/tests/jaeger/bug585540.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug585540.js rename to js/src/jit-test/tests/jaeger/bug585540.js diff --git a/js/src/trace-test/tests/jaeger/bug587431.js b/js/src/jit-test/tests/jaeger/bug587431.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug587431.js rename to js/src/jit-test/tests/jaeger/bug587431.js diff --git a/js/src/trace-test/tests/jaeger/bug588338.js b/js/src/jit-test/tests/jaeger/bug588338.js similarity index 83% rename from js/src/trace-test/tests/jaeger/bug588338.js rename to js/src/jit-test/tests/jaeger/bug588338.js index dee86ae8cd4d..65c30952077b 100644 --- a/js/src/trace-test/tests/jaeger/bug588338.js +++ b/js/src/jit-test/tests/jaeger/bug588338.js @@ -1,4 +1,4 @@ -// |trace-test| error: is not a function +// |jit-test| error: is not a function function f() { (e) } (x = Proxy.createFunction((function(x) { return { diff --git a/js/src/trace-test/tests/jaeger/bug588362-1.js b/js/src/jit-test/tests/jaeger/bug588362-1.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug588362-1.js rename to js/src/jit-test/tests/jaeger/bug588362-1.js diff --git a/js/src/trace-test/tests/jaeger/bug588362-2.js b/js/src/jit-test/tests/jaeger/bug588362-2.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug588362-2.js rename to js/src/jit-test/tests/jaeger/bug588362-2.js diff --git a/js/src/trace-test/tests/jaeger/bug588362-3.js b/js/src/jit-test/tests/jaeger/bug588362-3.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug588362-3.js rename to js/src/jit-test/tests/jaeger/bug588362-3.js diff --git a/js/src/trace-test/tests/jaeger/bug588363-1.js b/js/src/jit-test/tests/jaeger/bug588363-1.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug588363-1.js rename to js/src/jit-test/tests/jaeger/bug588363-1.js diff --git a/js/src/trace-test/tests/jaeger/bug588363-2.js b/js/src/jit-test/tests/jaeger/bug588363-2.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug588363-2.js rename to js/src/jit-test/tests/jaeger/bug588363-2.js diff --git a/js/src/trace-test/tests/jaeger/bug589108.js b/js/src/jit-test/tests/jaeger/bug589108.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug589108.js rename to js/src/jit-test/tests/jaeger/bug589108.js diff --git a/js/src/trace-test/tests/jaeger/bug589115.js b/js/src/jit-test/tests/jaeger/bug589115.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug589115.js rename to js/src/jit-test/tests/jaeger/bug589115.js diff --git a/js/src/trace-test/tests/jaeger/bug589461.js b/js/src/jit-test/tests/jaeger/bug589461.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug589461.js rename to js/src/jit-test/tests/jaeger/bug589461.js diff --git a/js/src/trace-test/tests/jaeger/bug590083.js b/js/src/jit-test/tests/jaeger/bug590083.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug590083.js rename to js/src/jit-test/tests/jaeger/bug590083.js diff --git a/js/src/trace-test/tests/jaeger/bug591602.js b/js/src/jit-test/tests/jaeger/bug591602.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug591602.js rename to js/src/jit-test/tests/jaeger/bug591602.js diff --git a/js/src/trace-test/tests/jaeger/bug591606.js b/js/src/jit-test/tests/jaeger/bug591606.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug591606.js rename to js/src/jit-test/tests/jaeger/bug591606.js diff --git a/js/src/trace-test/tests/jaeger/bug592973-1.js b/js/src/jit-test/tests/jaeger/bug592973-1.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug592973-1.js rename to js/src/jit-test/tests/jaeger/bug592973-1.js diff --git a/js/src/trace-test/tests/jaeger/bug592973-2.js b/js/src/jit-test/tests/jaeger/bug592973-2.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug592973-2.js rename to js/src/jit-test/tests/jaeger/bug592973-2.js diff --git a/js/src/trace-test/tests/jaeger/bug592973-3.js b/js/src/jit-test/tests/jaeger/bug592973-3.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug592973-3.js rename to js/src/jit-test/tests/jaeger/bug592973-3.js diff --git a/js/src/trace-test/tests/jaeger/bug593554.js b/js/src/jit-test/tests/jaeger/bug593554.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug593554.js rename to js/src/jit-test/tests/jaeger/bug593554.js diff --git a/js/src/trace-test/tests/jaeger/bug595917.js b/js/src/jit-test/tests/jaeger/bug595917.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug595917.js rename to js/src/jit-test/tests/jaeger/bug595917.js diff --git a/js/src/trace-test/tests/jaeger/bug595921.js b/js/src/jit-test/tests/jaeger/bug595921.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug595921.js rename to js/src/jit-test/tests/jaeger/bug595921.js diff --git a/js/src/trace-test/tests/jaeger/bug597378.js b/js/src/jit-test/tests/jaeger/bug597378.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug597378.js rename to js/src/jit-test/tests/jaeger/bug597378.js diff --git a/js/src/trace-test/tests/jaeger/bug597871.js b/js/src/jit-test/tests/jaeger/bug597871.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug597871.js rename to js/src/jit-test/tests/jaeger/bug597871.js diff --git a/js/src/trace-test/tests/jaeger/bug598696.js b/js/src/jit-test/tests/jaeger/bug598696.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug598696.js rename to js/src/jit-test/tests/jaeger/bug598696.js diff --git a/js/src/trace-test/tests/jaeger/bug599488.js b/js/src/jit-test/tests/jaeger/bug599488.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug599488.js rename to js/src/jit-test/tests/jaeger/bug599488.js diff --git a/js/src/trace-test/tests/jaeger/bug600139.js b/js/src/jit-test/tests/jaeger/bug600139.js similarity index 84% rename from js/src/trace-test/tests/jaeger/bug600139.js rename to js/src/jit-test/tests/jaeger/bug600139.js index d8e261930670..032847986400 100644 --- a/js/src/trace-test/tests/jaeger/bug600139.js +++ b/js/src/jit-test/tests/jaeger/bug600139.js @@ -1,4 +1,4 @@ -// |trace-test| error: ReferenceError +// |jit-test| error: ReferenceError // vim: set ts=4 sw=4 tw=99 et: function f(a, b, c) { if (!a.__SSi) { diff --git a/js/src/trace-test/tests/jaeger/bug600419.js b/js/src/jit-test/tests/jaeger/bug600419.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug600419.js rename to js/src/jit-test/tests/jaeger/bug600419.js diff --git a/js/src/trace-test/tests/jaeger/bug600424.js b/js/src/jit-test/tests/jaeger/bug600424.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug600424.js rename to js/src/jit-test/tests/jaeger/bug600424.js diff --git a/js/src/trace-test/tests/jaeger/bug601982.js b/js/src/jit-test/tests/jaeger/bug601982.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug601982.js rename to js/src/jit-test/tests/jaeger/bug601982.js diff --git a/js/src/trace-test/tests/jaeger/bug604427.js b/js/src/jit-test/tests/jaeger/bug604427.js similarity index 100% rename from js/src/trace-test/tests/jaeger/bug604427.js rename to js/src/jit-test/tests/jaeger/bug604427.js diff --git a/js/src/jit-test/tests/jaeger/bug606829.js b/js/src/jit-test/tests/jaeger/bug606829.js new file mode 100644 index 000000000000..1839c93d25cf --- /dev/null +++ b/js/src/jit-test/tests/jaeger/bug606829.js @@ -0,0 +1,8 @@ +/* Don't assert. */ +function f(x) +{ + if ("hi" == (x & 3)) { + return 1; + } +} +f(12); diff --git a/js/src/trace-test/tests/jaeger/compare-wrong-1.js b/js/src/jit-test/tests/jaeger/compare-wrong-1.js similarity index 100% rename from js/src/trace-test/tests/jaeger/compare-wrong-1.js rename to js/src/jit-test/tests/jaeger/compare-wrong-1.js diff --git a/js/src/trace-test/tests/jaeger/crash-on-compare.js b/js/src/jit-test/tests/jaeger/crash-on-compare.js similarity index 100% rename from js/src/trace-test/tests/jaeger/crash-on-compare.js rename to js/src/jit-test/tests/jaeger/crash-on-compare.js diff --git a/js/src/trace-test/tests/jaeger/deepBailAfterRunTracer.js b/js/src/jit-test/tests/jaeger/deepBailAfterRunTracer.js similarity index 100% rename from js/src/trace-test/tests/jaeger/deepBailAfterRunTracer.js rename to js/src/jit-test/tests/jaeger/deepBailAfterRunTracer.js diff --git a/js/src/trace-test/tests/jaeger/fused-eq-ifeq.js b/js/src/jit-test/tests/jaeger/fused-eq-ifeq.js similarity index 100% rename from js/src/trace-test/tests/jaeger/fused-eq-ifeq.js rename to js/src/jit-test/tests/jaeger/fused-eq-ifeq.js diff --git a/js/src/trace-test/tests/jaeger/getelem-sanity-1.js b/js/src/jit-test/tests/jaeger/getelem-sanity-1.js similarity index 100% rename from js/src/trace-test/tests/jaeger/getelem-sanity-1.js rename to js/src/jit-test/tests/jaeger/getelem-sanity-1.js diff --git a/js/src/trace-test/tests/jaeger/getelem-sanity-2.js b/js/src/jit-test/tests/jaeger/getelem-sanity-2.js similarity index 100% rename from js/src/trace-test/tests/jaeger/getelem-sanity-2.js rename to js/src/jit-test/tests/jaeger/getelem-sanity-2.js diff --git a/js/src/trace-test/tests/jaeger/getelem-sanity-3.js b/js/src/jit-test/tests/jaeger/getelem-sanity-3.js similarity index 100% rename from js/src/trace-test/tests/jaeger/getelem-sanity-3.js rename to js/src/jit-test/tests/jaeger/getelem-sanity-3.js diff --git a/js/src/trace-test/tests/jaeger/getelem-sanity-4.js b/js/src/jit-test/tests/jaeger/getelem-sanity-4.js similarity index 100% rename from js/src/trace-test/tests/jaeger/getelem-sanity-4.js rename to js/src/jit-test/tests/jaeger/getelem-sanity-4.js diff --git a/js/src/trace-test/tests/jaeger/getelem-sanity-5.js b/js/src/jit-test/tests/jaeger/getelem-sanity-5.js similarity index 100% rename from js/src/trace-test/tests/jaeger/getelem-sanity-5.js rename to js/src/jit-test/tests/jaeger/getelem-sanity-5.js diff --git a/js/src/trace-test/tests/jaeger/getelem-sanity-6.js b/js/src/jit-test/tests/jaeger/getelem-sanity-6.js similarity index 100% rename from js/src/trace-test/tests/jaeger/getelem-sanity-6.js rename to js/src/jit-test/tests/jaeger/getelem-sanity-6.js diff --git a/js/src/trace-test/tests/jaeger/getelem-sanity-7.js b/js/src/jit-test/tests/jaeger/getelem-sanity-7.js similarity index 100% rename from js/src/trace-test/tests/jaeger/getelem-sanity-7.js rename to js/src/jit-test/tests/jaeger/getelem-sanity-7.js diff --git a/js/src/trace-test/tests/jaeger/getelem-sanity-int-1.js b/js/src/jit-test/tests/jaeger/getelem-sanity-int-1.js similarity index 100% rename from js/src/trace-test/tests/jaeger/getelem-sanity-int-1.js rename to js/src/jit-test/tests/jaeger/getelem-sanity-int-1.js diff --git a/js/src/trace-test/tests/jaeger/getelem-sanity-int-2.js b/js/src/jit-test/tests/jaeger/getelem-sanity-int-2.js similarity index 100% rename from js/src/trace-test/tests/jaeger/getelem-sanity-int-2.js rename to js/src/jit-test/tests/jaeger/getelem-sanity-int-2.js diff --git a/js/src/trace-test/tests/jaeger/getelem-sanity-int-3.js b/js/src/jit-test/tests/jaeger/getelem-sanity-int-3.js similarity index 100% rename from js/src/trace-test/tests/jaeger/getelem-sanity-int-3.js rename to js/src/jit-test/tests/jaeger/getelem-sanity-int-3.js diff --git a/js/src/trace-test/tests/jaeger/globalOptimize-1.js b/js/src/jit-test/tests/jaeger/globalOptimize-1.js similarity index 100% rename from js/src/trace-test/tests/jaeger/globalOptimize-1.js rename to js/src/jit-test/tests/jaeger/globalOptimize-1.js diff --git a/js/src/trace-test/tests/jaeger/instanceOfWithKnownTypes.js b/js/src/jit-test/tests/jaeger/instanceOfWithKnownTypes.js similarity index 80% rename from js/src/trace-test/tests/jaeger/instanceOfWithKnownTypes.js rename to js/src/jit-test/tests/jaeger/instanceOfWithKnownTypes.js index a75e29a6edee..0ca3dc8d9477 100644 --- a/js/src/trace-test/tests/jaeger/instanceOfWithKnownTypes.js +++ b/js/src/jit-test/tests/jaeger/instanceOfWithKnownTypes.js @@ -1,4 +1,4 @@ -// |trace-test| error: TypeError +// |jit-test| error: TypeError // Verify that the compiler doesn't assert. diff --git a/js/src/jit-test/tests/jaeger/modWithConstLhs.js b/js/src/jit-test/tests/jaeger/modWithConstLhs.js new file mode 100644 index 000000000000..67bf398b0032 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/modWithConstLhs.js @@ -0,0 +1,2 @@ +// |jit-test| error: ReferenceError; +7%s; diff --git a/js/src/trace-test/tests/jaeger/mulNegZero.js b/js/src/jit-test/tests/jaeger/mulNegZero.js similarity index 100% rename from js/src/trace-test/tests/jaeger/mulNegZero.js rename to js/src/jit-test/tests/jaeger/mulNegZero.js diff --git a/js/src/trace-test/tests/jaeger/negation.js b/js/src/jit-test/tests/jaeger/negation.js similarity index 100% rename from js/src/trace-test/tests/jaeger/negation.js rename to js/src/jit-test/tests/jaeger/negation.js diff --git a/js/src/trace-test/tests/jaeger/regalloc-1.js b/js/src/jit-test/tests/jaeger/regalloc-1.js similarity index 91% rename from js/src/trace-test/tests/jaeger/regalloc-1.js rename to js/src/jit-test/tests/jaeger/regalloc-1.js index 76f1056d37be..c4b854b40b21 100644 --- a/js/src/trace-test/tests/jaeger/regalloc-1.js +++ b/js/src/jit-test/tests/jaeger/regalloc-1.js @@ -1,4 +1,4 @@ -// |trace-test| error: TypeError +// |jit-test| error: TypeError x = 2; diff --git a/js/src/trace-test/tests/jaeger/rsh-sanity-1.js b/js/src/jit-test/tests/jaeger/rsh-sanity-1.js similarity index 100% rename from js/src/trace-test/tests/jaeger/rsh-sanity-1.js rename to js/src/jit-test/tests/jaeger/rsh-sanity-1.js diff --git a/js/src/trace-test/tests/jaeger/scriptedICs-1.js b/js/src/jit-test/tests/jaeger/scriptedICs-1.js similarity index 100% rename from js/src/trace-test/tests/jaeger/scriptedICs-1.js rename to js/src/jit-test/tests/jaeger/scriptedICs-1.js diff --git a/js/src/trace-test/tests/jaeger/strictModeSetUndefinedVar.js b/js/src/jit-test/tests/jaeger/strictModeSetUndefinedVar.js similarity index 58% rename from js/src/trace-test/tests/jaeger/strictModeSetUndefinedVar.js rename to js/src/jit-test/tests/jaeger/strictModeSetUndefinedVar.js index 05fdcf288ad3..99b846c17ba0 100644 --- a/js/src/trace-test/tests/jaeger/strictModeSetUndefinedVar.js +++ b/js/src/jit-test/tests/jaeger/strictModeSetUndefinedVar.js @@ -1,4 +1,4 @@ -// |trace-test| error: ReferenceError; +// |jit-test| error: ReferenceError; function f() { "use strict"; diff --git a/js/src/trace-test/tests/jaeger/subCommutativity.js b/js/src/jit-test/tests/jaeger/subCommutativity.js similarity index 100% rename from js/src/trace-test/tests/jaeger/subCommutativity.js rename to js/src/jit-test/tests/jaeger/subCommutativity.js diff --git a/js/src/trace-test/tests/jaeger/testAddStringObject.js b/js/src/jit-test/tests/jaeger/testAddStringObject.js similarity index 100% rename from js/src/trace-test/tests/jaeger/testAddStringObject.js rename to js/src/jit-test/tests/jaeger/testAddStringObject.js diff --git a/js/src/trace-test/tests/jaeger/testBug550743.js b/js/src/jit-test/tests/jaeger/testBug550743.js similarity index 100% rename from js/src/trace-test/tests/jaeger/testBug550743.js rename to js/src/jit-test/tests/jaeger/testBug550743.js diff --git a/js/src/jit-test/tests/jaeger/testForOps.js b/js/src/jit-test/tests/jaeger/testForOps.js new file mode 100644 index 000000000000..413c59b3f197 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/testForOps.js @@ -0,0 +1,63 @@ +// vim: set ts=4 sw=4 tw=99 et: + +function assertObjectsEqual(obj1, obj2) { + assertEq(obj1.a, obj2.a); + assertEq(obj1.b, obj2.b); + assertEq(obj1.c, obj2.c); + assertEq(obj1.d, obj2.d); + assertEq(obj2.a, 1); + assertEq(obj2.b, "bee"); + assertEq(obj2.c, "crab"); + assertEq(obj2.d, 12); +} + +function forName(obj) { + assertJit(); + eval(''); + var r = { }; + for (x in obj) + r[x] = obj[x]; + return r; +} + +function forProp(obj) { + assertJit(); + var r = { }; + var c = { }; + for (c.x in obj) + r[c.x] = obj[c.x]; + return r; +} + +function forElem(obj, x) { + assertJit(); + var r = { }; + var c = { }; + for (c[x] in obj) + r[c[x]] = obj[c[x]]; + return r; +} + +function forLocal(obj) { + assertJit(); + var r = { }; + for (var x in obj) + r[x] = obj[x]; + return r; +} + +function forArg(obj, x) { + assertJit(); + var r = { }; + for (x in obj) + r[x] = obj[x]; + return r; +} + +var obj = { a: 1, b: "bee", c: "crab", d: 12 }; +assertObjectsEqual(obj, forName(obj)); +assertObjectsEqual(obj, forProp(obj)); +assertObjectsEqual(obj, forElem(obj, "v")); +assertObjectsEqual(obj, forLocal(obj)); +assertObjectsEqual(obj, forArg(obj)); + diff --git a/js/src/jit-test/tests/jaeger/testShiftSameBacking.js b/js/src/jit-test/tests/jaeger/testShiftSameBacking.js new file mode 100644 index 000000000000..cb2ce0059b46 --- /dev/null +++ b/js/src/jit-test/tests/jaeger/testShiftSameBacking.js @@ -0,0 +1,12 @@ +// vim: set ts=4 sw=4 tw=99 et: + +function f(a) { + var x = a; + var y = x; + + assertEq((x << y), (a << a)); + assertEq((y << x), (a << a)); +} + +f(2); + diff --git a/js/src/trace-test/tests/jaeger/unsignedShiftZero.js b/js/src/jit-test/tests/jaeger/unsignedShiftZero.js similarity index 100% rename from js/src/trace-test/tests/jaeger/unsignedShiftZero.js rename to js/src/jit-test/tests/jaeger/unsignedShiftZero.js diff --git a/js/src/trace-test/tests/jaeger/xor-sanity.js b/js/src/jit-test/tests/jaeger/xor-sanity.js similarity index 100% rename from js/src/trace-test/tests/jaeger/xor-sanity.js rename to js/src/jit-test/tests/jaeger/xor-sanity.js diff --git a/js/src/trace-test/tests/pic/bug558099.js b/js/src/jit-test/tests/pic/bug558099.js similarity index 100% rename from js/src/trace-test/tests/pic/bug558099.js rename to js/src/jit-test/tests/pic/bug558099.js diff --git a/js/src/trace-test/tests/pic/bug558616.js b/js/src/jit-test/tests/pic/bug558616.js similarity index 100% rename from js/src/trace-test/tests/pic/bug558616.js rename to js/src/jit-test/tests/pic/bug558616.js diff --git a/js/src/trace-test/tests/pic/bug582899.js b/js/src/jit-test/tests/pic/bug582899.js similarity index 100% rename from js/src/trace-test/tests/pic/bug582899.js rename to js/src/jit-test/tests/pic/bug582899.js diff --git a/js/src/trace-test/tests/pic/bug584642.js b/js/src/jit-test/tests/pic/bug584642.js similarity index 54% rename from js/src/trace-test/tests/pic/bug584642.js rename to js/src/jit-test/tests/pic/bug584642.js index b69f8d499bba..ebf4d7855359 100644 --- a/js/src/trace-test/tests/pic/bug584642.js +++ b/js/src/jit-test/tests/pic/bug584642.js @@ -1,3 +1,3 @@ -// |trace-test| error: ReferenceError +// |jit-test| error: ReferenceError Function("x=[(x)=s]")(); /* Don't assert. */ diff --git a/js/src/trace-test/tests/pic/bug595706.js b/js/src/jit-test/tests/pic/bug595706.js similarity index 100% rename from js/src/trace-test/tests/pic/bug595706.js rename to js/src/jit-test/tests/pic/bug595706.js diff --git a/js/src/trace-test/tests/pic/call_self.js b/js/src/jit-test/tests/pic/call_self.js similarity index 100% rename from js/src/trace-test/tests/pic/call_self.js rename to js/src/jit-test/tests/pic/call_self.js diff --git a/js/src/trace-test/tests/pic/densearray.js b/js/src/jit-test/tests/pic/densearray.js similarity index 100% rename from js/src/trace-test/tests/pic/densearray.js rename to js/src/jit-test/tests/pic/densearray.js diff --git a/js/src/trace-test/tests/pic/fuzz1.js b/js/src/jit-test/tests/pic/fuzz1.js similarity index 100% rename from js/src/trace-test/tests/pic/fuzz1.js rename to js/src/jit-test/tests/pic/fuzz1.js diff --git a/js/src/trace-test/tests/pic/fuzz2.js b/js/src/jit-test/tests/pic/fuzz2.js similarity index 100% rename from js/src/trace-test/tests/pic/fuzz2.js rename to js/src/jit-test/tests/pic/fuzz2.js diff --git a/js/src/trace-test/tests/pic/fuzz3.js b/js/src/jit-test/tests/pic/fuzz3.js similarity index 100% rename from js/src/trace-test/tests/pic/fuzz3.js rename to js/src/jit-test/tests/pic/fuzz3.js diff --git a/js/src/trace-test/tests/pic/grandproto.js b/js/src/jit-test/tests/pic/grandproto.js similarity index 100% rename from js/src/trace-test/tests/pic/grandproto.js rename to js/src/jit-test/tests/pic/grandproto.js diff --git a/js/src/trace-test/tests/pic/length_array.js b/js/src/jit-test/tests/pic/length_array.js similarity index 100% rename from js/src/trace-test/tests/pic/length_array.js rename to js/src/jit-test/tests/pic/length_array.js diff --git a/js/src/trace-test/tests/pic/length_mix.js b/js/src/jit-test/tests/pic/length_mix.js similarity index 100% rename from js/src/trace-test/tests/pic/length_mix.js rename to js/src/jit-test/tests/pic/length_mix.js diff --git a/js/src/trace-test/tests/pic/length_object.js b/js/src/jit-test/tests/pic/length_object.js similarity index 100% rename from js/src/trace-test/tests/pic/length_object.js rename to js/src/jit-test/tests/pic/length_object.js diff --git a/js/src/trace-test/tests/pic/length_string.js b/js/src/jit-test/tests/pic/length_string.js similarity index 100% rename from js/src/trace-test/tests/pic/length_string.js rename to js/src/jit-test/tests/pic/length_string.js diff --git a/js/src/trace-test/tests/pic/proto1.js b/js/src/jit-test/tests/pic/proto1.js similarity index 100% rename from js/src/trace-test/tests/pic/proto1.js rename to js/src/jit-test/tests/pic/proto1.js diff --git a/js/src/trace-test/tests/pic/proto3.js b/js/src/jit-test/tests/pic/proto3.js similarity index 100% rename from js/src/trace-test/tests/pic/proto3.js rename to js/src/jit-test/tests/pic/proto3.js diff --git a/js/src/trace-test/tests/pic/proto_self.js b/js/src/jit-test/tests/pic/proto_self.js similarity index 100% rename from js/src/trace-test/tests/pic/proto_self.js rename to js/src/jit-test/tests/pic/proto_self.js diff --git a/js/src/trace-test/tests/pic/self1.js b/js/src/jit-test/tests/pic/self1.js similarity index 100% rename from js/src/trace-test/tests/pic/self1.js rename to js/src/jit-test/tests/pic/self1.js diff --git a/js/src/trace-test/tests/pic/self2.js b/js/src/jit-test/tests/pic/self2.js similarity index 100% rename from js/src/trace-test/tests/pic/self2.js rename to js/src/jit-test/tests/pic/self2.js diff --git a/js/src/trace-test/tests/pic/self3.js b/js/src/jit-test/tests/pic/self3.js similarity index 100% rename from js/src/trace-test/tests/pic/self3.js rename to js/src/jit-test/tests/pic/self3.js diff --git a/js/src/trace-test/tests/pic/self8.js b/js/src/jit-test/tests/pic/self8.js similarity index 100% rename from js/src/trace-test/tests/pic/self8.js rename to js/src/jit-test/tests/pic/self8.js diff --git a/js/src/trace-test/tests/pic/set-assign.js b/js/src/jit-test/tests/pic/set-assign.js similarity index 100% rename from js/src/trace-test/tests/pic/set-assign.js rename to js/src/jit-test/tests/pic/set-assign.js diff --git a/js/src/trace-test/tests/pic/set1.js b/js/src/jit-test/tests/pic/set1.js similarity index 100% rename from js/src/trace-test/tests/pic/set1.js rename to js/src/jit-test/tests/pic/set1.js diff --git a/js/src/trace-test/tests/pic/set2.js b/js/src/jit-test/tests/pic/set2.js similarity index 100% rename from js/src/trace-test/tests/pic/set2.js rename to js/src/jit-test/tests/pic/set2.js diff --git a/js/src/trace-test/tests/pic/shape_regen.js b/js/src/jit-test/tests/pic/shape_regen.js similarity index 100% rename from js/src/trace-test/tests/pic/shape_regen.js rename to js/src/jit-test/tests/pic/shape_regen.js diff --git a/js/src/trace-test/tests/pic/thisprop.js b/js/src/jit-test/tests/pic/thisprop.js similarity index 100% rename from js/src/trace-test/tests/pic/thisprop.js rename to js/src/jit-test/tests/pic/thisprop.js diff --git a/js/src/trace-test/tests/sunspider/check-3d-cube.js b/js/src/jit-test/tests/sunspider/check-3d-cube.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-3d-cube.js rename to js/src/jit-test/tests/sunspider/check-3d-cube.js diff --git a/js/src/trace-test/tests/sunspider/check-3d-morph.js b/js/src/jit-test/tests/sunspider/check-3d-morph.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-3d-morph.js rename to js/src/jit-test/tests/sunspider/check-3d-morph.js diff --git a/js/src/trace-test/tests/sunspider/check-3d-raytrace.js b/js/src/jit-test/tests/sunspider/check-3d-raytrace.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-3d-raytrace.js rename to js/src/jit-test/tests/sunspider/check-3d-raytrace.js diff --git a/js/src/trace-test/tests/sunspider/check-access-binary-trees.js b/js/src/jit-test/tests/sunspider/check-access-binary-trees.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-access-binary-trees.js rename to js/src/jit-test/tests/sunspider/check-access-binary-trees.js diff --git a/js/src/trace-test/tests/sunspider/check-access-fannkuch.js b/js/src/jit-test/tests/sunspider/check-access-fannkuch.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-access-fannkuch.js rename to js/src/jit-test/tests/sunspider/check-access-fannkuch.js diff --git a/js/src/trace-test/tests/sunspider/check-access-nbody.js b/js/src/jit-test/tests/sunspider/check-access-nbody.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-access-nbody.js rename to js/src/jit-test/tests/sunspider/check-access-nbody.js diff --git a/js/src/trace-test/tests/sunspider/check-access-nsieve.js b/js/src/jit-test/tests/sunspider/check-access-nsieve.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-access-nsieve.js rename to js/src/jit-test/tests/sunspider/check-access-nsieve.js diff --git a/js/src/trace-test/tests/sunspider/check-bitops-3bit-bits-in-byte.js b/js/src/jit-test/tests/sunspider/check-bitops-3bit-bits-in-byte.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-bitops-3bit-bits-in-byte.js rename to js/src/jit-test/tests/sunspider/check-bitops-3bit-bits-in-byte.js diff --git a/js/src/trace-test/tests/sunspider/check-bitops-bits-in-byte.js b/js/src/jit-test/tests/sunspider/check-bitops-bits-in-byte.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-bitops-bits-in-byte.js rename to js/src/jit-test/tests/sunspider/check-bitops-bits-in-byte.js diff --git a/js/src/trace-test/tests/sunspider/check-bitops-bitwise-and.js b/js/src/jit-test/tests/sunspider/check-bitops-bitwise-and.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-bitops-bitwise-and.js rename to js/src/jit-test/tests/sunspider/check-bitops-bitwise-and.js diff --git a/js/src/trace-test/tests/sunspider/check-bitops-nsieve-bits.js b/js/src/jit-test/tests/sunspider/check-bitops-nsieve-bits.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-bitops-nsieve-bits.js rename to js/src/jit-test/tests/sunspider/check-bitops-nsieve-bits.js diff --git a/js/src/trace-test/tests/sunspider/check-controlflow-recursive.js b/js/src/jit-test/tests/sunspider/check-controlflow-recursive.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-controlflow-recursive.js rename to js/src/jit-test/tests/sunspider/check-controlflow-recursive.js diff --git a/js/src/trace-test/tests/sunspider/check-crypto-aes.js b/js/src/jit-test/tests/sunspider/check-crypto-aes.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-crypto-aes.js rename to js/src/jit-test/tests/sunspider/check-crypto-aes.js diff --git a/js/src/trace-test/tests/sunspider/check-crypto-md5.js b/js/src/jit-test/tests/sunspider/check-crypto-md5.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-crypto-md5.js rename to js/src/jit-test/tests/sunspider/check-crypto-md5.js diff --git a/js/src/trace-test/tests/sunspider/check-crypto-sha1.js b/js/src/jit-test/tests/sunspider/check-crypto-sha1.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-crypto-sha1.js rename to js/src/jit-test/tests/sunspider/check-crypto-sha1.js diff --git a/js/src/trace-test/tests/sunspider/check-date-format-tofte.js b/js/src/jit-test/tests/sunspider/check-date-format-tofte.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-date-format-tofte.js rename to js/src/jit-test/tests/sunspider/check-date-format-tofte.js diff --git a/js/src/trace-test/tests/sunspider/check-date-format-xparb.js b/js/src/jit-test/tests/sunspider/check-date-format-xparb.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-date-format-xparb.js rename to js/src/jit-test/tests/sunspider/check-date-format-xparb.js diff --git a/js/src/trace-test/tests/sunspider/check-math-cordic.js b/js/src/jit-test/tests/sunspider/check-math-cordic.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-math-cordic.js rename to js/src/jit-test/tests/sunspider/check-math-cordic.js diff --git a/js/src/trace-test/tests/sunspider/check-math-partial-sums.js b/js/src/jit-test/tests/sunspider/check-math-partial-sums.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-math-partial-sums.js rename to js/src/jit-test/tests/sunspider/check-math-partial-sums.js diff --git a/js/src/trace-test/tests/sunspider/check-math-spectral-norm.js b/js/src/jit-test/tests/sunspider/check-math-spectral-norm.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-math-spectral-norm.js rename to js/src/jit-test/tests/sunspider/check-math-spectral-norm.js diff --git a/js/src/trace-test/tests/sunspider/check-mont.js b/js/src/jit-test/tests/sunspider/check-mont.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-mont.js rename to js/src/jit-test/tests/sunspider/check-mont.js diff --git a/js/src/trace-test/tests/sunspider/check-regexp-dna.js b/js/src/jit-test/tests/sunspider/check-regexp-dna.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-regexp-dna.js rename to js/src/jit-test/tests/sunspider/check-regexp-dna.js diff --git a/js/src/trace-test/tests/sunspider/check-string-fasta.js b/js/src/jit-test/tests/sunspider/check-string-fasta.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-string-fasta.js rename to js/src/jit-test/tests/sunspider/check-string-fasta.js diff --git a/js/src/trace-test/tests/sunspider/check-string-tagcloud.js b/js/src/jit-test/tests/sunspider/check-string-tagcloud.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-string-tagcloud.js rename to js/src/jit-test/tests/sunspider/check-string-tagcloud.js diff --git a/js/src/trace-test/tests/sunspider/check-string-unpack-code.js b/js/src/jit-test/tests/sunspider/check-string-unpack-code.js similarity index 100% rename from js/src/trace-test/tests/sunspider/check-string-unpack-code.js rename to js/src/jit-test/tests/sunspider/check-string-unpack-code.js diff --git a/js/src/trace-test/tests/v8-v5/check-crypto.js b/js/src/jit-test/tests/v8-v5/check-crypto.js similarity index 100% rename from js/src/trace-test/tests/v8-v5/check-crypto.js rename to js/src/jit-test/tests/v8-v5/check-crypto.js diff --git a/js/src/trace-test/tests/v8-v5/check-deltablue.js b/js/src/jit-test/tests/v8-v5/check-deltablue.js similarity index 100% rename from js/src/trace-test/tests/v8-v5/check-deltablue.js rename to js/src/jit-test/tests/v8-v5/check-deltablue.js diff --git a/js/src/trace-test/tests/v8-v5/check-earley-boyer.js b/js/src/jit-test/tests/v8-v5/check-earley-boyer.js similarity index 100% rename from js/src/trace-test/tests/v8-v5/check-earley-boyer.js rename to js/src/jit-test/tests/v8-v5/check-earley-boyer.js diff --git a/js/src/trace-test/tests/v8-v5/check-raytrace.js b/js/src/jit-test/tests/v8-v5/check-raytrace.js similarity index 100% rename from js/src/trace-test/tests/v8-v5/check-raytrace.js rename to js/src/jit-test/tests/v8-v5/check-raytrace.js diff --git a/js/src/trace-test/tests/v8-v5/check-regexp.js b/js/src/jit-test/tests/v8-v5/check-regexp.js similarity index 100% rename from js/src/trace-test/tests/v8-v5/check-regexp.js rename to js/src/jit-test/tests/v8-v5/check-regexp.js diff --git a/js/src/trace-test/tests/v8-v5/check-richards.js b/js/src/jit-test/tests/v8-v5/check-richards.js similarity index 100% rename from js/src/trace-test/tests/v8-v5/check-richards.js rename to js/src/jit-test/tests/v8-v5/check-richards.js diff --git a/js/src/trace-test/tests/v8-v5/check-splay.js b/js/src/jit-test/tests/v8-v5/check-splay.js similarity index 99% rename from js/src/trace-test/tests/v8-v5/check-splay.js rename to js/src/jit-test/tests/v8-v5/check-splay.js index 6d9f8b97703e..cd83e41a091a 100644 --- a/js/src/trace-test/tests/v8-v5/check-splay.js +++ b/js/src/jit-test/tests/v8-v5/check-splay.js @@ -78,7 +78,7 @@ function GeneratePayloadTree(depth, key) { function GenerateKey() { // The benchmark framework guarantees that Math.random is // deterministic; see base.js. - // base.js isn't pulled in for trace-tests + // base.js isn't pulled in for jit-tests return MyMath.random(); } diff --git a/js/src/jitstats.tbl b/js/src/jitstats.tbl index 1f85fafccb50..74a6b7f43eb0 100644 --- a/js/src/jitstats.tbl +++ b/js/src/jitstats.tbl @@ -36,7 +36,7 @@ * * ***** END LICENSE BLOCK ***** */ -/* NB: Keep this list synced with jitstatHandler in trace-test.js. */ +/* NB: Keep this list synced with jitstatHandler in jit-test.js. */ /** * Proper use of this file: Consumers must define JITSTAT; they can optionally * also define MONITOR_JITSTAT or RECORDER_JITSTAT or both to do separate diff --git a/js/src/jsanalyze.cpp b/js/src/jsanalyze.cpp new file mode 100644 index 000000000000..72572dcc1b91 --- /dev/null +++ b/js/src/jsanalyze.cpp @@ -0,0 +1,664 @@ +/* -*- Mode: c++; c-basic-offset: 4; tab-width: 40; indent-tabs-mode: nil -*- */ +/* vim: set ts=40 sw=4 et tw=99: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla SpiderMonkey bytecode analysis + * + * The Initial Developer of the Original Code is + * Mozilla Foundation + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Brian Hackett + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "jsanalyze.h" +#include "jsautooplen.h" +#include "jscompartment.h" +#include "jscntxt.h" + +namespace js { +namespace analyze { + +///////////////////////////////////////////////////////////////////// +// Script +///////////////////////////////////////////////////////////////////// + +void +Script::destroy() +{ + JS_FinishArenaPool(&pool); +} + +template +inline T * +ArenaArray(JSArenaPool &pool, unsigned count) +{ + void *v; + JS_ARENA_ALLOCATE(v, &pool, count * sizeof(T)); + return (T *) v; +} + +template +inline T * +ArenaNew(JSArenaPool &pool) +{ + void *v; + JS_ARENA_ALLOCATE(v, &pool, sizeof(T)); + return new (v) T(); +} + +///////////////////////////////////////////////////////////////////// +// Bytecode +///////////////////////////////////////////////////////////////////// + +bool +Bytecode::mergeDefines(JSContext *cx, Script *script, bool initial, unsigned newDepth, + uint32 *newArray, unsigned newCount) +{ + if (initial) { + /* + * Haven't handled any incoming edges to this bytecode before. + * Define arrays are copy on write, so just reuse the array for this bytecode. + */ + stackDepth = newDepth; + defineArray = newArray; + defineCount = newCount; + return true; + } + + /* + * This bytecode has multiple incoming edges, intersect the new array with any + * variables known to be defined along other incoming edges. + */ + if (analyzed) { +#ifdef DEBUG + /* + * Once analyzed, a bytecode has its full set of definitions. There are two + * properties we depend on to ensure this. First, bytecode for a function + * is emitted in topological order, and since we analyze bytecodes in the + * order they were emitted we will have seen all incoming jumps except + * for any loop back edges. Second, javascript has structured control flow, + * so loop heads dominate their bodies; the set of variables defined + * on a back edge will be at least as large as at the head of the loop, + * so no intersection or further analysis needs to be done. + */ + JS_ASSERT(stackDepth == newDepth); + for (unsigned i = 0; i < defineCount; i++) { + bool found = false; + for (unsigned j = 0; j < newCount; j++) { + if (newArray[j] == defineArray[i]) + found = true; + } + JS_ASSERT(found); + } +#endif + } else { + JS_ASSERT(stackDepth == newDepth); + bool owned = false; + for (unsigned i = 0; i < defineCount; i++) { + bool found = false; + for (unsigned j = 0; j < newCount; j++) { + if (newArray[j] == defineArray[i]) + found = true; + } + if (!found) { + /* + * Get a mutable copy of the defines. This can end up making + * several copies for a bytecode if it has many incoming edges + * with progressively smaller sets of defined variables. + */ + if (!owned) { + uint32 *reallocArray = ArenaArray(script->pool, defineCount); + if (!reallocArray) { + script->setOOM(cx); + return false; + } + memcpy(reallocArray, defineArray, defineCount * sizeof(uint32)); + defineArray = reallocArray; + owned = true; + } + + /* Swap with the last element and pop the array. */ + defineArray[i--] = defineArray[--defineCount]; + } + } + } + + return true; +} + +///////////////////////////////////////////////////////////////////// +// Analysis +///////////////////////////////////////////////////////////////////// + +inline bool +Script::addJump(JSContext *cx, unsigned offset, + unsigned *currentOffset, unsigned *forwardJump, + unsigned stackDepth, uint32 *defineArray, unsigned defineCount) +{ + JS_ASSERT(offset < script->length); + + Bytecode *&bytecode = code[offset]; + bool initial = (bytecode == NULL); + if (initial) { + bytecode = ArenaNew(pool); + if (!bytecode) { + setOOM(cx); + return false; + } + } + + if (!bytecode->mergeDefines(cx, this, initial, stackDepth, defineArray, defineCount)) + return false; + bytecode->jumpTarget = true; + + if (offset < *currentOffset) { + /* Don't follow back edges to bytecode which has already been analyzed. */ + if (!bytecode->analyzed) { + if (*forwardJump == 0) + *forwardJump = *currentOffset; + *currentOffset = offset; + } + } else if (offset > *forwardJump) { + *forwardJump = offset; + } + + return true; +} + +inline void +Script::setLocal(uint32 local, uint32 offset) +{ + JS_ASSERT(local < localCount()); + JS_ASSERT(offset != LOCAL_CONDITIONALLY_DEFINED); + + /* + * It isn't possible to change the point when a variable becomes unconditionally + * defined, or to mark it as unconditionally defined after it has already been + * marked as having a use before def. It *is* possible to mark it as having + * a use before def after marking it as unconditionally defined. In a loop such as: + * + * while ((a = b) != 0) { x = a; } + * + * When walking through the body of this loop, we will first analyze the test + * (which comes after the body in the bytecode stream) as unconditional code, + * and mark a as definitely defined. a is not in the define array when taking + * the loop's back edge, so it is treated as possibly undefined when written to x. + */ + JS_ASSERT(locals[local] == LOCAL_CONDITIONALLY_DEFINED || + locals[local] == offset || offset == LOCAL_USE_BEFORE_DEF); + + locals[local] = offset; +} + +static inline ptrdiff_t +GetJumpOffset(jsbytecode *pc, jsbytecode *pc2) +{ + uint32 type = JOF_OPTYPE(*pc); + if (JOF_TYPE_IS_EXTENDED_JUMP(type)) + return GET_JUMPX_OFFSET(pc2); + return GET_JUMP_OFFSET(pc2); +} + +static inline unsigned +GetBytecodeLength(jsbytecode *pc) +{ + JSOp op = (JSOp)*pc; + JS_ASSERT(op < JSOP_LIMIT); + JS_ASSERT(op != JSOP_TRAP); + + if (js_CodeSpec[op].length != -1) + return js_CodeSpec[op].length; + return js_GetVariableBytecodeLength(pc); +} + +// return whether op bytecodes do not fallthrough (they may do a jump). +static inline bool +BytecodeNoFallThrough(JSOp op) +{ + switch (op) { + case JSOP_GOTO: + case JSOP_GOTOX: + case JSOP_DEFAULT: + case JSOP_DEFAULTX: + case JSOP_RETURN: + case JSOP_STOP: + case JSOP_RETRVAL: + case JSOP_THROW: + case JSOP_TABLESWITCH: + case JSOP_TABLESWITCHX: + case JSOP_LOOKUPSWITCH: + case JSOP_LOOKUPSWITCHX: + case JSOP_FILTER: + return true; + case JSOP_GOSUB: + case JSOP_GOSUBX: + // these fall through indirectly, after executing a 'finally'. + return false; + default: + return false; + } +} + +/* Untrap a single PC, and retrap it at scope exit. */ +struct UntrapOpcode +{ + jsbytecode *pc; + bool trap; + + UntrapOpcode(JSContext *cx, JSScript *script, jsbytecode *pc) + : pc(pc), trap(JSOp(*pc) == JSOP_TRAP) + { + if (trap) + *pc = JS_GetTrapOpcode(cx, script, pc); + } + + ~UntrapOpcode() + { + if (trap) + *pc = JSOP_TRAP; + } +}; + +void +Script::analyze(JSContext *cx, JSScript *script) +{ + JS_ASSERT(!code && !locals); + this->script = script; + + JS_InitArenaPool(&pool, "script_analyze", 256, 8, NULL); + + unsigned length = script->length; + unsigned nfixed = localCount(); + + code = ArenaArray(pool, length); + locals = ArenaArray(pool, nfixed); + + if (!code || !locals) { + setOOM(cx); + return; + } + + PodZero(code, length); + + for (unsigned i = 0; i < nfixed; i++) + locals[i] = LOCAL_CONDITIONALLY_DEFINED; + + /* + * Treat locals as having a possible use-before-def if they could be accessed + * by debug code or by eval, or if they could be accessed by an inner script. + */ + + if (script->usesEval || cx->compartment->debugMode) { + for (uint32 i = 0; i < nfixed; i++) + setLocal(i, LOCAL_USE_BEFORE_DEF); + } + + for (uint32 i = 0; i < script->nClosedVars; i++) { + uint32 slot = script->getClosedVar(i); + if (slot < nfixed) + setLocal(slot, LOCAL_USE_BEFORE_DEF); + } + + /* + * If we are in the middle of one or more jumps, the offset of the highest + * target jumping over this bytecode. Includes implicit jumps from + * try/catch/finally blocks. + */ + unsigned forwardJump = 0; + + /* + * If we are in the middle of a try block, the offset of the highest + * catch/finally/enditer. + */ + unsigned forwardCatch = 0; + + /* Fill in stack depth and definitions at initial bytecode. */ + Bytecode *startcode = ArenaNew(pool); + if (!startcode) { + setOOM(cx); + return; + } + + startcode->stackDepth = 0; + code[0] = startcode; + + unsigned offset, nextOffset = 0; + while (nextOffset < length) { + offset = nextOffset; + + JS_ASSERT(forwardCatch <= forwardJump); + + /* Check if the current forward jump/try-block has finished. */ + if (forwardJump && forwardJump == offset) + forwardJump = 0; + if (forwardCatch && forwardCatch == offset) + forwardCatch = 0; + + Bytecode *&bytecode = code[offset]; + jsbytecode *pc = script->code + offset; + + UntrapOpcode untrap(cx, script, pc); + + JSOp op = (JSOp)*pc; + JS_ASSERT(op < JSOP_LIMIT); + + /* Immediate successor of this bytecode. */ + unsigned successorOffset = offset + GetBytecodeLength(pc); + + /* + * Next bytecode to analyze. This is either the successor, or is an + * earlier bytecode if this bytecode has a loop backedge. + */ + nextOffset = successorOffset; + + if (!bytecode) { + /* Haven't found a path by which this bytecode is reachable. */ + continue; + } + + if (bytecode->analyzed) { + /* No need to reanalyze, see Bytecode::mergeDefines. */ + continue; + } + + bytecode->analyzed = true; + + if (forwardCatch) + bytecode->inTryBlock = true; + + unsigned stackDepth = bytecode->stackDepth; + uint32 *defineArray = bytecode->defineArray; + unsigned defineCount = bytecode->defineCount; + + if (!forwardJump) { + /* + * There is no jump over this bytecode, nor a containing try block. + * Either this bytecode will definitely be executed, or an exception + * will be thrown which the script does not catch. Either way, + * any variables definitely defined at this bytecode will stay + * defined throughout the rest of the script. We just need to + * remember the offset where the variable became unconditionally + * defined, rather than continue to maintain it in define arrays. + */ + for (unsigned i = 0; i < defineCount; i++) { + uint32 local = defineArray[i]; + JS_ASSERT_IF(locals[local] != LOCAL_CONDITIONALLY_DEFINED && + locals[local] != LOCAL_USE_BEFORE_DEF, + locals[local] <= offset); + if (locals[local] == LOCAL_CONDITIONALLY_DEFINED) + setLocal(local, offset); + } + defineArray = NULL; + defineCount = 0; + } + + unsigned nuses, ndefs; + if (js_CodeSpec[op].nuses == -1) + nuses = js_GetVariableStackUses(op, pc); + else + nuses = js_CodeSpec[op].nuses; + + if (js_CodeSpec[op].ndefs == -1) + ndefs = js_GetEnterBlockStackDefs(cx, script, pc); + else + ndefs = js_CodeSpec[op].ndefs; + + JS_ASSERT(stackDepth >= nuses); + stackDepth -= nuses; + stackDepth += ndefs; + + switch (op) { + + case JSOP_SETRVAL: + case JSOP_POPV: + usesRval = true; + break; + + case JSOP_NAME: + case JSOP_CALLNAME: + case JSOP_BINDNAME: + case JSOP_SETNAME: + case JSOP_DELNAME: + case JSOP_INCNAME: + case JSOP_DECNAME: + case JSOP_NAMEINC: + case JSOP_NAMEDEC: + case JSOP_FORNAME: + usesScope = true; + break; + + /* Watch for opcodes the method JIT doesn't compile. */ + case JSOP_GOSUB: + case JSOP_GOSUBX: + case JSOP_IFPRIMTOP: + case JSOP_FILTER: + case JSOP_ENDFILTER: + case JSOP_TABLESWITCHX: + case JSOP_LOOKUPSWITCHX: + hadFailure = true; + return; + + case JSOP_TABLESWITCH: { + jsbytecode *pc2 = pc; + unsigned defaultOffset = offset + GetJumpOffset(pc, pc2); + pc2 += JUMP_OFFSET_LEN; + jsint low = GET_JUMP_OFFSET(pc2); + pc2 += JUMP_OFFSET_LEN; + jsint high = GET_JUMP_OFFSET(pc2); + pc2 += JUMP_OFFSET_LEN; + + if (!addJump(cx, defaultOffset, &nextOffset, &forwardJump, + stackDepth, defineArray, defineCount)) { + return; + } + + for (jsint i = low; i <= high; i++) { + unsigned targetOffset = offset + GetJumpOffset(pc, pc2); + if (targetOffset != offset) { + if (!addJump(cx, targetOffset, &nextOffset, &forwardJump, + stackDepth, defineArray, defineCount)) { + return; + } + } + pc2 += JUMP_OFFSET_LEN; + } + break; + } + + case JSOP_LOOKUPSWITCH: { + jsbytecode *pc2 = pc; + unsigned defaultOffset = offset + GetJumpOffset(pc, pc2); + pc2 += JUMP_OFFSET_LEN; + unsigned npairs = GET_UINT16(pc2); + pc2 += UINT16_LEN; + + if (!addJump(cx, defaultOffset, &nextOffset, &forwardJump, + stackDepth, defineArray, defineCount)) { + return; + } + + while (npairs) { + pc2 += INDEX_LEN; + unsigned targetOffset = offset + GetJumpOffset(pc, pc2); + if (!addJump(cx, targetOffset, &nextOffset, &forwardJump, + stackDepth, defineArray, defineCount)) { + return; + } + pc2 += JUMP_OFFSET_LEN; + npairs--; + } + break; + } + + case JSOP_TRY: { + /* + * Everything between a try and corresponding catch or finally is conditional. + * Note that there is no problem with code which is skipped by a thrown + * exception but is not caught by a later handler in the same function: + * no more code will execute, and it does not matter what is defined. + */ + JSTryNote *tn = script->trynotes()->vector; + JSTryNote *tnlimit = tn + script->trynotes()->length; + for (; tn < tnlimit; tn++) { + unsigned startOffset = script->main - script->code + tn->start; + if (startOffset == offset + 1) { + unsigned catchOffset = startOffset + tn->length; + + /* This will overestimate try block code, for multiple catch/finally. */ + if (catchOffset > forwardCatch) + forwardCatch = catchOffset; + + if (tn->kind != JSTRY_ITER) { + if (!addJump(cx, catchOffset, &nextOffset, &forwardJump, + stackDepth, defineArray, defineCount)) { + return; + } + code[catchOffset]->exceptionEntry = true; + } + } + } + break; + } + + case JSOP_GETLOCAL: + /* + * Watch for uses of variables not known to be defined, and mark + * them as having possible uses before definitions. Ignore GETLOCAL + * followed by a POP, these are generated for, e.g. 'var x;' + */ + if (pc[JSOP_GETLOCAL_LENGTH] != JSOP_POP) { + uint32 local = GET_SLOTNO(pc); + if (local < nfixed && !localDefined(local, offset)) + setLocal(local, LOCAL_USE_BEFORE_DEF); + } + break; + + case JSOP_CALLLOCAL: + case JSOP_INCLOCAL: + case JSOP_DECLOCAL: + case JSOP_LOCALINC: + case JSOP_LOCALDEC: { + uint32 local = GET_SLOTNO(pc); + if (local < nfixed && !localDefined(local, offset)) + setLocal(local, LOCAL_USE_BEFORE_DEF); + break; + } + + case JSOP_SETLOCAL: + case JSOP_FORLOCAL: { + uint32 local = GET_SLOTNO(pc); + JS_ASSERT_IF(local < nfixed && + locals[local] != LOCAL_CONDITIONALLY_DEFINED && + locals[local] != LOCAL_USE_BEFORE_DEF, + locals[local] <= offset); + if (local < nfixed && locals[local] == LOCAL_CONDITIONALLY_DEFINED) { + if (forwardJump) { + /* Add this local to the variables defined after this bytecode. */ + uint32 *newArray = ArenaArray(pool, defineCount + 1); + if (!newArray) { + setOOM(cx); + return; + } + if (defineCount) + memcpy(newArray, defineArray, defineCount * sizeof(uint32)); + defineArray = newArray; + defineArray[defineCount++] = local; + } else { + /* This local is unconditionally defined by this bytecode. */ + setLocal(local, offset); + } + } + break; + } + + default: + break; + } + + uint32 type = JOF_TYPE(js_CodeSpec[op].format); + + /* Check basic jump opcodes, which may or may not have a fallthrough. */ + if (type == JOF_JUMP || type == JOF_JUMPX) { + /* Some opcodes behave differently on their branching path. */ + unsigned newStackDepth; + + switch (op) { + case JSOP_OR: + case JSOP_AND: + case JSOP_ORX: + case JSOP_ANDX: + /* OR/AND instructions push the operation result when short circuiting. */ + newStackDepth = stackDepth + 1; + break; + + case JSOP_CASE: + case JSOP_CASEX: + /* Case instructions do not push the lvalue back when branching. */ + newStackDepth = stackDepth - 1; + break; + + default: + newStackDepth = stackDepth; + break; + } + + unsigned targetOffset = offset + GetJumpOffset(pc, pc); + if (!addJump(cx, targetOffset, &nextOffset, &forwardJump, + newStackDepth, defineArray, defineCount)) { + return; + } + } + + /* Handle any fallthrough from this opcode. */ + if (!BytecodeNoFallThrough(op)) { + JS_ASSERT(successorOffset < script->length); + + Bytecode *&nextcode = code[successorOffset]; + bool initial = (nextcode == NULL); + + if (initial) { + nextcode = ArenaNew(pool); + if (!nextcode) { + setOOM(cx); + return; + } + } + + if (!nextcode->mergeDefines(cx, this, initial, stackDepth, defineArray, defineCount)) + return; + } + } + + JS_ASSERT(!failed()); + JS_ASSERT(forwardJump == 0 && forwardCatch == 0); +} + +} /* namespace analyze */ +} /* namespace js */ diff --git a/js/src/jsanalyze.h b/js/src/jsanalyze.h new file mode 100644 index 000000000000..de7430290297 --- /dev/null +++ b/js/src/jsanalyze.h @@ -0,0 +1,213 @@ +/* -*- Mode: c++; c-basic-offset: 4; tab-width: 40; indent-tabs-mode: nil -*- */ +/* vim: set ts=40 sw=4 et tw=99: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla SpiderMonkey bytecode analysis + * + * The Initial Developer of the Original Code is + * Mozilla Foundation + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* Definitions for javascript analysis. */ + +#ifndef jsanalyze_h___ +#define jsanalyze_h___ + +#include "jsarena.h" +#include "jscntxt.h" +#include "jsscript.h" + +struct JSScript; + +namespace js { +namespace analyze { + +class Script; + +/* Information about a bytecode instruction. */ +struct Bytecode +{ + friend class Script; + + /* Whether there are any incoming jumps to this instruction. */ + bool jumpTarget : 1; + + /* Whether this instruction has been analyzed to get its output defines and stack. */ + bool analyzed : 1; + + /* Whether this is a catch/finally entry point. */ + bool exceptionEntry : 1; + + /* Whether this is in a try block. */ + bool inTryBlock : 1; + + /* Whether this is a method JIT safe point. */ + bool safePoint : 1; + + /* Stack depth before this opcode. */ + uint32 stackDepth; + + /* + * The set of locals defined at this point. This does not include locals which + * were unconditionally defined at an earlier point in the script. + */ + uint32 defineCount; + uint32 *defineArray; + + Bytecode() + { + PodZero(this); + } + + private: + bool mergeDefines(JSContext *cx, + Script *script, bool initial, uint32 newDepth, + uint32 *newArray, uint32 newCount); + + /* Whether a local variable is in the define set at this bytecode. */ + bool isDefined(uint32 slot) + { + JS_ASSERT(analyzed); + for (size_t ind = 0; ind < defineCount; ind++) { + if (defineArray[ind] == slot) + return true; + } + return false; + } +}; + +/* Information about a script. */ +class Script +{ + friend struct Bytecode; + + JSScript *script; + Bytecode **code; + + /* Maximum number of locals to consider for a script. */ + static const unsigned LOCAL_LIMIT = 50; + + /* Offsets at which each local becomes unconditionally defined, or a value below. */ + uint32 *locals; + + static const uint32 LOCAL_USE_BEFORE_DEF = uint32(-1); + static const uint32 LOCAL_CONDITIONALLY_DEFINED = uint32(-2); + + bool outOfMemory; + bool hadFailure; + bool usesRval; + bool usesScope; + + public: + /* Pool for allocating analysis structures which will not outlive this script. */ + JSArenaPool pool; + + void analyze(JSContext *cx, JSScript *script); + void destroy(); + + /* + * For analysis scripts allocated on the stack. Scripts don't have constructors, + * and must be zeroed out before being used. + */ + ~Script() { destroy(); } + + /* Whether we ran out of memory during analysis. */ + bool OOM() { return outOfMemory; } + + /* Whether the script was analyzed successfully. */ + bool failed() { return hadFailure; } + + /* Whether there are POPV/SETRVAL bytecodes which can write to the frame's rval. */ + bool usesReturnValue() const { return usesRval; } + + /* Whether there are NAME bytecodes which can access the frame's scope chain. */ + bool usesScopeChain() const { return usesScope; } + + /* Accessors for bytecode information. */ + + Bytecode& getCode(uint32 offset) { + JS_ASSERT(offset < script->length); + JS_ASSERT(code[offset]); + return *code[offset]; + } + Bytecode& getCode(jsbytecode *pc) { return getCode(pc - script->code); } + + Bytecode* maybeCode(uint32 offset) { + JS_ASSERT(offset < script->length); + return code[offset]; + } + Bytecode* maybeCode(jsbytecode *pc) { return maybeCode(pc - script->code); } + + bool jumpTarget(uint32 offset) { + JS_ASSERT(offset < script->length); + return code[offset] && code[offset]->jumpTarget; + } + bool jumpTarget(jsbytecode *pc) { return jumpTarget(pc - script->code); } + + /* Accessors for local variable information. */ + + unsigned localCount() { + return (script->nfixed >= LOCAL_LIMIT) ? LOCAL_LIMIT : script->nfixed; + } + + bool localHasUseBeforeDef(uint32 local) { + JS_ASSERT(local < script->nfixed && !failed()); + return local >= localCount() || locals[local] == LOCAL_USE_BEFORE_DEF; + } + + /* These return true for variables that may have a use before def. */ + bool localDefined(uint32 local, uint32 offset) { + return localHasUseBeforeDef(local) || (locals[local] <= offset) || + getCode(offset).isDefined(local); + } + bool localDefined(uint32 local, jsbytecode *pc) { + return localDefined(local, pc - script->code); + } + + private: + void setOOM(JSContext *cx) { + if (!outOfMemory) + js_ReportOutOfMemory(cx); + outOfMemory = true; + hadFailure = true; + } + + inline bool addJump(JSContext *cx, unsigned offset, + unsigned *currentOffset, unsigned *forwardJump, + unsigned stackDepth, uint32 *defineArray, unsigned defineCount); + + inline void setLocal(uint32 local, uint32 offset); +}; + +} /* namespace analyze */ +} /* namespace js */ + +#endif // jsanalyze_h___ diff --git a/js/src/jsapi-tests/Makefile.in b/js/src/jsapi-tests/Makefile.in index 756cfe0bde67..5f875e1d419c 100644 --- a/js/src/jsapi-tests/Makefile.in +++ b/js/src/jsapi-tests/Makefile.in @@ -71,6 +71,7 @@ CPPSRCS = \ testScriptObject.cpp \ testSetPropertyWithNativeGetterStubSetter.cpp \ testBug604087.cpp \ + testThreads.cpp \ testTrap.cpp \ testUTF8.cpp \ testXDR.cpp \ diff --git a/js/src/jsapi-tests/testClassGetter.cpp b/js/src/jsapi-tests/testClassGetter.cpp index d7c5f52d63ca..ca134853ee86 100644 --- a/js/src/jsapi-tests/testClassGetter.cpp +++ b/js/src/jsapi-tests/testClassGetter.cpp @@ -53,10 +53,8 @@ static JSFunctionSpec ptestFunctions[] = { BEGIN_TEST(testClassGetter_isCalled) { - JSObject *my_proto; - - my_proto = JS_InitClass(cx, JS_GetGlobalObject(cx), NULL, &ptestClass, PTest, 0, - NULL, ptestFunctions, NULL, NULL); + CHECK(JS_InitClass(cx, JS_GetGlobalObject(cx), NULL, &ptestClass, PTest, 0, + NULL, ptestFunctions, NULL, NULL)); EXEC("function check() { var o = new PTest(); o.test_fn(); o.test_value1; o.test_value2; o.test_value1; }"); diff --git a/js/src/jsapi-tests/testContexts.cpp b/js/src/jsapi-tests/testContexts.cpp index aa1a1df2c7ca..699730f56197 100644 --- a/js/src/jsapi-tests/testContexts.cpp +++ b/js/src/jsapi-tests/testContexts.cpp @@ -29,58 +29,6 @@ BEGIN_TEST(testContexts_IsRunning) } END_TEST(testContexts_IsRunning) -#ifdef JS_THREADSAFE - -#include "prthread.h" - -struct ThreadData { - JSRuntime *rt; - JSObject *obj; - const char *code; - bool ok; -}; - -BEGIN_TEST(testContexts_bug561444) - { - const char *code = ".b.@c = '';"; - EXEC(code); - - jsrefcount rc = JS_SuspendRequest(cx); - { - ThreadData data = {rt, global, code, false}; - PRThread *thread = - PR_CreateThread(PR_USER_THREAD, threadMain, &data, - PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); - CHECK(thread); - PR_JoinThread(thread); - CHECK(data.ok); - } - JS_ResumeRequest(cx, rc); - return true; - } - - static void threadMain(void *arg) { - ThreadData *d = (ThreadData *) arg; - - JSContext *cx = JS_NewContext(d->rt, 8192); - if (!cx) - return; - JS_BeginRequest(cx); - { - jsvalRoot v(cx); - - JSAutoEnterCompartment ac; - ac.enterAndIgnoreErrors(cx, d->obj); - - if (!JS_EvaluateScript(cx, d->obj, d->code, strlen(d->code), __FILE__, __LINE__, v.addr())) - return; - } - JS_DestroyContext(cx); - d->ok = true; - } -END_TEST(testContexts_bug561444) -#endif - BEGIN_TEST(testContexts_bug563735) { JSContext *cx2 = JS_NewContext(rt, 8192); diff --git a/js/src/jsapi-tests/testThreads.cpp b/js/src/jsapi-tests/testThreads.cpp new file mode 100644 index 000000000000..63e6ec9f1279 --- /dev/null +++ b/js/src/jsapi-tests/testThreads.cpp @@ -0,0 +1,155 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sw=4 et tw=99: + */ + +#ifdef JS_THREADSAFE + +#include "tests.h" +#include "prthread.h" + +struct ThreadData { + JSRuntime *rt; + JSObject *obj; + const char *code; + bool ok; +}; + +BEGIN_TEST(testThreads_bug561444) + { + const char *code = ".b.@c = '';"; + EXEC(code); + + jsrefcount rc = JS_SuspendRequest(cx); + { + ThreadData data = {rt, global, code, false}; + PRThread *thread = + PR_CreateThread(PR_USER_THREAD, threadMain, &data, + PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); + CHECK(thread); + PR_JoinThread(thread); + CHECK(data.ok); + } + JS_ResumeRequest(cx, rc); + return true; + } + + static void threadMain(void *arg) { + ThreadData *d = (ThreadData *) arg; + + JSContext *cx = JS_NewContext(d->rt, 8192); + if (!cx) + return; + JS_BeginRequest(cx); + { + JSAutoEnterCompartment ac; + jsval v; + d->ok = ac.enter(cx, d->obj) && + JS_EvaluateScript(cx, d->obj, d->code, strlen(d->code), __FILE__, __LINE__, + &v); + } + JS_DestroyContext(cx); + } +END_TEST(testThreads_bug561444) + +template +class Repeat { + size_t n; + const T &t; + + public: + Repeat(size_t n, const T &t) : n(n), t(t) {} + + bool operator()() const { + for (size_t i = 0; i < n; i++) + if (!t()) + return false; + return true; + } +}; + +template Repeat repeat(size_t n, const T &t) { return Repeat(n, t); } + +/* Class of callable that does something in n parallel threads. */ +template +class Parallel { + size_t n; + const T &t; + + struct pair { const Parallel *self; bool ok; }; + + static void threadMain(void *arg) { + pair *p = (pair *) arg; + if (!p->self->t()) + p->ok = false; + } + + public: + Parallel(size_t n, const T &t) : n(n), t(t) {} + + bool operator()() const { + pair p = {this, true}; + + PRThread **thread = new PRThread *[n]; + if (!thread) + return false; + + size_t i; + for (i = 0; i < n; i++) { + thread[i] = PR_CreateThread(PR_USER_THREAD, threadMain, &p, PR_PRIORITY_NORMAL, + PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); + if (thread[i] == NULL) { + p.ok = false; + break; + } + } + while (i--) + PR_JoinThread(thread[i]); + + delete[] thread; + return p.ok; + } +}; + +template Parallel parallel(size_t n, const T &t) { return Parallel(n, t); } + +/* Class of callable that creates a compartment and runs some code in it. */ +class eval { + JSRuntime *rt; + const char *code; + + public: + eval(JSRuntime *rt, const char *code) : rt(rt), code(code) {} + + bool operator()() const { + JSContext *cx = JS_NewContext(rt, 8192); + if (!cx) + return false; + + bool ok = false; + { + JSAutoRequest ar(cx); + JSObject *global = + JS_NewCompartmentAndGlobalObject(cx, JSAPITest::basicGlobalClass(), NULL); + if (global) { + JS_SetGlobalObject(cx, global); + jsval rval; + ok = JS_InitStandardClasses(cx, global) && + JS_EvaluateScript(cx, global, code, strlen(code), "", 0, &rval); + } + } + JS_DestroyContextMaybeGC(cx); + return ok; + } +}; + +BEGIN_TEST(testThreads_bug604782) +{ + jsrefcount rc = JS_SuspendRequest(cx); + bool ok = repeat(20, parallel(3, eval(rt, "for(i=0;i<1000;i++);")))(); + JS_ResumeRequest(cx, rc); + CHECK(ok); + return true; +} +END_TEST(testThreads_bug604782) + +#endif diff --git a/js/src/jsapi-tests/tests.h b/js/src/jsapi-tests/tests.h index 53e4c7040bd7..07329192d8cc 100644 --- a/js/src/jsapi-tests/tests.h +++ b/js/src/jsapi-tests/tests.h @@ -48,7 +48,7 @@ class jsvalRoot { -public: + public: explicit jsvalRoot(JSContext *context, jsval value = JSVAL_NULL) : cx(context), v(value) { @@ -70,7 +70,7 @@ public: jsval * addr() { return &v; } jsval value() const { return v; } -private: + private: JSContext *cx; jsval v; }; @@ -78,7 +78,7 @@ private: /* Note: Aborts on OOM. */ class JSAPITestString { js::Vector chars; -public: + public: JSAPITestString() {} JSAPITestString(const char *s) { *this += s; } JSAPITestString(const JSAPITestString &s) { *this += s; } @@ -105,7 +105,7 @@ inline JSAPITestString operator+(JSAPITestString a, const JSAPITestString &b) { class JSAPITest { -public: + public: static JSAPITest *list; JSAPITest *next; @@ -217,7 +217,17 @@ public: JSAPITestString messages() const { return msgs; } -protected: + static JSClass * basicGlobalClass() { + static JSClass c = { + "global", JSCLASS_GLOBAL_FLAGS, + JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, + JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, + JSCLASS_NO_OPTIONAL_MEMBERS + }; + return &c; + } + + protected: static JSBool print(JSContext *cx, uintN argc, jsval *vp) { @@ -271,13 +281,7 @@ protected: } virtual JSClass * getGlobalClass() { - static JSClass basicGlobalClass = { - "global", JSCLASS_GLOBAL_FLAGS, - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, - JSCLASS_NO_OPTIONAL_MEMBERS - }; - return &basicGlobalClass; + return basicGlobalClass(); } virtual JSObject * createGlobal() { @@ -300,7 +304,7 @@ protected: #define BEGIN_TEST(testname) \ class cls_##testname : public JSAPITest { \ - public: \ + public: \ virtual const char * name() { return #testname; } \ virtual bool run() @@ -318,7 +322,7 @@ protected: #define BEGIN_FIXTURE_TEST(fixture, testname) \ class cls_##testname : public fixture { \ - public: \ + public: \ virtual const char * name() { return #testname; } \ virtual bool run() diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index de8bcc0d1f0f..29e1d72bd552 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -649,10 +649,6 @@ JSRuntime::init(uint32 maxbytes) stateChange = JS_NEW_CONDVAR(gcLock); if (!stateChange) return false; - titleSharingDone = JS_NEW_CONDVAR(gcLock); - if (!titleSharingDone) - return false; - titleSharingTodo = NO_TITLE_SHARING_TODO; debuggerLock = JS_NEW_LOCK(); if (!debuggerLock) return false; @@ -703,8 +699,6 @@ JSRuntime::~JSRuntime() JS_DESTROY_LOCK(rtLock); if (stateChange) JS_DESTROY_CONDVAR(stateChange); - if (titleSharingDone) - JS_DESTROY_CONDVAR(titleSharingDone); if (debuggerLock) JS_DESTROY_LOCK(debuggerLock); #endif @@ -813,8 +807,8 @@ StartRequest(JSContext *cx) JSThread *t = cx->thread; JS_ASSERT(CURRENT_THREAD_IS_ME(t)); - if (t->requestDepth) { - t->requestDepth++; + if (t->data.requestDepth) { + t->data.requestDepth++; } else { JSRuntime *rt = cx->runtime; AutoLockGC lock(rt); @@ -827,7 +821,14 @@ StartRequest(JSContext *cx) /* Indicate that a request is running. */ rt->requestCount++; - t->requestDepth = 1; + t->data.requestDepth = 1; + + /* + * Adjust rt->interruptCounter to reflect any interrupts added while the + * thread was suspended. + */ + if (t->data.interruptFlags) + JS_ATOMIC_INCREMENT(&rt->interruptCounter); if (rt->requestCount == 1 && rt->activityCallback) rt->activityCallback(rt->activityCallbackArg, true); @@ -839,9 +840,9 @@ StopRequest(JSContext *cx) { JSThread *t = cx->thread; JS_ASSERT(CURRENT_THREAD_IS_ME(t)); - JS_ASSERT(t->requestDepth != 0); - if (t->requestDepth != 1) { - t->requestDepth--; + JS_ASSERT(t->data.requestDepth != 0); + if (t->data.requestDepth != 1) { + t->data.requestDepth--; } else { LeaveTrace(cx); /* for GC safety */ @@ -851,9 +852,14 @@ StopRequest(JSContext *cx) JSRuntime *rt = cx->runtime; AutoLockGC lock(rt); - t->requestDepth = 0; + t->data.requestDepth = 0; - js_ShareWaitingTitles(cx); + /* + * Adjust rt->interruptCounter to reflect any interrupts added while the + * thread still had active requests. + */ + if (t->data.interruptFlags) + JS_ATOMIC_DECREMENT(&rt->interruptCounter); /* Give the GC a chance to run if this was the last request running. */ JS_ASSERT(rt->requestCount > 0); @@ -903,12 +909,12 @@ JS_SuspendRequest(JSContext *cx) JSThread *t = cx->thread; JS_ASSERT(CURRENT_THREAD_IS_ME(t)); - jsrefcount saveDepth = t->requestDepth; + jsrefcount saveDepth = t->data.requestDepth; if (!saveDepth) return 0; t->suspendCount++; - t->requestDepth = 1; + t->data.requestDepth = 1; StopRequest(cx); return saveDepth; #else @@ -925,10 +931,10 @@ JS_ResumeRequest(JSContext *cx, jsrefcount saveDepth) if (saveDepth == 0) return; JS_ASSERT(saveDepth >= 1); - JS_ASSERT(!t->requestDepth); + JS_ASSERT(!t->data.requestDepth); JS_ASSERT(t->suspendCount); StartRequest(cx); - t->requestDepth = saveDepth; + t->data.requestDepth = saveDepth; t->suspendCount--; #endif } @@ -1702,15 +1708,6 @@ JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsid id, JSBool *resolved) return JS_TRUE; } -static JSBool -AlreadyHasOwnProperty(JSContext *cx, JSObject *obj, JSAtom *atom) -{ - JS_LOCK_OBJ(cx, obj); - bool found = obj->nativeContains(ATOM_TO_JSID(atom)); - JS_UNLOCK_OBJ(cx, obj); - return found; -} - JS_PUBLIC_API(JSBool) JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj) { @@ -1724,7 +1721,7 @@ JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj) /* Check whether we need to bind 'undefined' and define it if so. */ atom = rt->atomState.typeAtoms[JSTYPE_VOID]; - if (!AlreadyHasOwnProperty(cx, obj, atom) && + if (!obj->nativeContains(ATOM_TO_JSID(atom)) && !obj->defineProperty(cx, ATOM_TO_JSID(atom), UndefinedValue(), PropertyStub, PropertyStub, JSPROP_PERMANENT | JSPROP_READONLY)) { @@ -1734,7 +1731,7 @@ JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj) /* Initialize any classes that have not been resolved yet. */ for (i = 0; standard_class_atoms[i].init; i++) { atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset); - if (!AlreadyHasOwnProperty(cx, obj, atom) && + if (!obj->nativeContains(ATOM_TO_JSID(atom)) && !standard_class_atoms[i].init(cx, obj)) { return JS_FALSE; } @@ -1800,7 +1797,7 @@ static JSIdArray * EnumerateIfResolved(JSContext *cx, JSObject *obj, JSAtom *atom, JSIdArray *ida, jsint *ip, JSBool *foundp) { - *foundp = AlreadyHasOwnProperty(cx, obj, atom); + *foundp = obj->nativeContains(ATOM_TO_JSID(atom)); if (*foundp) ida = AddAtomToArray(cx, atom, ida, ip); return ida; @@ -3000,7 +2997,7 @@ JS_NewGlobalObject(JSContext *cx, JSClass *clasp) return NULL; /* Construct a regexp statics object for this global object. */ - JSObject *res = regexp_statics_construct(cx); + JSObject *res = regexp_statics_construct(cx, obj); if (!res || !js_SetReservedSlot(cx, obj, JSRESERVED_GLOBAL_REGEXP_STATICS, ObjectValue(*res))) { @@ -3164,17 +3161,15 @@ LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, jsid id, if (shape->isMethod()) { AutoShapeRooter root(cx, shape); - JS_UNLOCK_OBJ(cx, obj2); vp->setObject(shape->methodObject()); return obj2->methodReadBarrier(cx, *shape, vp); } /* Peek at the native property's slot value, without doing a Get. */ if (obj2->containsSlot(shape->slot)) - *vp = obj2->lockedGetSlot(shape->slot); + *vp = obj2->nativeGetSlot(shape->slot); else vp->setBoolean(true); - JS_UNLOCK_OBJ(cx, obj2); } else if (obj2->isDenseArray()) { return js_GetDenseArrayElementValue(cx, obj2, id, vp); } else { @@ -3236,23 +3231,15 @@ JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name, uintN return atom && JS_LookupPropertyWithFlagsById(cx, obj, ATOM_TO_JSID(atom), flags, &obj2, vp); } -static JSBool -HasPropertyResult(JSContext *cx, JSObject *obj2, JSProperty *prop, JSBool *foundp) -{ - *foundp = (prop != NULL); - if (prop) - obj2->dropProperty(cx, prop); - return true; -} - JS_PUBLIC_API(JSBool) JS_HasPropertyById(JSContext *cx, JSObject *obj, jsid id, JSBool *foundp) { JSObject *obj2; JSProperty *prop; - return LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING, - &obj2, &prop) && - HasPropertyResult(cx, obj2, prop, foundp); + JSBool ok = LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING, + &obj2, &prop); + *foundp = (prop != NULL); + return ok; } JS_PUBLIC_API(JSBool) @@ -3290,14 +3277,10 @@ JS_AlreadyHasOwnPropertyById(JSContext *cx, JSObject *obj, jsid id, JSBool *foun return JS_FALSE; } *foundp = (obj == obj2); - if (prop) - obj2->dropProperty(cx, prop); return JS_TRUE; } - JS_LOCK_OBJ(cx, obj); *foundp = obj->nativeContains(id); - JS_UNLOCK_OBJ(cx, obj); return JS_TRUE; } @@ -3508,7 +3491,6 @@ JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name, const char *ali return JS_FALSE; } if (obj2 != obj || !obj->isNative()) { - obj2->dropProperty(cx, prop); JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS, alias, name, obj2->getClass()->name); return JS_FALSE; @@ -3524,7 +3506,6 @@ JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name, const char *ali shape->shortid) != NULL); } - JS_UNLOCK_OBJ(cx, obj); return ok; } @@ -3534,7 +3515,6 @@ JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias) JSObject *obj2; JSProperty *prop; Shape *shape; - JSBool ok; CHECK_REQUEST(cx); assertSameCompartment(cx, obj); @@ -3550,20 +3530,17 @@ JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias) } if (obj2 != obj || !obj->isNative()) { char numBuf[12]; - obj2->dropProperty(cx, prop); JS_snprintf(numBuf, sizeof numBuf, "%ld", (long)alias); JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS, numBuf, name, obj2->getClass()->name); return JS_FALSE; } shape = (Shape *)prop; - ok = (js_AddNativeProperty(cx, obj, INT_TO_JSID(alias), - shape->getter(), shape->setter(), shape->slot, - shape->attributes(), shape->getFlags() | Shape::ALIAS, - shape->shortid) - != NULL); - JS_UNLOCK_OBJ(cx, obj); - return ok; + return js_AddNativeProperty(cx, obj, INT_TO_JSID(alias), + shape->getter(), shape->setter(), shape->slot, + shape->attributes(), shape->getFlags() | Shape::ALIAS, + shape->shortid) + != NULL; } static JSBool @@ -3582,8 +3559,6 @@ GetPropertyDescriptorById(JSContext *cx, JSObject *obj, jsid id, uintN flags, desc->getter = NULL; desc->setter = NULL; desc->value.setUndefined(); - if (prop) - obj2->dropProperty(cx, prop); return JS_TRUE; } @@ -3599,11 +3574,10 @@ GetPropertyDescriptorById(JSContext *cx, JSObject *obj, jsid id, uintN flags, desc->getter = shape->getter(); desc->setter = shape->setter(); if (obj2->containsSlot(shape->slot)) - desc->value = obj2->lockedGetSlot(shape->slot); + desc->value = obj2->nativeGetSlot(shape->slot); else desc->value.setUndefined(); } - JS_UNLOCK_OBJ(cx, obj2); } else { if (obj2->isProxy()) { JSAutoResolveFlags rf(cx, flags); @@ -3701,8 +3675,6 @@ SetPropertyAttributesById(JSContext *cx, JSObject *obj, jsid id, uintN attrs, JS return false; if (!prop || obj != obj2) { *foundp = false; - if (prop) - obj2->dropProperty(cx, prop); return true; } JSBool ok = obj->isNative() @@ -5026,22 +4998,10 @@ JS_GetOperationCallback(JSContext *cx) JS_PUBLIC_API(void) JS_TriggerOperationCallback(JSContext *cx) { - /* - * We allow for cx to come from another thread. Thus we must deal with - * possible JS_ClearContextThread calls when accessing cx->thread. But we - * assume that the calling thread is in a request so JSThread cannot be - * GC-ed. - */ - JSThreadData *td; #ifdef JS_THREADSAFE - JSThread *thread = cx->thread; - if (!thread) - return; - td = &thread->data; -#else - td = JS_THREAD_DATA(cx); + AutoLockGC lock(cx->runtime); #endif - td->triggerOperationCallback(); + TriggerOperationCallback(cx); } JS_PUBLIC_API(void) @@ -5869,7 +5829,7 @@ JS_ClearContextThread(JSContext *cx) AutoLockGC lock(rt); js_WaitForGC(rt); js_ClearContextThread(cx); - JS_ASSERT_IF(JS_CLIST_IS_EMPTY(&t->contextList), !t->requestDepth); + JS_ASSERT_IF(JS_CLIST_IS_EMPTY(&t->contextList), !t->data.requestDepth); /* * We can access t->id as long as the GC lock is held and we cannot race diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 8baad1ef801e..72c2fdc7c252 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -915,6 +915,7 @@ JS_StringToVersion(const char *string); embedding. */ #define JSOPTION_METHODJIT JS_BIT(14) /* Whole-method JIT. */ +#define JSOPTION_PROFILING JS_BIT(15) /* Profiler to make tracer/methodjit choices. */ #define JSOPTION_ROPES JS_BIT(16) /* Enable rope optimization for * string concat. */ @@ -1719,6 +1720,10 @@ struct JSClass { #define JSCLASS_MARK_IS_TRACE (1<<(JSCLASS_HIGH_FLAGS_SHIFT+3)) #define JSCLASS_INTERNAL_FLAG2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+4)) +/* Indicate whether the proto or ctor should be frozen. */ +#define JSCLASS_FREEZE_PROTO (1<<(JSCLASS_HIGH_FLAGS_SHIFT+5)) +#define JSCLASS_FREEZE_CTOR (1<<(JSCLASS_HIGH_FLAGS_SHIFT+6)) + /* Additional global reserved slots, beyond those for standard prototypes. */ #define JSRESERVED_GLOBAL_SLOTS_COUNT 3 #define JSRESERVED_GLOBAL_THIS (JSProto_LIMIT * 3) diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 5c933537e05b..c95e6499386c 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -385,7 +385,6 @@ GetArrayElement(JSContext *cx, JSObject *obj, jsdouble index, JSBool *hole, *hole = JS_TRUE; vp->setUndefined(); } else { - obj2->dropProperty(cx, prop); if (!obj->getProperty(cx, idr.id(), vp)) return JS_FALSE; *hole = JS_FALSE; @@ -727,7 +726,6 @@ array_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) shape = (const Shape *) prop; if (!js_NativeGet(cx, obj, obj2, shape, JSGET_METHOD_BARRIER, vp)) return JS_FALSE; - JS_UNLOCK_OBJ(cx, obj2); } return JS_TRUE; } @@ -914,9 +912,7 @@ array_trace(JSTracer *trc, JSObject *obj) } } -namespace { - -JSBool +static JSBool array_fix(JSContext *cx, JSObject *obj, bool *success, AutoIdVector *props) { JS_ASSERT(obj->isDenseArray()); @@ -933,8 +929,6 @@ array_fix(JSContext *cx, JSObject *obj, bool *success, AutoIdVector *props) return true; } -} // namespace - Class js_ArrayClass = { "Array", Class::NON_NATIVE | @@ -1725,7 +1719,7 @@ js::array_sort(JSContext *cx, uintN argc, Value *vp) Value *argv = JS_ARGV(cx, vp); Value fval; - if (argc > 0) { + if (argc > 0 && !argv[0].isUndefined()) { if (argv[0].isPrimitive()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_SORT_ARG); return false; @@ -2463,7 +2457,7 @@ array_slice(JSContext *cx, uintN argc, Value *vp) } begin = (jsuint)d; - if (argc > 1) { + if (argc > 1 && !argv[1].isUndefined()) { if (!ValueToNumber(cx, argv[1], &d)) return JS_FALSE; d = js_DoubleToInteger(d); diff --git a/js/src/jsbuiltins.cpp b/js/src/jsbuiltins.cpp index eb328bcca18d..f16aa8b4d806 100644 --- a/js/src/jsbuiltins.cpp +++ b/js/src/jsbuiltins.cpp @@ -185,12 +185,11 @@ JS_DEFINE_CALLINFO_2(extern, INT32, js_StringToInt32, CONTEXT, STRING, 1, ACCSET static inline JSBool AddPropertyHelper(JSContext* cx, JSObject* obj, Shape* shape, bool isDefinitelyAtom) { - JS_LOCK_OBJ(cx, obj); JS_ASSERT(shape->previous() == obj->lastProperty()); if (obj->nativeEmpty()) { if (!obj->ensureClassReservedSlotsForEmptyObject(cx)) - goto exit_trace; + return false; } uint32 slot; @@ -201,20 +200,12 @@ AddPropertyHelper(JSContext* cx, JSObject* obj, Shape* shape, bool isDefinitelyA JS_ASSERT(obj->getSlot(slot).isUndefined()); } else { if (!obj->allocSlot(cx, &slot)) - goto exit_trace; + return false; JS_ASSERT(slot == shape->slot); } obj->extend(cx, shape, isDefinitelyAtom); - if (js_IsPropertyCacheDisabled(cx)) - goto exit_trace; - - JS_UNLOCK_OBJ(cx, obj); - return true; - - exit_trace: - JS_UNLOCK_OBJ(cx, obj); - return false; + return !js_IsPropertyCacheDisabled(cx); } JSBool FASTCALL @@ -247,8 +238,6 @@ HasProperty(JSContext* cx, JSObject* obj, jsid id) JSProperty* prop; if (js_LookupPropertyWithFlags(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop) < 0) return JS_NEITHER; - if (prop) - obj2->dropProperty(cx, prop); return prop != NULL; } diff --git a/js/src/jsclone.cpp b/js/src/jsclone.cpp index a5c1a910528b..7c880dc6f116 100644 --- a/js/src/jsclone.cpp +++ b/js/src/jsclone.cpp @@ -559,8 +559,6 @@ JSStructuredCloneWriter::write(const Value &v) } if (prop) { - obj2->dropProperty(context(), prop); - Value val; if (!writeId(id) || !obj->getProperty(context(), id, &val) || !startWrite(val)) return false; diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 3f8dac67e856..aec05b196c68 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -597,7 +597,6 @@ DestroyThread(JSThread *thread) { /* The thread must have zero contexts. */ JS_ASSERT(JS_CLIST_IS_EMPTY(&thread->contextList)); - JS_ASSERT(!thread->titleToShare); /* * The conservative GC scanner should be disabled when the thread leaves @@ -625,6 +624,13 @@ js_CurrentThread(JSRuntime *rt) JSThread::Map::AddPtr p = rt->threads.lookupForAdd(id); if (p) { thread = p->value; + + /* + * If thread has no contexts, it might be left over from a previous + * thread with the same id but a different stack address. + */ + if (JS_CLIST_IS_EMPTY(&thread->contextList)) + thread->data.nativeStackBase = GetNativeStackBase(); } else { JS_UNLOCK_GC(rt); thread = NewThread(id); @@ -642,6 +648,7 @@ js_CurrentThread(JSRuntime *rt) JS_ASSERT(p->value == thread); } JS_ASSERT(thread->id == id); + JS_ASSERT(thread->data.nativeStackBase == GetNativeStackBase()); return thread; } @@ -1027,10 +1034,10 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode) /* * For API compatibility we support destroying contexts with non-zero * cx->outstandingRequests but we assume that all JS_BeginRequest calls - * on this cx contributes to cx->thread->requestDepth and there is no + * on this cx contributes to cx->thread->data.requestDepth and there is no * JS_SuspendRequest calls that set aside the counter. */ - JS_ASSERT(cx->outstandingRequests <= cx->thread->requestDepth); + JS_ASSERT(cx->outstandingRequests <= cx->thread->data.requestDepth); #endif if (mode != JSDCM_NEW_FAILED) { @@ -1055,7 +1062,7 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode) * Typically we are called outside a request, so ensure that the GC is not * running before removing the context from rt->contextList, see bug 477021. */ - if (cx->thread->requestDepth == 0) + if (cx->thread->data.requestDepth == 0) js_WaitForGC(rt); #endif JS_REMOVE_LINK(&cx->link); @@ -1083,7 +1090,7 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode) * force or maybe run the GC, but by that point, rt->state will * not be JSRTS_UP, and that GC attempt will return early. */ - if (cx->thread->requestDepth == 0) + if (cx->thread->data.requestDepth == 0) JS_BeginRequest(cx); #endif @@ -1133,7 +1140,7 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode) JSThread *t = cx->thread; #endif js_ClearContextThread(cx); - JS_ASSERT_IF(JS_CLIST_IS_EMPTY(&t->contextList), !t->requestDepth); + JS_ASSERT_IF(JS_CLIST_IS_EMPTY(&t->contextList), !t->data.requestDepth); #endif #ifdef JS_METER_DST_OFFSET_CACHING cx->dstOffsetCache.dumpStats(); @@ -1176,19 +1183,6 @@ FreeContext(JSContext *cx) js_free(cx); } -JSBool -js_ValidContextPointer(JSRuntime *rt, JSContext *cx) -{ - JSCList *cl; - - for (cl = rt->contextList.next; cl != &rt->contextList; cl = cl->next) { - if (cl == &cx->link) - return JS_TRUE; - } - JS_RUNTIME_METER(rt, deadContexts); - return JS_FALSE; -} - JSContext * js_ContextIterator(JSRuntime *rt, JSBool unlocked, JSContext **iterp) { @@ -1208,7 +1202,7 @@ js_NextActiveContext(JSRuntime *rt, JSContext *cx) JSContext *iter = cx; #ifdef JS_THREADSAFE while ((cx = js_ContextIterator(rt, JS_FALSE, &iter)) != NULL) { - if (cx->outstandingRequests && cx->thread->requestDepth) + if (cx->outstandingRequests && cx->thread->data.requestDepth) break; } return cx; @@ -1832,8 +1826,8 @@ js_ReportValueErrorFlags(JSContext *cx, uintN flags, const uintN errorNumber, #if defined DEBUG && defined XP_UNIX /* For gdb usage. */ -void js_traceon(JSContext *cx) { cx->tracefp = stderr; cx->tracePrevPc = NULL; } -void js_traceoff(JSContext *cx) { cx->tracefp = NULL; } +void js_logon(JSContext *cx) { cx->logfp = stderr; cx->logPrevPc = NULL; } +void js_logoff(JSContext *cx) { cx->logfp = NULL; } #endif JSErrorFormatString js_ErrorFormatString[JSErr_Limit] = { @@ -1854,16 +1848,23 @@ js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber) JSBool js_InvokeOperationCallback(JSContext *cx) { + JSRuntime *rt = cx->runtime; + JSThreadData *td = JS_THREAD_DATA(cx); + JS_ASSERT_REQUEST_DEPTH(cx); - JS_ASSERT(JS_THREAD_DATA(cx)->interruptFlags & JSThreadData::INTERRUPT_OPERATION_CALLBACK); + JS_ASSERT(td->interruptFlags != 0); /* - * Reset the callback flag first, then yield. If another thread is racing + * Reset the callback counter first, then yield. If another thread is racing * us here we will accumulate another callback request which will be * serviced at the next opportunity. */ - JS_ATOMIC_CLEAR_MASK(&JS_THREAD_DATA(cx)->interruptFlags, - JSThreadData::INTERRUPT_OPERATION_CALLBACK); + JS_LOCK_GC(rt); + td->interruptFlags = 0; +#ifdef JS_THREADSAFE + JS_ATOMIC_DECREMENT(&rt->interruptCounter); +#endif + JS_UNLOCK_GC(rt); /* * Unless we are going to run the GC, we automatically yield the current @@ -1872,7 +1873,6 @@ js_InvokeOperationCallback(JSContext *cx) * not yield. Operation callbacks are supposed to happen rarely (seconds, * not milliseconds) so it is acceptable to yield at every callback. */ - JSRuntime *rt = cx->runtime; if (rt->gcIsNeeded) { js_GC(cx, GC_NORMAL); @@ -1910,18 +1910,39 @@ JSBool js_HandleExecutionInterrupt(JSContext *cx) { JSBool result = JS_TRUE; - if (JS_THREAD_DATA(cx)->interruptFlags & JSThreadData::INTERRUPT_OPERATION_CALLBACK) + if (JS_THREAD_DATA(cx)->interruptFlags) result = js_InvokeOperationCallback(cx) && result; return result; } namespace js { +void +TriggerOperationCallback(JSContext *cx) +{ + /* + * We allow for cx to come from another thread. Thus we must deal with + * possible JS_ClearContextThread calls when accessing cx->thread. But we + * assume that the calling thread is in a request so JSThread cannot be + * GC-ed. + */ + JSThreadData *td; +#ifdef JS_THREADSAFE + JSThread *thread = cx->thread; + if (!thread) + return; + td = &thread->data; +#else + td = JS_THREAD_DATA(cx); +#endif + td->triggerOperationCallback(cx->runtime); +} + void TriggerAllOperationCallbacks(JSRuntime *rt) { for (ThreadDataIter i(rt); !i.empty(); i.popFront()) - i.threadData()->triggerOperationCallback(); + i.threadData()->triggerOperationCallback(rt); } } /* namespace js */ @@ -2274,6 +2295,9 @@ JSContext::updateJITEnabled() JSC::MacroAssemblerX86Common::HasSSE2 # endif ; +#ifdef JS_TRACER + profilingEnabled = (options & JSOPTION_PROFILING) && traceJitEnabled && methodJitEnabled; +#endif #endif } diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index b2d0f6130d1f..8a90708ea7c6 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -155,6 +155,7 @@ typedef Queue SlotList; class TypeMap; struct REFragment; typedef nanojit::HashMap REHashMap; +class LoopProfile; #if defined(JS_JIT_SPEW) || defined(DEBUG) struct FragPI; @@ -924,6 +925,12 @@ typedef HashMap, SystemAllocPolicy> RecordAttemptMap; +/* Holds the profile data for loops. */ +typedef HashMap, + SystemAllocPolicy> LoopProfileMap; + class Oracle; /* @@ -987,13 +994,22 @@ struct TraceMonitor { nanojit::Assembler* assembler; FrameInfoCache* frameCache; + /* This gets incremented every time the monitor is flushed. */ + uintN flushEpoch; + Oracle* oracle; TraceRecorder* recorder; + /* If we are profiling a loop, this tracks the current profile. Otherwise NULL. */ + LoopProfile* profile; + GlobalState globalStates[MONITOR_N_GLOBAL_STATES]; TreeFragment* vmfragments[FRAGMENT_TABLE_SIZE]; RecordAttemptMap* recordAttempts; + /* A hashtable mapping PC values to loop profiles for those loops. */ + LoopProfileMap* loopProfiles; + /* * Maximum size of the code cache before we start flushing. 1/16 of this * size is used as threshold for the regular expression code cache. @@ -1104,11 +1120,17 @@ struct JSPendingProxyOperation { }; struct JSThreadData { +#ifdef JS_THREADSAFE + /* The request depth for this thread. */ + unsigned requestDepth; +#endif + /* - * If this flag is set, we were asked to call back the operation callback - * as soon as possible. + * If non-zero, we were been asked to call the operation callback as soon + * as possible. If the thread has an active request, this contributes + * towards rt->interruptCounter. */ - volatile jsword interruptFlags; + volatile int32 interruptFlags; /* Keeper of the contiguous stack used by all contexts in this thread. */ js::StackSpace stackSpace; @@ -1193,17 +1215,8 @@ struct JSThreadData { void mark(JSTracer *trc); void purge(JSContext *cx); - static const jsword INTERRUPT_OPERATION_CALLBACK = 0x1; - - void triggerOperationCallback() { - /* - * Use JS_ATOMIC_SET in the hope that it will make sure the write will - * become immediately visible to other processors polling the flag. - * Note that we only care about visibility here, not read/write - * ordering. - */ - JS_ATOMIC_SET_MASK(&interruptFlags, INTERRUPT_OPERATION_CALLBACK); - } + /* This must be called with the GC lock held. */ + inline void triggerOperationCallback(JSRuntime *rt); }; #ifdef JS_THREADSAFE @@ -1224,21 +1237,6 @@ struct JSThread { /* Opaque thread-id, from NSPR's PR_GetCurrentThread(). */ void *id; - /* Indicates that the thread is waiting in ClaimTitle from jslock.cpp. */ - JSTitle *titleToShare; - - /* - * This thread is inside js_GC, either waiting until it can start GC, or - * waiting for GC to finish on another thread. This thread holds no locks; - * other threads may steal titles from it. - * - * Protected by rt->gcLock. - */ - bool gcWaiting; - - /* The request depth for this thread. */ - unsigned requestDepth; - /* Number of JS_SuspendRequest calls withot JS_ResumeRequest. */ unsigned suspendCount; @@ -1246,9 +1244,6 @@ struct JSThread { unsigned checkRequestDepth; # endif - /* Weak ref, for low-cost sealed title locking */ - JSTitle *lockedSealedTitle; - /* Factored out of JSThread for !JS_THREADSAFE embedding in JSRuntime. */ JSThreadData data; }; @@ -1455,28 +1450,6 @@ struct JSRuntime { /* Used to synchronize down/up state change; protected by gcLock. */ PRCondVar *stateChange; - /* - * State for sharing single-threaded titles, once a second thread tries to - * lock a title. The titleSharingDone condvar is protected by rt->gcLock - * to minimize number of locks taken in JS_EndRequest. - * - * The titleSharingTodo linked list is likewise "global" per runtime, not - * one-list-per-context, to conserve space over all contexts, optimizing - * for the likely case that titles become shared rarely, and among a very - * small set of threads (contexts). - */ - PRCondVar *titleSharingDone; - JSTitle *titleSharingTodo; - -/* - * Magic terminator for the rt->titleSharingTodo linked list, threaded through - * title->u.link. This hack allows us to test whether a title is on the list - * by asking whether title->u.link is non-null. We use a large, likely bogus - * pointer here to distinguish this value from any valid u.count (small int) - * value. - */ -#define NO_TITLE_SHARING_TODO ((JSTitle *) 0xfeedbeef) - /* * Lock serializing trapList and watchPointList accesses, and count of all * mutations to trapList and watchPointList made by debugger threads. To @@ -1536,7 +1509,10 @@ struct JSRuntime { JSObject *anynameObject; JSObject *functionNamespaceObject; -#ifndef JS_THREADSAFE +#ifdef JS_THREADSAFE + /* Number of threads with active requests and unhandled interrupts. */ + volatile int32 interruptCounter; +#else JSThreadData threadData; #define JS_THREAD_DATA(cx) (&(cx)->runtime->threadData) @@ -1596,14 +1572,7 @@ struct JSRuntime { jsrefcount nonInlineCalls; jsrefcount constructs; - /* Title lock and scope property metering. */ - jsrefcount claimAttempts; - jsrefcount claimedTitles; - jsrefcount deadContexts; - jsrefcount deadlocksAvoided; - jsrefcount liveShapes; - jsrefcount sharedTitles; - jsrefcount totalShapes; + /* Property metering. */ jsrefcount liveObjectProps; jsrefcount liveObjectPropsPreSweep; jsrefcount totalObjectProps; @@ -2045,11 +2014,11 @@ struct JSContext /* Argument formatter support for JS_{Convert,Push}Arguments{,VA}. */ JSArgumentFormatMap *argumentFormatMap; - /* Last message string and trace file for debugging. */ + /* Last message string and log file for debugging. */ char *lastMessage; #ifdef DEBUG - void *tracefp; - jsbytecode *tracePrevPc; + void *logfp; + jsbytecode *logPrevPc; #endif /* Per-context optional error reporter. */ @@ -2246,6 +2215,7 @@ struct JSContext #ifdef JS_METHODJIT bool methodJitEnabled; + bool profilingEnabled; #endif /* Caller must be holding runtime->gcLock. */ @@ -2420,7 +2390,7 @@ class AutoCheckRequestDepth { # define CHECK_REQUEST(cx) \ JS_ASSERT((cx)->thread); \ - JS_ASSERT((cx)->thread->requestDepth || (cx)->thread == (cx)->runtime->gcThread); \ + JS_ASSERT((cx)->thread->data.requestDepth || (cx)->thread == (cx)->runtime->gcThread); \ AutoCheckRequestDepth _autoCheckRequestDepth(cx); #else @@ -3058,13 +3028,6 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize); extern void js_DestroyContext(JSContext *cx, JSDestroyContextMode mode); -/* - * Return true if cx points to a context in rt->contextList, else return false. - * NB: the caller (see jslock.c:ClaimTitle) must hold rt->gcLock. - */ -extern JSBool -js_ValidContextPointer(JSRuntime *rt, JSContext *cx); - static JS_INLINE JSContext * js_ContextFromLinkField(JSCList *link) { @@ -3200,7 +3163,7 @@ extern JSErrorFormatString js_ErrorFormatString[JSErr_Limit]; #ifdef JS_THREADSAFE # define JS_ASSERT_REQUEST_DEPTH(cx) (JS_ASSERT((cx)->thread), \ - JS_ASSERT((cx)->thread->requestDepth >= 1)) + JS_ASSERT((cx)->thread->data.requestDepth >= 1)) #else # define JS_ASSERT_REQUEST_DEPTH(cx) ((void) 0) #endif @@ -3212,7 +3175,27 @@ extern JSErrorFormatString js_ErrorFormatString[JSErr_Limit]; */ #define JS_CHECK_OPERATION_LIMIT(cx) \ (JS_ASSERT_REQUEST_DEPTH(cx), \ - (!(JS_THREAD_DATA(cx)->interruptFlags & JSThreadData::INTERRUPT_OPERATION_CALLBACK) || js_InvokeOperationCallback(cx))) + (!JS_THREAD_DATA(cx)->interruptFlags || js_InvokeOperationCallback(cx))) + +JS_ALWAYS_INLINE void +JSThreadData::triggerOperationCallback(JSRuntime *rt) +{ + /* + * Use JS_ATOMIC_SET and JS_ATOMIC_INCREMENT in the hope that it ensures + * the write will become immediately visible to other processors polling + * the flag. Note that we only care about visibility here, not read/write + * ordering: this field can only be written with the GC lock held. + */ + if (interruptFlags) + return; + JS_ATOMIC_SET(&interruptFlags, 1); + +#ifdef JS_THREADSAFE + /* rt->interruptCounter does not reflect suspended threads. */ + if (requestDepth != 0) + JS_ATOMIC_INCREMENT(&rt->interruptCounter); +#endif +} /* * Invoke the operation callback and return false if the current execution @@ -3226,7 +3209,11 @@ js_HandleExecutionInterrupt(JSContext *cx); namespace js { -/* Must be called with GC lock taken. */ +/* These must be called with GC lock taken. */ + +JS_FRIEND_API(void) +TriggerOperationCallback(JSContext *cx); + void TriggerAllOperationCallbacks(JSRuntime *rt); diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index ce17a22a1549..d523ec261e4f 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -38,9 +38,10 @@ * * ***** END LICENSE BLOCK ***** */ +#include "jscntxt.h" #include "jscompartment.h" #include "jsgc.h" -#include "jscntxt.h" +#include "jsiter.h" #include "jsproxy.h" #include "jsscope.h" #include "methodjit/PolyIC.h" @@ -143,6 +144,10 @@ JSCompartment::wrap(JSContext *cx, Value *vp) if (obj->compartment() == this) return true; + /* Translate StopIteration singleton. */ + if (obj->getClass() == &js_StopIterationClass) + return js_FindClassObject(cx, NULL, JSProto_StopIteration, vp); + /* Don't unwrap an outer window proxy. */ if (!obj->getClass()->ext.innerObject) { obj = vp->toObject().unwrap(&flags); diff --git a/js/src/jsdate.cpp b/js/src/jsdate.cpp index 3e26e2c17a31..34af443b32c0 100644 --- a/js/src/jsdate.cpp +++ b/js/src/jsdate.cpp @@ -2019,10 +2019,8 @@ date_toISOString(JSContext *cx, uintN argc, Value *vp) return date_utc_format(cx, vp, print_iso_string); } -namespace { - /* ES5 15.9.5.44. */ -JSBool +static JSBool date_toJSON(JSContext *cx, uintN argc, Value *vp) { /* Step 1. */ @@ -2068,8 +2066,6 @@ date_toJSON(JSContext *cx, uintN argc, Value *vp) return true; } -} - /* for Date.toLocaleString; interface to PRMJTime date struct. */ static void diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index b50de625c925..b4b9deb13218 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -559,8 +559,6 @@ DropWatchPointAndUnlock(JSContext *cx, JSWatchPoint *wp, uintN flag) DBG_UNLOCK(rt); if (!setter) { - JS_LOCK_OBJ(cx, wp->object); - /* * If the property wasn't found on wp->object, or it isn't still being * watched, then someone else must have deleted or unwatched it, and we @@ -575,7 +573,6 @@ DropWatchPointAndUnlock(JSContext *cx, JSWatchPoint *wp, uintN flag) if (!shape) ok = false; } - JS_UNLOCK_OBJ(cx, wp->object); } cx->free(wp); @@ -679,15 +676,13 @@ js_watch_set(JSContext *cx, JSObject *obj, jsid id, Value *vp) wp->flags |= JSWP_HELD; DBG_UNLOCK(rt); - JS_LOCK_OBJ(cx, obj); jsid propid = shape->id; jsid userid = SHAPE_USERID(shape); - JS_UNLOCK_OBJ(cx, obj); /* NB: wp is held, so we can safely dereference it still. */ if (!wp->handler(cx, obj, propid, obj->containsSlot(shape->slot) - ? Jsvalify(obj->getSlotMT(cx, shape->slot)) + ? Jsvalify(obj->nativeGetSlot(shape->slot)) : JSVAL_VOID, Jsvalify(vp), wp->closure)) { DBG_LOCK(rt); @@ -781,7 +776,6 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop; const Shape *shape; JSRuntime *rt; - JSBool ok; JSWatchPoint *wp; PropertyOp watcher; @@ -837,14 +831,13 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsid id, if (pobj->isNative()) { valroot.set(pobj->containsSlot(shape->slot) - ? pobj->lockedGetSlot(shape->slot) + ? pobj->nativeGetSlot(shape->slot) : UndefinedValue()); getter = shape->getter(); setter = shape->setter(); attrs = shape->attributes(); flags = shape->getFlags(); shortid = shape->shortid; - JS_UNLOCK_OBJ(cx, pobj); } else { if (!pobj->getProperty(cx, propid, valroot.addr()) || !pobj->getAttributes(cx, propid, &attrs)) { @@ -868,22 +861,17 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsid id, * At this point, prop/shape exists in obj, obj is locked, and we must * unlock the object before returning. */ - ok = JS_TRUE; DBG_LOCK(rt); wp = FindWatchPoint(rt, obj, propid); if (!wp) { DBG_UNLOCK(rt); watcher = js_WrapWatchedSetter(cx, propid, shape->attributes(), shape->setter()); - if (!watcher) { - ok = JS_FALSE; - goto out; - } + if (!watcher) + return JS_FALSE; wp = (JSWatchPoint *) cx->malloc(sizeof *wp); - if (!wp) { - ok = JS_FALSE; - goto out; - } + if (!wp) + return JS_FALSE; wp->handler = NULL; wp->closure = NULL; wp->object = obj; @@ -898,8 +886,7 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsid id, JS_INIT_CLIST(&wp->links); DBG_LOCK(rt); DropWatchPointAndUnlock(cx, wp, JSWP_LIVE); - ok = JS_FALSE; - goto out; + return JS_FALSE; } wp->shape = shape; @@ -916,10 +903,7 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsid id, wp->handler = handler; wp->closure = reinterpret_cast(closure); DBG_UNLOCK(rt); - -out: - JS_UNLOCK_OBJ(cx, obj); - return ok; + return JS_TRUE; } JS_PUBLIC_API(JSBool) diff --git a/js/src/jsemit.cpp b/js/src/jsemit.cpp index f10874d633d3..e514eaae936e 100644 --- a/js/src/jsemit.cpp +++ b/js/src/jsemit.cpp @@ -1713,7 +1713,6 @@ LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, JS_ASSERT(cg->compileAndGo()); obj = cg->scopeChain; - JS_LOCK_OBJ(cx, obj); const Shape *shape = obj->nativeLookup(ATOM_TO_JSID(atom)); if (shape) { /* @@ -1724,10 +1723,9 @@ LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, */ if (!shape->writable() && !shape->configurable() && shape->hasDefaultGetter() && obj->containsSlot(shape->slot)) { - *constp = obj->lockedGetSlot(shape->slot); + *constp = obj->getSlot(shape->slot); } } - JS_UNLOCK_OBJ(cx, obj); if (shape) break; @@ -4514,13 +4512,13 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) { JSBool ok, useful, wantval; JSStmtInfo *stmt, stmtInfo; - ptrdiff_t top, off, tmp, beq, jmp; + ptrdiff_t top, off, tmp, beq, jmp, tmp2, tmp3; JSParseNode *pn2, *pn3; JSAtom *atom; JSAtomListElement *ale; jsatomid atomIndex; uintN index; - ptrdiff_t noteIndex; + ptrdiff_t noteIndex, noteIndex2; JSSrcNoteType noteType; jsbytecode *pc; JSOp op; @@ -4831,6 +4829,9 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) jmp = EmitJump(cx, cg, JSOP_GOTO, 0); if (jmp < 0) return JS_FALSE; + noteIndex2 = js_NewSrcNote(cx, cg, SRC_TRACE); + if (noteIndex2 < 0) + return JS_FALSE; top = EmitTraceOp(cx, cg); if (top < 0) return JS_FALSE; @@ -4842,6 +4843,12 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) beq = EmitJump(cx, cg, JSOP_IFNE, top - CG_OFFSET(cg)); if (beq < 0) return JS_FALSE; + /* + * Be careful: We must set noteIndex2 before noteIndex in case the noteIndex + * note gets bigger. + */ + if (!js_SetSrcNoteOffset(cx, cg, noteIndex2, 0, beq - top)) + return JS_FALSE; if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, beq - jmp)) return JS_FALSE; ok = js_PopStatementCG(cx, cg); @@ -4853,6 +4860,10 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) if (noteIndex < 0 || js_Emit1(cx, cg, JSOP_NOP) < 0) return JS_FALSE; + noteIndex2 = js_NewSrcNote(cx, cg, SRC_TRACE); + if (noteIndex2 < 0) + return JS_FALSE; + /* Compile the loop body. */ top = EmitTraceOp(cx, cg); if (top < 0) @@ -4879,6 +4890,12 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) beq = EmitJump(cx, cg, JSOP_IFNE, top - CG_OFFSET(cg)); if (beq < 0) return JS_FALSE; + /* + * Be careful: We must set noteIndex2 before noteIndex in case the noteIndex + * note gets bigger. + */ + if (!js_SetSrcNoteOffset(cx, cg, noteIndex2, 0, beq - top)) + return JS_FALSE; if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, 1 + (beq - top))) return JS_FALSE; ok = js_PopStatementCG(cx, cg); @@ -4952,6 +4969,10 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) if (jmp < 0) return JS_FALSE; + noteIndex2 = js_NewSrcNote(cx, cg, SRC_TRACE); + if (noteIndex2 < 0) + return JS_FALSE; + top = CG_OFFSET(cg); SET_STATEMENT_TOP(&stmtInfo, top); if (EmitTraceOp(cx, cg) < 0) @@ -5099,9 +5120,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) /* The stack should be balanced around the JSOP_FOR* opcode sequence. */ JS_ASSERT(cg->stackDepth == loopDepth); - /* Set the first srcnote offset so we can find the start of the loop body. */ - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, CG_OFFSET(cg) - jmp)) - return JS_FALSE; + tmp2 = CG_OFFSET(cg); /* Emit code for the loop body. */ if (!js_EmitTree(cx, cg, pn->pn_right)) @@ -5123,6 +5142,15 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) if (beq < 0) return JS_FALSE; + /* + * Be careful: We must set noteIndex2 before noteIndex in case the noteIndex + * note gets bigger. + */ + if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex2, 0, beq - top)) + return JS_FALSE; + /* Set the first srcnote offset so we can find the start of the loop body. */ + if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, tmp2 - jmp)) + return JS_FALSE; /* Set the second srcnote offset so we can find the closing jump. */ if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1, beq - jmp)) return JS_FALSE; @@ -5180,6 +5208,10 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) top = CG_OFFSET(cg); SET_STATEMENT_TOP(&stmtInfo, top); + noteIndex2 = js_NewSrcNote(cx, cg, SRC_TRACE); + if (noteIndex2 < 0) + return JS_FALSE; + /* Emit code for the loop body. */ if (EmitTraceOp(cx, cg) < 0) return JS_FALSE; @@ -5188,10 +5220,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) /* Set the second note offset so we can find the update part. */ JS_ASSERT(noteIndex != -1); - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1, - CG_OFFSET(cg) - tmp)) { - return JS_FALSE; - } + tmp2 = CG_OFFSET(cg); /* Set loop and enclosing "update" offsets, for continue. */ stmt = &stmtInfo; @@ -5225,11 +5254,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) } } - /* Set the first note offset so we can find the loop condition. */ - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, - CG_OFFSET(cg) - tmp)) { - return JS_FALSE; - } + tmp3 = CG_OFFSET(cg); if (pn2->pn_kid2) { /* Fix up the goto from top to target the loop condition. */ @@ -5240,6 +5265,23 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) return JS_FALSE; } + /* + * Be careful: We must set noteIndex2 before noteIndex in case the noteIndex + * note gets bigger. + */ + if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex2, 0, + CG_OFFSET(cg) - top)) { + return JS_FALSE; + } + /* Set the first note offset so we can find the loop condition. */ + if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, + tmp3 - tmp)) { + return JS_FALSE; + } + if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1, + tmp2 - tmp)) { + return JS_FALSE; + } /* The third note offset helps us find the loop-closing jump. */ if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 2, CG_OFFSET(cg) - tmp)) { diff --git a/js/src/jsemit.h b/js/src/jsemit.h index c36f94c9311d..b3f834e04ffc 100644 --- a/js/src/jsemit.h +++ b/js/src/jsemit.h @@ -810,6 +810,7 @@ typedef enum JSSrcNoteType { SRC_WHILE = 4, /* JSOP_GOTO to for or while loop condition from before loop, else JSOP_NOP at top of do-while loop */ + SRC_TRACE = 4, /* For JSOP_TRACE; includes distance to loop end */ SRC_CONTINUE = 5, /* JSOP_GOTO is a continue, not a break; also used on JSOP_ENDINIT if extra comma at end of array literal: [1,2,,]; diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp index d7b5e414a74b..01c09df5bc4b 100644 --- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -259,8 +259,6 @@ GetStackTraceValueBuffer(JSExnPrivate *priv) return (jsval *)(priv->stackElems + priv->stackDepth); } -namespace { - struct CopyTo { Value *dst; @@ -270,8 +268,6 @@ struct CopyTo } }; -} - static JSBool InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message, JSString *filename, uintN lineno, JSErrorReport *report) @@ -463,8 +459,6 @@ exn_enumerate(JSContext *cx, JSObject *obj) atom = *(JSAtom **)((uint8 *)atomState + offsets[i]); if (!js_LookupProperty(cx, obj, ATOM_TO_JSID(atom), &pobj, &prop)) return JS_FALSE; - if (prop) - pobj->dropProperty(cx, prop); } return JS_TRUE; } diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index e80b4ac73d56..4d84c948b593 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -209,8 +209,6 @@ NewArguments(JSContext *cx, JSObject *parent, uint32 argc, JSObject &callee) return argsobj; } -namespace { - struct STATIC_SKIP_INFERENCE PutArg { PutArg(Value *dst) : dst(dst) {} @@ -222,8 +220,6 @@ struct STATIC_SKIP_INFERENCE PutArg } }; -} - JSObject * js_GetArgsObject(JSContext *cx, JSStackFrame *fp) { @@ -647,17 +643,11 @@ args_enumerate(JSContext *cx, JSObject *obj) JSProperty *prop; if (!js_LookupProperty(cx, obj, id, &pobj, &prop)) return false; - - /* prop is null when the property was deleted. */ - if (prop) - pobj->dropProperty(cx, prop); } return true; } -namespace { - -JSBool +static JSBool StrictArgGetter(JSContext *cx, JSObject *obj, jsid id, Value *vp) { LeaveTrace(cx); @@ -684,7 +674,7 @@ StrictArgGetter(JSContext *cx, JSObject *obj, jsid id, Value *vp) return true; } -JSBool +static JSBool StrictArgSetter(JSContext *cx, JSObject *obj, jsid id, Value *vp) { if (!InstanceOf(cx, obj, &StrictArgumentsClass, NULL)) @@ -711,7 +701,7 @@ StrictArgSetter(JSContext *cx, JSObject *obj, jsid id, Value *vp) js_SetProperty(cx, obj, id, vp, true); } -JSBool +static JSBool strictargs_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp) { JS_ASSERT(obj->isStrictArguments()); @@ -761,14 +751,14 @@ strictargs_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject return true; } -JSBool +static JSBool strictargs_enumerate(JSContext *cx, JSObject *obj) { JS_ASSERT(obj->isStrictArguments()); /* * Trigger reflection in strictargs_resolve using a series of - * js_LookupProperty calls. Beware deleted properties! + * js_LookupProperty calls. */ JSObject *pobj; JSProperty *prop; @@ -776,33 +766,23 @@ strictargs_enumerate(JSContext *cx, JSObject *obj) // length if (!js_LookupProperty(cx, obj, ATOM_TO_JSID(cx->runtime->atomState.lengthAtom), &pobj, &prop)) return false; - if (prop) - pobj->dropProperty(cx, prop); // callee if (!js_LookupProperty(cx, obj, ATOM_TO_JSID(cx->runtime->atomState.calleeAtom), &pobj, &prop)) return false; - if (prop) - pobj->dropProperty(cx, prop); // caller if (!js_LookupProperty(cx, obj, ATOM_TO_JSID(cx->runtime->atomState.callerAtom), &pobj, &prop)) return false; - if (prop) - pobj->dropProperty(cx, prop); for (uint32 i = 0, argc = obj->getArgsInitialLength(); i < argc; i++) { if (!js_LookupProperty(cx, obj, INT_TO_JSID(i), &pobj, &prop)) return false; - if (prop) - pobj->dropProperty(cx, prop); } return true; } -} // namespace - static void args_finalize(JSContext *cx, JSObject *obj) { @@ -1401,7 +1381,7 @@ JS_PUBLIC_DATA(Class) js_CallClass = { PropertyStub, /* setProperty */ JS_EnumerateStub, (JSResolveOp)call_resolve, - NULL, /* convert */ + NULL, /* convert: Leave it NULL so we notice if calls ever escape */ NULL, /* finalize */ NULL, /* reserved0 */ NULL, /* checkAccess */ @@ -1623,8 +1603,6 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) return true; } -namespace { - struct LazyFunctionDataProp { uint16 atomOffset; int8 tinyid; @@ -1638,19 +1616,17 @@ struct PoisonPillProp { /* NB: no sentinels at ends -- use JS_ARRAY_LENGTH to bound loops. */ -const LazyFunctionDataProp lazyFunctionDataProps[] = { +static const LazyFunctionDataProp lazyFunctionDataProps[] = { {ATOM_OFFSET(arity), FUN_ARITY, JSPROP_PERMANENT|JSPROP_READONLY}, {ATOM_OFFSET(name), FUN_NAME, JSPROP_PERMANENT|JSPROP_READONLY}, }; /* Properties censored into [[ThrowTypeError]] in strict mode. */ -const PoisonPillProp poisonPillProps[] = { +static const PoisonPillProp poisonPillProps[] = { {ATOM_OFFSET(arguments), FUN_ARGUMENTS }, {ATOM_OFFSET(caller), FUN_CALLER }, }; -} - static JSBool fun_enumerate(JSContext *cx, JSObject *obj) { @@ -2250,8 +2226,6 @@ js_fun_call(JSContext *cx, uintN argc, Value *vp) return ok; } -namespace { - struct STATIC_SKIP_INFERENCE CopyNonHoleArgs { CopyNonHoleArgs(JSObject *aobj, Value *dst) : aobj(aobj), dst(dst) {} @@ -2266,8 +2240,6 @@ struct STATIC_SKIP_INFERENCE CopyNonHoleArgs } }; -} - /* ES5 15.3.4.3 */ JSBool js_fun_apply(JSContext *cx, uintN argc, Value *vp) @@ -2372,11 +2344,8 @@ js_fun_apply(JSContext *cx, uintN argc, Value *vp) return true; } -namespace { - -JSBool +static JSBool CallOrConstructBoundFunction(JSContext *cx, uintN argc, Value *vp); -} inline bool JSObject::initBoundFunction(JSContext *cx, const Value &thisArg, @@ -2436,10 +2405,8 @@ JSObject::getBoundFunctionArguments(uintN &argslen) const return getSlots() + FUN_CLASS_RESERVED_SLOTS; } -namespace { - /* ES5 15.3.4.5.1 and 15.3.4.5.2. */ -JSBool +static JSBool CallOrConstructBoundFunction(JSContext *cx, uintN argc, Value *vp) { JSObject *obj = &vp[0].toObject(); @@ -2487,7 +2454,7 @@ CallOrConstructBoundFunction(JSContext *cx, uintN argc, Value *vp) } /* ES5 15.3.4.5. */ -JSBool +static JSBool fun_bind(JSContext *cx, uintN argc, Value *vp) { /* Step 1. */ @@ -2546,8 +2513,6 @@ fun_bind(JSContext *cx, uintN argc, Value *vp) return true; } -} - static JSFunctionSpec function_methods[] = { #if JS_HAS_TOSOURCE JS_FN(js_toSource_str, fun_toSource, 0,0), @@ -2778,9 +2743,7 @@ Function(JSContext *cx, uintN argc, Value *vp) filename, lineno); } -namespace { - -JSBool +static JSBool ThrowTypeError(JSContext *cx, uintN argc, Value *vp) { JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL, @@ -2788,8 +2751,6 @@ ThrowTypeError(JSContext *cx, uintN argc, Value *vp) return false; } -} - JSObject * js_InitFunctionClass(JSContext *cx, JSObject *obj) { diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 5363af249bb4..4bba5660856e 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -757,11 +757,11 @@ MarkConservativeStackRoots(JSTracer *trc) JSThread *thread = r.front().value; ConservativeGCThreadData *ctd = &thread->data.conservativeGC; if (ctd->hasStackToScan()) { - JS_ASSERT_IF(!thread->requestDepth, thread->suspendCount); + JS_ASSERT_IF(!thread->data.requestDepth, thread->suspendCount); MarkThreadDataConservatively(trc, &thread->data); } else { JS_ASSERT(!thread->suspendCount); - JS_ASSERT(thread->requestDepth <= ctd->requestThreshold); + JS_ASSERT(thread->data.requestDepth <= ctd->requestThreshold); } } #else @@ -795,8 +795,8 @@ RecordNativeStackTopForGC(JSContext *cx) #ifdef JS_THREADSAFE /* Record the stack top here only if we are called from a request. */ - JS_ASSERT(cx->thread->requestDepth >= ctd->requestThreshold); - if (cx->thread->requestDepth == ctd->requestThreshold) + JS_ASSERT(cx->thread->data.requestDepth >= ctd->requestThreshold); + if (cx->thread->data.requestDepth == ctd->requestThreshold) return; #endif ctd->recordStackTop(); @@ -1630,7 +1630,7 @@ MarkRuntime(JSTracer *trc) while (JSContext *acx = js_ContextIterator(rt, JS_TRUE, &iter)) { for (AutoGCRooter *gcr = acx->autoGCRooters; gcr; gcr = gcr->down) { #ifdef JS_THREADSAFE - JS_ASSERT_IF(!acx->thread->requestDepth, acx->thread->suspendCount); + JS_ASSERT_IF(!acx->thread->data.requestDepth, acx->thread->suspendCount); #endif JS_ASSERT(JS_THREAD_DATA(acx)->conservativeGC.hasStackToScan()); void *thing; @@ -2337,7 +2337,7 @@ LetOtherGCFinish(JSContext *cx) JS_ASSERT(rt->gcThread); JS_ASSERT(cx->thread != rt->gcThread); - size_t requestDebit = cx->thread->requestDepth ? 1 : 0; + size_t requestDebit = cx->thread->data.requestDepth ? 1 : 0; JS_ASSERT(requestDebit <= rt->requestCount); #ifdef JS_TRACER JS_ASSERT_IF(requestDebit == 0, !JS_ON_TRACE(cx)); @@ -2359,10 +2359,6 @@ LetOtherGCFinish(JSContext *cx) JS_NOTIFY_REQUEST_DONE(rt); } - /* See comments before another call to js_ShareWaitingTitles below. */ - cx->thread->gcWaiting = true; - js_ShareWaitingTitles(cx); - /* * Check that we did not release the GC lock above and let the GC to * finish before we wait. @@ -2379,7 +2375,6 @@ LetOtherGCFinish(JSContext *cx) JS_AWAIT_GC_DONE(rt); } while (rt->gcThread); - cx->thread->gcWaiting = false; rt->requestCount += requestDebit; } @@ -2431,7 +2426,7 @@ AutoGCSession::AutoGCSession(JSContext *cx) for (JSThread::Map::Range r = rt->threads.all(); !r.empty(); r.popFront()) { JSThread *thread = r.front().value; if (thread != cx->thread) - thread->data.triggerOperationCallback(); + thread->data.triggerOperationCallback(rt); } /* @@ -2440,23 +2435,14 @@ AutoGCSession::AutoGCSession(JSContext *cx) * JS_NOTIFY_REQUEST_DONE, which will wake us up, is only called on * rt->requestCount transitions to 0. */ - size_t requestDebit = cx->thread->requestDepth ? 1 : 0; + size_t requestDebit = cx->thread->data.requestDepth ? 1 : 0; JS_ASSERT(requestDebit <= rt->requestCount); if (requestDebit != rt->requestCount) { rt->requestCount -= requestDebit; - /* - * Share any title that is owned by the GC thread before we wait, to - * avoid a deadlock with ClaimTitle. We also set the gcWaiting flag so - * that ClaimTitle can claim the title ownership from the GC thread if - * that function is called while the GC is waiting. - */ - cx->thread->gcWaiting = true; - js_ShareWaitingTitles(cx); do { JS_AWAIT_REQUEST_DONE(rt); } while (rt->requestCount > 0); - cx->thread->gcWaiting = false; rt->requestCount += requestDebit; } @@ -2620,7 +2606,7 @@ SetProtoCheckingForCycles(JSContext *cx, JSObject *obj, JSObject *proto) * request. */ #ifdef JS_THREADSAFE - JS_ASSERT(cx->thread->requestDepth); + JS_ASSERT(cx->thread->data.requestDepth); /* * This is only necessary if AutoGCSession below would wait for GC to diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 08daa2d38eed..1f8ae4f2bbcc 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -82,6 +82,7 @@ #include "jscntxtinlines.h" #include "jsinterpinlines.h" #include "jsobjinlines.h" +#include "jsprobes.h" #include "jspropertycacheinlines.h" #include "jsscopeinlines.h" #include "jsscriptinlines.h" @@ -1024,10 +1025,6 @@ CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs, return true; if (obj2->isNative()) { oldAttrs = ((Shape *) prop)->attributes(); - - /* If our caller doesn't want prop, unlock obj2. */ - if (!propp) - JS_UNLOCK_OBJ(cx, obj2); } else { if (!obj2->getAttributes(cx, id, &oldAttrs)) return false; @@ -1077,8 +1074,6 @@ CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs, if (!(oldAttrs & JSPROP_PERMANENT)) return JS_TRUE; } - if (prop) - obj2->dropProperty(cx, prop); report = JSREPORT_ERROR; isFunction = (oldAttrs & (JSPROP_GETTER | JSPROP_SETTER)) != 0; @@ -1478,17 +1473,17 @@ js::GetUpvar(JSContext *cx, uintN closureLevel, UpvarCookie cookie) #ifdef DEBUG JS_STATIC_INTERPRET JS_REQUIRES_STACK void -js_TraceOpcode(JSContext *cx) +js_LogOpcode(JSContext *cx) { - FILE *tracefp; + FILE *logfp; JSStackFrame *fp; JSFrameRegs *regs; intN ndefs, n, nuses; JSString *str; JSOp op; - tracefp = (FILE *) cx->tracefp; - JS_ASSERT(tracefp); + logfp = (FILE *) cx->logfp; + JS_ASSERT(logfp); fp = cx->fp(); regs = cx->regs; @@ -1496,10 +1491,10 @@ js_TraceOpcode(JSContext *cx) * Operations in prologues don't produce interesting values, and * js_DecompileValueGenerator isn't set up to handle them anyway. */ - if (cx->tracePrevPc && regs->pc >= fp->script()->main) { - JSOp tracePrevOp = JSOp(*cx->tracePrevPc); - ndefs = js_GetStackDefs(cx, &js_CodeSpec[tracePrevOp], tracePrevOp, - fp->script(), cx->tracePrevPc); + if (cx->logPrevPc && regs->pc >= fp->script()->main) { + JSOp logPrevOp = JSOp(*cx->logPrevPc); + ndefs = js_GetStackDefs(cx, &js_CodeSpec[logPrevOp], logPrevOp, + fp->script(), cx->logPrevPc); /* * If there aren't that many elements on the stack, then we have @@ -1511,7 +1506,7 @@ js_TraceOpcode(JSContext *cx) for (n = -ndefs; n < 0; n++) { char *bytes = DecompileValueGenerator(cx, n, regs->sp[n], NULL); if (bytes) { - fprintf(tracefp, "%s %s", + fprintf(logfp, "%s %s", (n == -ndefs) ? " output:" : ",", bytes); cx->free(bytes); @@ -1519,35 +1514,43 @@ js_TraceOpcode(JSContext *cx) JS_ClearPendingException(cx); } } - fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - fp->base())); + fprintf(logfp, " @ %u\n", (uintN) (regs->sp - fp->base())); } - fprintf(tracefp, " stack: "); + fprintf(logfp, " stack: "); for (Value *siter = fp->base(); siter < regs->sp; siter++) { - str = js_ValueToString(cx, *siter); - if (!str) { - fputs("", tracefp); + if (siter->isObject() && siter->toObject().getClass() == &js_CallClass) { + /* + * Call objects have NULL convert ops so that we catch cases + * where they escape. So js_ValueToString doesn't work on them. + */ + fputs("", logfp); } else { - JS_ClearPendingException(cx); - js_FileEscapedString(tracefp, str, 0); + str = js_ValueToString(cx, *siter); + if (!str) { + fputs("", logfp); + } else { + JS_ClearPendingException(cx); + js_FileEscapedString(logfp, str, 0); + } } - fputc(' ', tracefp); + fputc(' ', logfp); } - fputc('\n', tracefp); + fputc('\n', logfp); } - fprintf(tracefp, "%4u: ", + fprintf(logfp, "%4u: ", js_PCToLineNumber(cx, fp->script(), fp->hasImacropc() ? fp->imacropc() : regs->pc)); js_Disassemble1(cx, fp->script(), regs->pc, regs->pc - fp->script()->code, - JS_FALSE, tracefp); + JS_FALSE, logfp); op = (JSOp) *regs->pc; nuses = js_GetStackUses(&js_CodeSpec[op], op, regs->pc); if (nuses != 0) { for (n = -nuses; n < 0; n++) { char *bytes = DecompileValueGenerator(cx, n, regs->sp[n], NULL); if (bytes) { - fprintf(tracefp, "%s %s", + fprintf(logfp, "%s %s", (n == -nuses) ? " inputs:" : ",", bytes); cx->free(bytes); @@ -1555,12 +1558,12 @@ js_TraceOpcode(JSContext *cx) JS_ClearPendingException(cx); } } - fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - fp->base())); + fprintf(logfp, " @ %u\n", (uintN) (regs->sp - fp->base())); } - cx->tracePrevPc = regs->pc; + cx->logPrevPc = regs->pc; - /* It's nice to have complete traces when debugging a crash. */ - fflush(tracefp); + /* It's nice to have complete logs when debugging a crash. */ + fflush(logfp); } #endif /* DEBUG */ @@ -2018,10 +2021,8 @@ AssertValidPropertyCacheHit(JSContext *cx, JSScript *script, JSFrameRegs& regs, } if (!ok) return false; - if (cx->runtime->gcNumber != sample || entry->vshape() != pobj->shape()) { - pobj->dropProperty(cx, prop); + if (cx->runtime->gcNumber != sample || entry->vshape() != pobj->shape()) return true; - } JS_ASSERT(prop); JS_ASSERT(pobj == found); @@ -2032,7 +2033,7 @@ AssertValidPropertyCacheHit(JSContext *cx, JSScript *script, JSFrameRegs& regs, } else if (entry->vword.isShape()) { JS_ASSERT(entry->vword.toShape() == shape); JS_ASSERT_IF(shape->isMethod(), - &shape->methodObject() == &pobj->lockedGetSlot(shape->slot).toObject()); + &shape->methodObject() == &pobj->nativeGetSlot(shape->slot).toObject()); } else { Value v; JS_ASSERT(entry->vword.isFunObj()); @@ -2040,7 +2041,7 @@ AssertValidPropertyCacheHit(JSContext *cx, JSScript *script, JSFrameRegs& regs, JS_ASSERT(pobj->brandedOrHasMethodBarrier()); JS_ASSERT(shape->hasDefaultGetterOrIsMethod()); JS_ASSERT(pobj->containsSlot(shape->slot)); - v = pobj->lockedGetSlot(shape->slot); + v = pobj->nativeGetSlot(shape->slot); JS_ASSERT(&entry->vword.toFunObj() == &v.toObject()); if (shape->isMethod()) { @@ -2049,7 +2050,6 @@ AssertValidPropertyCacheHit(JSContext *cx, JSScript *script, JSFrameRegs& regs, } } - pobj->dropProperty(cx, prop); return true; } @@ -2187,13 +2187,13 @@ Interpret(JSContext *cx, JSStackFrame *entryFrame, uintN inlineCallCount, JSInte * expect from looking at the code. (We do omit POPs after SETs; * unfortunate, but not worth fixing.) */ -# define TRACE_OPCODE(OP) JS_BEGIN_MACRO \ - if (JS_UNLIKELY(cx->tracefp != NULL) && \ +# define LOG_OPCODE(OP) JS_BEGIN_MACRO \ + if (JS_UNLIKELY(cx->logfp != NULL) && \ (OP) == *regs.pc) \ - js_TraceOpcode(cx); \ + js_LogOpcode(cx); \ JS_END_MACRO # else -# define TRACE_OPCODE(OP) ((void) 0) +# define LOG_OPCODE(OP) ((void) 0) # endif /* @@ -2238,7 +2238,7 @@ Interpret(JSContext *cx, JSStackFrame *entryFrame, uintN inlineCallCount, JSInte DO_OP(); \ JS_END_MACRO -# define BEGIN_CASE(OP) L_##OP: TRACE_OPCODE(OP); CHECK_RECORDER(); +# define BEGIN_CASE(OP) L_##OP: LOG_OPCODE(OP); CHECK_RECORDER(); # define END_CASE(OP) DO_NEXT_OP(OP##_LENGTH); # define END_VARLEN_CASE DO_NEXT_OP(len); # define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP) \ @@ -2386,6 +2386,7 @@ Interpret(JSContext *cx, JSStackFrame *entryFrame, uintN inlineCallCount, JSInte #ifndef TRACE_RECORDER #define TRACE_RECORDER(cx) (false) +#define TRACE_PROFILER(cx) (false) #endif #if defined(JS_TRACER) && defined(JS_METHODJIT) @@ -2410,7 +2411,7 @@ Interpret(JSContext *cx, JSStackFrame *entryFrame, uintN inlineCallCount, JSInte if ((n) <= 0) { \ CHECK_BRANCH(); \ if (op == JSOP_NOTRACE) { \ - if (TRACE_RECORDER(cx)) { \ + if (TRACE_RECORDER(cx) || TRACE_PROFILER(cx)) { \ MONITOR_BRANCH(); \ op = (JSOp) *regs.pc; \ } \ @@ -2504,6 +2505,8 @@ Interpret(JSContext *cx, JSStackFrame *entryFrame, uintN inlineCallCount, JSInte if (interpMode == JSINTERP_RECORD) { JS_ASSERT(TRACE_RECORDER(cx)); ENABLE_INTERRUPTS(); + } else if (interpMode == JSINTERP_PROFILE) { + ENABLE_INTERRUPTS(); } else if (TRACE_RECORDER(cx)) { AbortRecording(cx, "attempt to reenter interpreter while recording"); } @@ -2561,7 +2564,7 @@ Interpret(JSContext *cx, JSStackFrame *entryFrame, uintN inlineCallCount, JSInte do_op: CHECK_RECORDER(); - TRACE_OPCODE(op); + LOG_OPCODE(op); switchOp = intN(op) | switchMask; do_switch: switch (switchOp) { @@ -2602,6 +2605,20 @@ Interpret(JSContext *cx, JSStackFrame *entryFrame, uintN inlineCallCount, JSInte } #ifdef JS_TRACER +#ifdef JS_METHODJIT + if (LoopProfile *prof = TRACE_PROFILER(cx)) { + LoopProfile::ProfileAction act = prof->profileOperation(cx, op); + switch (act) { + case LoopProfile::ProfComplete: + leaveOnSafePoint = true; + LEAVE_ON_SAFE_POINT(); + break; + default: + moreInterrupts = true; + break; + } + } +#endif if (TraceRecorder* tr = TRACE_RECORDER(cx)) { AbortableRecordingStatus status = tr->monitorRecording(op); JS_ASSERT_IF(cx->throwing, status == ARECORD_ERROR); @@ -2983,8 +3000,6 @@ BEGIN_CASE(JSOP_IN) if (!obj->lookupProperty(cx, id, &obj2, &prop)) goto error; bool cond = prop != NULL; - if (prop) - obj2->dropProperty(cx, prop); TRY_BRANCH_AFTER_COND(cond, 2); regs.sp--; regs.sp[-1].setBoolean(cond); @@ -3059,8 +3074,7 @@ BEGIN_CASE(JSOP_FORNAME) JSProperty *prop; if (!js_FindProperty(cx, id, &obj, &obj2, &prop)) goto error; - if (prop) - obj2->dropProperty(cx, prop); + { AutoValueRooter tvr(cx); JS_ASSERT(regs.sp[-1].isObject()); @@ -3150,7 +3164,7 @@ END_CASE(JSOP_PICK) JS_ASSERT((shape)->slot != SHAPE_INVALID_SLOT || \ !shape->hasDefaultSetter()); \ if (((shape)->slot != SHAPE_INVALID_SLOT)) \ - *(vp) = (pobj)->lockedGetSlot((shape)->slot); \ + *(vp) = (pobj)->nativeGetSlot((shape)->slot); \ else \ (vp)->setUndefined(); \ } else { \ @@ -3166,7 +3180,7 @@ END_CASE(JSOP_PICK) (shape)->slot != SHAPE_INVALID_SLOT && \ !(obj)->brandedOrHasMethodBarrier()) { \ /* Fast path for, e.g., plain Object instance properties. */ \ - (obj)->lockedSetSlot((shape)->slot, *vp); \ + (obj)->nativeSetSlot((shape)->slot, *vp); \ } else { \ if (!js_NativeSet(cx, obj, shape, false, vp)) \ goto error; \ @@ -3739,7 +3753,6 @@ BEGIN_CASE(JSOP_DELNAME) /* ECMA says to return true if name is undefined or inherited. */ PUSH_BOOLEAN(true); if (prop) { - obj2->dropProperty(cx, prop); if (!obj->deleteProperty(cx, id, ®s.sp[-1], false)) goto error; } @@ -3848,8 +3861,7 @@ BEGIN_CASE(JSOP_GNAMEDEC) ASSERT_VALID_PROPERTY_CACHE_HIT(0, obj, obj2, entry); if (obj == obj2 && entry->vword.isSlot()) { uint32 slot = entry->vword.toSlot(); - JS_ASSERT(obj->containsSlot(slot)); - Value &rref = obj->getSlotRef(slot); + Value &rref = obj->nativeGetSlotRef(slot); int32_t tmp; if (JS_LIKELY(rref.isInt32() && CanIncDecWithoutOverflow(tmp = rref.toInt32()))) { int32_t inc = tmp + ((js_CodeSpec[op].format & JOF_INC) ? 1 : -1); @@ -3872,7 +3884,6 @@ BEGIN_CASE(JSOP_GNAMEDEC) atomNotDefined = atom; goto atom_not_defined; } - obj2->dropProperty(cx, prop); } do_incop: @@ -4088,8 +4099,7 @@ BEGIN_CASE(JSOP_GETXPROP) rval.setObject(entry->vword.toFunObj()); } else if (entry->vword.isSlot()) { uint32 slot = entry->vword.toSlot(); - JS_ASSERT(obj2->containsSlot(slot)); - rval = obj2->lockedGetSlot(slot); + rval = obj2->nativeGetSlot(slot); } else { JS_ASSERT(entry->vword.isShape()); const Shape *shape = entry->vword.toShape(); @@ -4184,8 +4194,7 @@ BEGIN_CASE(JSOP_CALLPROP) rval.setObject(entry->vword.toFunObj()); } else if (entry->vword.isSlot()) { uint32 slot = entry->vword.toSlot(); - JS_ASSERT(obj2->containsSlot(slot)); - rval = obj2->lockedGetSlot(slot); + rval = obj2->nativeGetSlot(slot); } else { JS_ASSERT(entry->vword.isShape()); const Shape *shape = entry->vword.toShape(); @@ -4325,15 +4334,7 @@ BEGIN_CASE(JSOP_SETMETHOD) JS_ASSERT(obj->isExtensible()); if (obj->nativeEmpty()) { - /* - * We check that cx owns obj here and will continue to own - * it after ensureClassReservedSlotsForEmptyObject returns - * so we can continue to skip JS_UNLOCK_OBJ calls. - */ - JS_ASSERT(CX_OWNS_OBJECT_TITLE(cx, obj)); - bool ok = obj->ensureClassReservedSlotsForEmptyObject(cx); - JS_ASSERT(CX_OWNS_OBJECT_TITLE(cx, obj)); - if (!ok) + if (!obj->ensureClassReservedSlotsForEmptyObject(cx)) goto error; } @@ -4370,7 +4371,7 @@ BEGIN_CASE(JSOP_SETMETHOD) * might contain a method of a branded shape. */ TRACE_2(SetPropHit, entry, shape); - obj->lockedSetSlot(slot, rval); + obj->nativeSetSlot(slot, rval); /* * Purge the property cache of the id we may have just @@ -4563,7 +4564,7 @@ BEGIN_CASE(JSOP_ENUMELEM) } END_CASE(JSOP_ENUMELEM) -{ +{ // begin block around calling opcodes JSFunction *newfun; JSObject *callee; uint32 flags; @@ -4608,8 +4609,28 @@ BEGIN_CASE(JSOP_NEW) } END_CASE(JSOP_NEW) -BEGIN_CASE(JSOP_CALL) BEGIN_CASE(JSOP_EVAL) +{ + argc = GET_ARGC(regs.pc); + vp = regs.sp - (argc + 2); + + if (!IsFunctionObject(*vp, &callee)) + goto call_using_invoke; + + newfun = callee->getFunctionPrivate(); + if (!IsBuiltinEvalFunction(newfun)) + goto not_direct_eval; + + Probes::enterJSFun(cx, newfun); + JSBool ok = CallJSNative(cx, newfun->u.n.native, argc, vp); + Probes::exitJSFun(cx, newfun); + regs.sp = vp + 1; + if (!ok) + goto error; +} +END_CASE(JSOP_EVAL) + +BEGIN_CASE(JSOP_CALL) BEGIN_CASE(JSOP_APPLY) { argc = GET_ARGC(regs.pc); @@ -4618,6 +4639,7 @@ BEGIN_CASE(JSOP_APPLY) if (IsFunctionObject(*vp, &callee)) { newfun = callee->getFunctionPrivate(); + not_direct_eval: /* Clear frame flags since this is not a constructor call. */ flags = 0; if (newfun->isInterpreted()) @@ -4673,7 +4695,7 @@ BEGIN_CASE(JSOP_APPLY) mjit::CompileStatus status = mjit::CanMethodJIT(cx, script, regs.fp); if (status == mjit::Compile_Error) goto error; - if (!TRACE_RECORDER(cx) && status == mjit::Compile_Okay) { + if (!TRACE_RECORDER(cx) && !TRACE_PROFILER(cx) && status == mjit::Compile_Okay) { interpReturnOK = mjit::JaegerShot(cx); CHECK_INTERRUPT_HANDLER(); goto jit_return; @@ -4700,6 +4722,7 @@ BEGIN_CASE(JSOP_APPLY) goto end_call; } + call_using_invoke: bool ok; ok = Invoke(cx, InvokeArgsAlreadyOnTheStack(vp, argc), 0); regs.sp = vp + 1; @@ -4712,7 +4735,8 @@ BEGIN_CASE(JSOP_APPLY) end_call:; } END_CASE(JSOP_CALL) -} + +} // end block around calling opcodes BEGIN_CASE(JSOP_SETCALL) { @@ -4766,8 +4790,7 @@ BEGIN_CASE(JSOP_CALLNAME) PUSH_OBJECT(entry->vword.toFunObj()); } else if (entry->vword.isSlot()) { uintN slot = entry->vword.toSlot(); - JS_ASSERT(obj2->containsSlot(slot)); - PUSH_COPY(obj2->lockedGetSlot(slot)); + PUSH_COPY(obj2->nativeGetSlot(slot)); } else { JS_ASSERT(entry->vword.isShape()); shape = entry->vword.toShape(); @@ -4812,7 +4835,6 @@ BEGIN_CASE(JSOP_CALLNAME) /* Take the slow path if prop was not found in a native object. */ if (!obj->isNative() || !obj2->isNative()) { - obj2->dropProperty(cx, prop); if (!obj->getProperty(cx, id, &rval)) goto error; } else { @@ -4821,7 +4843,6 @@ BEGIN_CASE(JSOP_CALLNAME) if (normalized->getClass() == &js_WithClass && !shape->hasDefaultGetter()) normalized = js_UnwrapWithObject(cx, normalized); NATIVE_GET(cx, normalized, obj2, shape, JSGET_METHOD_BARRIER, &rval); - JS_UNLOCK_OBJ(cx, obj2); } PUSH_COPY(rval); @@ -5234,7 +5255,6 @@ BEGIN_CASE(JSOP_CALLUPVAR_DBG) } /* Minimize footprint with generic code instead of NATIVE_GET. */ - obj2->dropProperty(cx, prop); Value *vp = regs.sp; PUSH_NULL(); if (!obj->getProperty(cx, id, vp)) @@ -5278,38 +5298,22 @@ BEGIN_CASE(JSOP_FORGLOBAL) if (!IteratorNext(cx, ®s.sp[-1].toObject(), &rval)) goto error; PUSH_COPY(rval); - uint32 slot = GET_SLOTNO(regs.pc); - slot = script->getGlobalSlot(slot); + uint32 slot = script->getGlobalSlot(GET_SLOTNO(regs.pc)); JSObject *obj = regs.fp->scopeChain().getGlobal(); - JS_ASSERT(obj->containsSlot(slot)); - JS_LOCK_OBJ(cx, obj); - { - if (!obj->methodWriteBarrier(cx, slot, rval)) { - JS_UNLOCK_OBJ(cx, obj); - goto error; - } - obj->lockedSetSlot(slot, rval); - JS_UNLOCK_OBJ(cx, obj); - } + if (!obj->methodWriteBarrier(cx, slot, rval)) + goto error; + obj->nativeSetSlot(slot, rval); regs.sp--; } END_CASE(JSOP_FORGLOBAL) BEGIN_CASE(JSOP_SETGLOBAL) { - uint32 slot = GET_SLOTNO(regs.pc); - slot = script->getGlobalSlot(slot); + uint32 slot = script->getGlobalSlot(GET_SLOTNO(regs.pc)); JSObject *obj = regs.fp->scopeChain().getGlobal(); - JS_ASSERT(obj->containsSlot(slot)); - { - JS_LOCK_OBJ(cx, obj); - if (!obj->methodWriteBarrier(cx, slot, regs.sp[-1])) { - JS_UNLOCK_OBJ(cx, obj); - goto error; - } - obj->lockedSetSlot(slot, regs.sp[-1]); - JS_UNLOCK_OBJ(cx, obj); - } + if (!obj->methodWriteBarrier(cx, slot, regs.sp[-1])) + goto error; + obj->nativeSetSlot(slot, regs.sp[-1]); } END_SET_CASE(JSOP_SETGLOBAL) @@ -5352,8 +5356,6 @@ BEGIN_CASE(JSOP_DEFVAR) JS_ASSERT(prop); obj2 = obj; } - - obj2->dropProperty(cx, prop); } END_CASE(JSOP_DEFVAR) @@ -5464,7 +5466,6 @@ BEGIN_CASE(JSOP_DEFFUN) if (oldAttrs & JSPROP_PERMANENT) doSet = true; } - pobj->dropProperty(cx, prop); } Value rval = ObjectValue(*obj); @@ -5925,8 +5926,7 @@ BEGIN_CASE(JSOP_INITMETHOD) */ PropertyCacheEntry *entry; const Shape *shape; - if (CX_OWNS_OBJECT_TITLE(cx, obj) && - JS_PROPERTY_CACHE(cx).testForInit(rt, regs.pc, obj, &shape, &entry) && + if (JS_PROPERTY_CACHE(cx).testForInit(rt, regs.pc, obj, &shape, &entry) && shape->hasDefaultSetter() && shape->previous() == obj->lastProperty()) { @@ -5954,7 +5954,7 @@ BEGIN_CASE(JSOP_INITMETHOD) * contain a method of a branded shape. */ TRACE_2(SetPropHit, entry, shape); - obj->lockedSetSlot(slot, rval); + obj->nativeSetSlot(slot, rval); } else { PCMETER(JS_PROPERTY_CACHE(cx).inipcmisses++); @@ -6152,6 +6152,12 @@ BEGIN_CASE(JSOP_EXCEPTION) JS_ASSERT(cx->throwing); PUSH_COPY(cx->exception); cx->throwing = JS_FALSE; +#if defined(JS_TRACER) && defined(JS_METHODJIT) + if (interpMode == JSINTERP_PROFILE) { + leaveOnSafePoint = true; + LEAVE_ON_SAFE_POINT(); + } +#endif CHECK_BRANCH(); END_CASE(JSOP_EXCEPTION) @@ -6750,6 +6756,10 @@ END_CASE(JSOP_ARRAYPUSH) */ if (TRACE_RECORDER(cx)) AbortRecording(cx, "error or exception while recording"); +# ifdef JS_METHODJIT + if (TRACE_PROFILER(cx)) + AbortProfiling(cx); +# endif #endif if (!cx->throwing) { @@ -6904,7 +6914,7 @@ END_CASE(JSOP_ARRAYPUSH) JS_ASSERT(regs.sp == regs.fp->base()); #ifdef DEBUG - cx->tracePrevPc = NULL; + cx->logPrevPc = NULL; #endif if (entryFrame != regs.fp) @@ -6931,6 +6941,10 @@ END_CASE(JSOP_ARRAYPUSH) JS_ASSERT_IF(interpReturnOK && interpMode == JSINTERP_RECORD, !TRACE_RECORDER(cx)); if (TRACE_RECORDER(cx)) AbortRecording(cx, "recording out of Interpret"); +# ifdef JS_METHODJIT + if (TRACE_PROFILER(cx)) + AbortProfiling(cx); +# endif #endif JS_ASSERT_IF(!regs.fp->isGeneratorFrame(), !js_IsActiveWithOrBlock(cx, ®s.fp->scopeChain(), 0)); diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index 228497529099..cdf955c96c1f 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -63,7 +63,8 @@ enum JSInterpMode { JSINTERP_NORMAL = 0, /* Interpreter is running normally. */ JSINTERP_RECORD = 1, /* interpreter has been started to record/run traces */ - JSINTERP_SAFEPOINT = 2 /* interpreter should leave on a method JIT safe point */ + JSINTERP_SAFEPOINT = 2, /* interpreter should leave on a method JIT safe point */ + JSINTERP_PROFILE = 3 /* interpreter should profile a loop */ }; /* Flags used in JSStackFrame::flags_ */ @@ -1089,7 +1090,7 @@ js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, js::Value *vp, js::Value *vp2); * previous opcode. */ extern JS_REQUIRES_STACK void -js_TraceOpcode(JSContext *cx); +js_LogOpcode(JSContext *cx); /* * JS_OPMETER helper functions. diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 6315b6c52b65..5a660aa4621a 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -254,8 +254,6 @@ static bool EnumerateNativeProperties(JSContext *cx, JSObject *obj, JSObject *pobj, uintN flags, IdSet &ht, typename EnumPolicy::ResultVector *props) { - JS_LOCK_OBJ(cx, pobj); - size_t initialLength = props->length(); /* Collect all unique properties from this object's scope. */ @@ -272,8 +270,6 @@ EnumerateNativeProperties(JSContext *cx, JSObject *obj, JSObject *pobj, uintN fl } Reverse(props->begin() + initialLength, props->end()); - - JS_UNLOCK_OBJ(cx, pobj); return true; } @@ -628,6 +624,16 @@ GetIterator(JSContext *cx, JSObject *obj, uintN flags, Value *vp) bool keysOnly = (flags == JSITER_ENUMERATE); if (obj) { + /* Enumerate Iterator.prototype directly. */ + JSIteratorOp op = obj->getClass()->ext.iteratorObject; + if (op && (obj->getClass() != &js_IteratorClass || obj->getNativeIterator())) { + JSObject *iterobj = op(cx, obj, !(flags & JSITER_FOREACH)); + if (!iterobj) + return false; + vp->setObject(*iterobj); + return true; + } + if (keysOnly) { /* * Check to see if this is the same as the most recent object which @@ -817,8 +823,7 @@ js_ValueToIterator(JSContext *cx, uintN flags, Value *vp) if ((flags & JSITER_ENUMERATE)) { if (!js_ValueToObjectOrNull(cx, *vp, &obj)) return false; - if (!obj) - return GetIterator(cx, NULL, flags, vp); + /* fall through */ } else { obj = js_ValueToNonNullObject(cx, *vp); if (!obj) @@ -826,18 +831,6 @@ js_ValueToIterator(JSContext *cx, uintN flags, Value *vp) } } - AutoObjectRooter tvr(cx, obj); - - /* Enumerate Iterator.prototype directly. */ - JSIteratorOp op = obj->getClass()->ext.iteratorObject; - if (op && (obj->getClass() != &js_IteratorClass || obj->getNativeIterator())) { - JSObject *iterobj = op(cx, obj, !(flags & JSITER_FOREACH)); - if (!iterobj) - return false; - vp->setObject(*iterobj); - return true; - } - return GetIterator(cx, obj, flags, vp); } @@ -922,12 +915,11 @@ SuppressDeletedPropertyHelper(JSContext *cx, JSObject *obj, IdPredicate predicat return false; if (prop) { uintN attrs; - if (obj2.object()->isNative()) { + if (obj2.object()->isNative()) attrs = ((Shape *) prop)->attributes(); - JS_UNLOCK_OBJ(cx, obj2.object()); - } else if (!obj2.object()->getAttributes(cx, *idp, &attrs)) { + else if (!obj2.object()->getAttributes(cx, *idp, &attrs)) return false; - } + if (attrs & JSPROP_ENUMERATE) continue; } @@ -1089,7 +1081,8 @@ stopiter_hasInstance(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp) Class js_StopIterationClass = { js_StopIteration_str, - JSCLASS_HAS_CACHED_PROTO(JSProto_StopIteration), + JSCLASS_HAS_CACHED_PROTO(JSProto_StopIteration) | + JSCLASS_FREEZE_PROTO, PropertyStub, /* addProperty */ PropertyStub, /* delProperty */ PropertyStub, /* getProperty */ diff --git a/js/src/jslock.cpp b/js/src/jslock.cpp index a29f883fe8f7..e9f505e21fc7 100644 --- a/js/src/jslock.cpp +++ b/js/src/jslock.cpp @@ -359,443 +359,6 @@ js_FinishLock(JSThinLock *tl) #endif } -#ifdef DEBUG_SCOPE_COUNT - -#include -#include "jsdhash.h" - -static FILE *logfp = NULL; -static JSDHashTable logtbl; - -typedef struct logentry { - JSDHashEntryStub stub; - char op; - const char *file; - int line; -} logentry; - -static void -logit(JSTitle *title, char op, const char *file, int line) -{ - logentry *entry; - - if (!logfp) { - logfp = fopen("/tmp/scope.log", "w"); - if (!logfp) - return; - setvbuf(logfp, NULL, _IONBF, 0); - } - fprintf(logfp, "%p %d %c %s %d\n", title, title->u.count, op, file, line); - - if (!logtbl.entryStore && - !JS_DHashTableInit(&logtbl, JS_DHashGetStubOps(), NULL, - sizeof(logentry), 100)) { - return; - } - entry = (logentry *) JS_DHashTableOperate(&logtbl, title, JS_DHASH_ADD); - if (!entry) - return; - entry->stub.key = title; - entry->op = op; - entry->file = file; - entry->line = line; -} - -void -js_unlog_title(JSTitle *title) -{ - if (!logtbl.entryStore) - return; - (void) JS_DHashTableOperate(&logtbl, title, JS_DHASH_REMOVE); -} - -# define LOGIT(title,op) logit(title, op, __FILE__, __LINE__) - -#else - -# define LOGIT(title, op) /* nothing */ - -#endif /* DEBUG_SCOPE_COUNT */ - -/* - * Return true if we would deadlock waiting in ClaimTitle on - * rt->titleSharingDone until ownercx finishes its request and shares a title. - * - * (i) rt->gcLock held - */ -static bool -WillDeadlock(JSContext *ownercx, JSThread *thread) -{ - JS_ASSERT(CURRENT_THREAD_IS_ME(thread)); - JS_ASSERT(ownercx->thread != thread); - - for (;;) { - JS_ASSERT(ownercx->thread); - JS_ASSERT(ownercx->thread->requestDepth); - JSTitle *title = ownercx->thread->titleToShare; - if (!title || !title->ownercx) { - /* - * ownercx->thread doesn't wait or has just been notified that the - * title became shared. - */ - return false; - } - - /* - * ownercx->thread is waiting in ClaimTitle for a context from some - * thread to finish its request. If that thread is the current thread, - * we would deadlock. Otherwise we must recursively check if that - * thread waits for the current thread. - */ - if (title->ownercx->thread == thread) { - JS_RUNTIME_METER(ownercx->runtime, deadlocksAvoided); - return true; - } - ownercx = title->ownercx; - } -} - -static void -FinishSharingTitle(JSContext *cx, JSTitle *title); - -/* - * Make title multi-threaded, i.e. share its ownership among contexts in rt - * using a "thin" or (if necessary due to contention) "fat" lock. Called only - * from ClaimTitle, immediately below, when we detect deadlock were we to wait - * for title's lock, because its ownercx is waiting on a title owned by the - * calling cx. - * - * (i) rt->gcLock held - */ -static void -ShareTitle(JSContext *cx, JSTitle *title) -{ - JSRuntime *rt; - JSTitle **todop; - - rt = cx->runtime; - if (title->u.link) { - for (todop = &rt->titleSharingTodo; *todop != title; - todop = &(*todop)->u.link) { - JS_ASSERT(*todop != NO_TITLE_SHARING_TODO); - } - *todop = title->u.link; - title->u.link = NULL; /* null u.link for sanity ASAP */ - JS_NOTIFY_ALL_CONDVAR(rt->titleSharingDone); - } - FinishSharingTitle(cx, title); -} - -/* - * FinishSharingTitle is the tail part of ShareTitle, split out to become a - * subroutine of js_ShareWaitingTitles too. The bulk of the work here involves - * making mutable strings in the title's object's slots be immutable. We have - * to do this because such strings will soon be available to multiple threads, - * so their buffers can't be realloc'd any longer in js_ConcatStrings, and - * their members can't be modified by js_ConcatStrings, JSString::undepend, or - * MinimizeDependentStrings. - * - * The last bit of work done by this function nulls title->ownercx and updates - * rt->sharedTitles. - */ -static void -FinishSharingTitle(JSContext *cx, JSTitle *title) -{ - js_InitLock(&title->lock); - title->u.count = 0; /* NULL may not pun as 0 */ - - JSObject *obj = TITLE_TO_OBJECT(title); - if (obj) { - uint32 nslots = obj->slotSpan(); - for (uint32 i = 0; i != nslots; ++i) { - Value v = obj->getSlot(i); - if (v.isString() && - !js_MakeStringImmutable(cx, v.toString())) { - /* - * FIXME bug 363059: The following error recovery changes - * runtime execution semantics, arbitrarily and silently - * ignoring errors except out-of-memory, which should have been - * reported through JS_ReportOutOfMemory at this point. - */ - obj->setSlot(i, UndefinedValue()); - } - } - } - - title->ownercx = NULL; /* NB: set last, after lock init */ - JS_RUNTIME_METER(cx->runtime, sharedTitles); -} - -/* - * Given a title with apparently non-null ownercx different from cx, try to - * set ownercx to cx, claiming exclusive (single-threaded) ownership of title. - * If we claim ownership, return true. Otherwise, we wait for ownercx to be - * set to null (indicating that title is multi-threaded); or if waiting would - * deadlock, we set ownercx to null ourselves via ShareTitle. In any case, - * once ownercx is null we return false. - */ -static JSBool -ClaimTitle(JSTitle *title, JSContext *cx) -{ - JSRuntime *rt = cx->runtime; - JS_ASSERT_IF(!cx->thread->requestDepth, cx->thread == rt->gcThread && rt->gcRunning); - - JS_RUNTIME_METER(rt, claimAttempts); - AutoLockGC lock(rt); - - /* Reload in case ownercx went away while we blocked on the lock. */ - while (JSContext *ownercx = title->ownercx) { - /* - * Avoid selflock if ownercx is dead, or is not running a request, or - * has the same thread as cx, or cx->thread runs the GC (in which case - * all other requests must be suspended), or ownercx->thread runs a GC - * and the GC waits for all requests to finish. Set title->ownercx to - * cx so that the matching JS_UNLOCK_OBJ macro call will take the fast - * path around the corresponding js_UnlockObj function call. - * - * If title->u.link is non-null, title has already been inserted on - * the rt->titleSharingTodo list, because another thread's context - * already wanted to lock title while ownercx was running a request. - * That context must still be in request and cannot be dead. Moreover, - * the GC can not run at this moment as it must wait until all the - * titles are shared and the threads that want to lock them finish - * their requests. Thus we can claim the title if its thread matches - * ours. - */ - bool canClaim; - if (title->u.link) { - JS_ASSERT(js_ValidContextPointer(rt, ownercx)); - JS_ASSERT(ownercx->thread->requestDepth); - JS_ASSERT(!rt->gcRunning); - canClaim = (ownercx->thread == cx->thread); - } else { - canClaim = (!js_ValidContextPointer(rt, ownercx) || - !ownercx->thread || - !ownercx->thread->requestDepth || - cx->thread == ownercx->thread || - cx->thread == rt->gcThread || - ownercx->thread->gcWaiting); - } - if (canClaim) { - title->ownercx = cx; - JS_RUNTIME_METER(rt, claimedTitles); - return JS_TRUE; - } - - /* - * Avoid deadlock if title's owner thread is waiting on a title that - * the current thread owns, by revoking title's ownership. This - * approach to deadlock avoidance works because the engine never nests - * title locks. - * - * If cx->thread could hold locks on ownercx->thread->titleToShare, or - * if ownercx->thread could hold locks on title, we would need to keep - * reentrancy counts for all such "flyweight" (ownercx != NULL) locks, - * so that control would unwind properly once these locks became - * "thin" or "fat". The engine promotes a title from exclusive to - * shared access only when locking, never when holding or unlocking. - */ - if (WillDeadlock(ownercx, cx->thread)) { - ShareTitle(cx, title); - break; - } - - /* - * Thanks to the non-zero NO_TITLE_SHARING_TODO link terminator, we - * can decide whether title is on rt->titleSharingTodo with a single - * non-null test, and avoid double-insertion bugs. - */ - if (!title->u.link) { - title->u.link = rt->titleSharingTodo; - rt->titleSharingTodo = title; - } - - /* - * We know that some other thread's context owns title, which is now - * linked onto rt->titleSharingTodo, awaiting the end of that other - * thread's request. So it is safe to wait on rt->titleSharingDone. - * But before waiting, we force the operation callback for that other - * thread so it can quickly suspend. - */ - JS_THREAD_DATA(ownercx)->triggerOperationCallback(); - - JS_ASSERT(!cx->thread->titleToShare); - cx->thread->titleToShare = title; -#ifdef DEBUG - PRStatus stat = -#endif - PR_WaitCondVar(rt->titleSharingDone, PR_INTERVAL_NO_TIMEOUT); - JS_ASSERT(stat != PR_FAILURE); - cx->thread->titleToShare = NULL; - } - return JS_FALSE; -} - -void -js_ShareWaitingTitles(JSContext *cx) -{ - JSTitle *title, **todop; - bool shared; - - /* See whether cx has any single-threaded titles to start sharing. */ - todop = &cx->runtime->titleSharingTodo; - shared = false; - while ((title = *todop) != NO_TITLE_SHARING_TODO) { - if (title->ownercx->thread != cx->thread) { - todop = &title->u.link; - continue; - } - *todop = title->u.link; - title->u.link = NULL; /* null u.link for sanity ASAP */ - - FinishSharingTitle(cx, title); /* set ownercx = NULL */ - shared = true; - } - if (shared) - JS_NOTIFY_ALL_CONDVAR(cx->runtime->titleSharingDone); -} - -/* Exported to js.c, which calls it via OBJ_GET_* and JSVAL_IS_* macros. */ -JS_FRIEND_API(jsval) -js_GetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot) -{ - jsval v; -#ifndef NSPR_LOCK - JSThinLock *tl; - jsword me; -#endif - - OBJ_CHECK_SLOT(obj, slot); - - /* - * Native object locking is inlined here to optimize the single-threaded - * and contention-free multi-threaded cases. - */ - JS_ASSERT(obj->title.ownercx != cx); - JS_ASSERT(obj->containsSlot(slot)); - - /* - * Avoid locking if called from the GC. Also avoid locking a non-extensible - * object. If neither of those special cases applies, try to claim obj's - * flyweight lock from whatever context may have had it in an earlier - * request. - */ - if (CX_THREAD_IS_RUNNING_GC(cx) || - !obj->isExtensible() || - (obj->title.ownercx && ClaimTitle(&obj->title, cx))) { - return Jsvalify(obj->getSlot(slot)); - } - -#ifndef NSPR_LOCK - tl = &obj->title.lock; - me = CX_THINLOCK_ID(cx); - JS_ASSERT(CURRENT_THREAD_IS_ME(me)); - if (NativeCompareAndSwap(&tl->owner, 0, me)) { - /* - * Got the lock with one compare-and-swap. Even so, someone else may - * have mutated obj so it now has its own title lock, which would - * require either a restart from the top of this routine, or a thin - * lock release followed by fat lock acquisition. - */ - v = Jsvalify(obj->getSlot(slot)); - if (!NativeCompareAndSwap(&tl->owner, me, 0)) { - /* Assert that title locks never revert to flyweight. */ - JS_ASSERT(obj->title.ownercx != cx); - LOGIT(obj->title, '1'); - obj->title.u.count = 1; - js_UnlockObj(cx, obj); - } - return v; - } - if (Thin_RemoveWait(ReadWord(tl->owner)) == me) - return Jsvalify(obj->getSlot(slot)); -#endif - - js_LockObj(cx, obj); - v = Jsvalify(obj->getSlot(slot)); - - /* - * Test whether cx took ownership of obj's scope during js_LockObj. - * - * This does not mean that a given scope reverted to flyweight from "thin" - * or "fat" -- it does mean that obj's map pointer changed due to another - * thread setting a property, requiring obj to cease sharing a prototype - * object's scope (whose lock was not flyweight, else we wouldn't be here - * in the first place!). - */ - if (obj->title.ownercx != cx) - js_UnlockTitle(cx, &obj->title); - return v; -} - -void -js_SetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot, jsval v) -{ -#ifndef NSPR_LOCK - JSThinLock *tl; - jsword me; -#endif - - OBJ_CHECK_SLOT(obj, slot); - - /* Any string stored in a thread-safe object must be immutable. */ - if (JSVAL_IS_STRING(v) && - !js_MakeStringImmutable(cx, JSVAL_TO_STRING(v))) { - /* FIXME bug 363059: See comments in js_FinishSharingScope. */ - v = JSVAL_NULL; - } - - /* - * Native object locking is inlined here to optimize the single-threaded - * and contention-free multi-threaded cases. - */ - JS_ASSERT(obj->title.ownercx != cx); - JS_ASSERT(obj->containsSlot(slot)); - - /* - * Avoid locking if called from the GC. Also avoid locking a non-extensible - * object. If neither of those special cases applies, try to claim obj's - * flyweight lock from whatever context may have had it in an earlier - * request. - */ - if (CX_THREAD_IS_RUNNING_GC(cx) || - !obj->isExtensible() || - (obj->title.ownercx && ClaimTitle(&obj->title, cx))) { - obj->lockedSetSlot(slot, Valueify(v)); - return; - } - -#ifndef NSPR_LOCK - tl = &obj->title.lock; - me = CX_THINLOCK_ID(cx); - JS_ASSERT(CURRENT_THREAD_IS_ME(me)); - if (NativeCompareAndSwap(&tl->owner, 0, me)) { - obj->lockedSetSlot(slot, Valueify(v)); - if (!NativeCompareAndSwap(&tl->owner, me, 0)) { - /* Assert that scope locks never revert to flyweight. */ - JS_ASSERT(obj->title.ownercx != cx); - LOGIT(obj->title, '1'); - obj->title.u.count = 1; - js_UnlockObj(cx, obj); - } - return; - } - if (Thin_RemoveWait(ReadWord(tl->owner)) == me) { - obj->lockedSetSlot(slot, Valueify(v)); - return; - } -#endif - - js_LockObj(cx, obj); - obj->lockedSetSlot(slot, Valueify(v)); - - /* - * Same drill as above, in js_GetSlotThreadSafe. - */ - if (obj->title.ownercx != cx) - js_UnlockTitle(cx, &obj->title); -} - #ifndef NSPR_LOCK static JSFatLock * @@ -1163,169 +726,11 @@ js_UnlockRuntime(JSRuntime *rt) PR_Unlock(rt->rtLock); } -void -js_LockTitle(JSContext *cx, JSTitle *title) -{ - jsword me = CX_THINLOCK_ID(cx); - - JS_ASSERT(CURRENT_THREAD_IS_ME(me)); - JS_ASSERT(title->ownercx != cx); - if (CX_THREAD_IS_RUNNING_GC(cx)) - return; - if (title->ownercx && ClaimTitle(title, cx)) - return; - - if (Thin_RemoveWait(ReadWord(title->lock.owner)) == me) { - JS_ASSERT(title->u.count > 0); - LOGIT(title, '+'); - title->u.count++; - } else { - ThinLock(&title->lock, me); - JS_ASSERT(title->u.count == 0); - LOGIT(title, '1'); - title->u.count = 1; - } -} - -void -js_UnlockTitle(JSContext *cx, JSTitle *title) -{ - jsword me = CX_THINLOCK_ID(cx); - - /* We hope compilers use me instead of reloading cx->thread in the macro. */ - if (CX_THREAD_IS_RUNNING_GC(cx)) - return; - if (cx->thread->lockedSealedTitle == title) { - cx->thread->lockedSealedTitle = NULL; - return; - } - - /* - * If title->ownercx is not null, it's likely that two contexts not using - * requests nested locks for title. The first context, cx here, claimed - * title; the second, title->ownercx here, re-claimed it because the first - * was not in a request, or was on the same thread. We don't want to keep - * track of such nesting, because it penalizes the common non-nested case. - * Instead of asserting here and silently coping, we simply re-claim title - * for cx and return. - * - * See http://bugzilla.mozilla.org/show_bug.cgi?id=229200 for a real world - * case where an asymmetric thread model (Mozilla's main thread is known - * to be the only thread that runs the GC) combined with multiple contexts - * per thread has led to such request-less nesting. - */ - if (title->ownercx) { - JS_ASSERT(title->u.count == 0); - JS_ASSERT(title->lock.owner == 0); - title->ownercx = cx; - return; - } - - JS_ASSERT(title->u.count > 0); - if (Thin_RemoveWait(ReadWord(title->lock.owner)) != me) { - JS_ASSERT(0); /* unbalanced unlock */ - return; - } - LOGIT(title, '-'); - if (--title->u.count == 0) - ThinUnlock(&title->lock, me); -} - -void -js_LockObj(JSContext *cx, JSObject *obj) -{ - JS_ASSERT(obj->isNative()); - - /* - * We must test whether the GC is calling and return without mutating any - * state, especially lockedSealedScope. Note asymmetry with respect to - * js_UnlockObj, which is a thin-layer on top of js_UnlockTitle. - */ - if (CX_THREAD_IS_RUNNING_GC(cx)) - return; - - if (!obj->isExtensible() && !cx->thread->lockedSealedTitle) { - cx->thread->lockedSealedTitle = &obj->title; - return; - } - - js_LockTitle(cx, &obj->title); -} - -void -js_UnlockObj(JSContext *cx, JSObject *obj) -{ - JS_ASSERT(obj->isNative()); - js_UnlockTitle(cx, &obj->title); -} - -void -js_InitTitle(JSContext *cx, JSTitle *title) -{ -#ifdef JS_THREADSAFE - title->ownercx = cx; - js_InitLock(&title->lock); - - /* - * Set u.link = NULL, not u.count = 0, in case the target architecture's - * null pointer has a non-zero integer representation. - */ - title->u.link = NULL; -#endif -} - -void -js_FinishTitle(JSContext *cx, JSTitle *title) -{ -#ifdef DEBUG_SCOPE_COUNT - js_unlog_title(title); -#endif - -#ifdef JS_THREADSAFE - /* Title must be single-threaded at this point, so set ownercx. */ - JS_ASSERT(title->u.count == 0); - title->ownercx = cx; - js_FinishLock(&title->lock); -#endif -} - #ifdef DEBUG - JSBool js_IsRuntimeLocked(JSRuntime *rt) { return js_CurrentThreadId() == rt->rtLockOwner; } - -JSBool -js_IsObjLocked(JSContext *cx, JSObject *obj) -{ - return js_IsTitleLocked(cx, &obj->title); -} - -JSBool -js_IsTitleLocked(JSContext *cx, JSTitle *title) -{ - /* Special case: the GC locking any object's title, see js_LockTitle. */ - if (CX_THREAD_IS_RUNNING_GC(cx)) - return JS_TRUE; - - /* Special case: locked object is not extensible -- see js_LockObj. */ - if (cx->thread->lockedSealedTitle == title) - return JS_TRUE; - - /* - * General case: the title is either exclusively owned by some context, or - * it has a thin or fat lock to cope with shared (concurrent) ownership. - * - * js_LockTitle(cx, title) must set ownercx to cx when claiming the title - * from another context on the same thread. - */ - if (title->ownercx) - return title->ownercx == cx; - return js_CurrentThreadId() == - ((JSThread *)Thin_RemoveWait(ReadWord(title->lock.owner)))->id; -} - #endif /* DEBUG */ #endif /* JS_THREADSAFE */ diff --git a/js/src/jslock.h b/js/src/jslock.h index 38f656820b17..d3b9067f8403 100644 --- a/js/src/jslock.h +++ b/js/src/jslock.h @@ -88,23 +88,6 @@ typedef struct JSThinLock { typedef PRLock JSLock; -typedef struct JSTitle JSTitle; - -struct JSTitle { - JSContext *ownercx; /* creating context, NULL if shared */ - JSThinLock lock; /* binary semaphore protecting title */ - union { /* union lockful and lock-free state: */ - jsrefcount count; /* lock entry count for reentrancy */ - JSTitle *link; /* next link in rt->titleSharingTodo */ - } u; -}; - -/* - * Title structure is always allocated as a field of JSObject. - */ -#define TITLE_TO_OBJECT(title) \ - ((JSObject *)((uint8 *) (title) - offsetof(JSObject, title))) - /* * Atomic increment and decrement for a reference counter, given jsrefcount *p. * NB: jsrefcount is int32, aka PRInt32, so that pratom.h functions work. @@ -133,76 +116,24 @@ struct JSTitle { #define JS_LOCK_RUNTIME(rt) js_LockRuntime(rt) #define JS_UNLOCK_RUNTIME(rt) js_UnlockRuntime(rt) -/* - * NB: The JS_LOCK_OBJ and JS_UNLOCK_OBJ macros work *only* on native objects - * (objects for which obj->isNative() returns true). All uses of these macros in - * the engine are predicated on obj->isNative or equivalent checks. - */ -#define CX_OWNS_OBJECT_TITLE(cx,obj) ((obj)->title.ownercx == (cx)) - -#define JS_LOCK_OBJ(cx,obj) \ - JS_BEGIN_MACRO \ - JSObject *obj_ = (obj); \ - if (!CX_OWNS_OBJECT_TITLE(cx, obj_)) { \ - js_LockObj(cx, obj_); \ - JS_SET_OBJ_INFO(obj_, __FILE__, __LINE__); \ - } \ - JS_END_MACRO - -#define JS_UNLOCK_OBJ(cx,obj) \ - JS_BEGIN_MACRO \ - JSObject *obj_ = (obj); \ - if (!CX_OWNS_OBJECT_TITLE(cx, obj_)) \ - js_UnlockObj(cx, obj_); \ - JS_END_MACRO - -#define JS_LOCK_TITLE(cx,title) \ - ((title)->ownercx == (cx) ? (void)0 \ - : (js_LockTitle(cx, (title)), \ - JS_SET_TITLE_INFO(title,__FILE__,__LINE__))) - -#define JS_UNLOCK_TITLE(cx,title) ((title)->ownercx == (cx) ? (void)0 \ - : js_UnlockTitle(cx, title)) - extern void js_Lock(JSContext *cx, JSThinLock *tl); extern void js_Unlock(JSContext *cx, JSThinLock *tl); extern void js_LockRuntime(JSRuntime *rt); extern void js_UnlockRuntime(JSRuntime *rt); -extern void js_LockObj(JSContext *cx, JSObject *obj); -extern void js_UnlockObj(JSContext *cx, JSObject *obj); -extern void js_InitTitle(JSContext *cx, JSTitle *title); -extern void js_FinishTitle(JSContext *cx, JSTitle *title); -extern void js_LockTitle(JSContext *cx, JSTitle *title); -extern void js_UnlockTitle(JSContext *cx, JSTitle *title); extern int js_SetupLocks(int,int); extern void js_CleanupLocks(); -extern JS_FRIEND_API(jsval) -js_GetSlotThreadSafe(JSContext *, JSObject *, uint32); -extern void js_SetSlotThreadSafe(JSContext *, JSObject *, uint32, jsval); extern void js_InitLock(JSThinLock *); extern void js_FinishLock(JSThinLock *); -/* - * This function must be called with the GC lock held. - */ -extern void -js_ShareWaitingTitles(JSContext *cx); - #ifdef DEBUG #define JS_IS_RUNTIME_LOCKED(rt) js_IsRuntimeLocked(rt) -#define JS_IS_OBJ_LOCKED(cx,obj) js_IsObjLocked(cx,obj) -#define JS_IS_TITLE_LOCKED(cx,title) js_IsTitleLocked(cx,title) extern JSBool js_IsRuntimeLocked(JSRuntime *rt); -extern JSBool js_IsObjLocked(JSContext *cx, JSObject *obj); -extern JSBool js_IsTitleLocked(JSContext *cx, JSTitle *title); #else #define JS_IS_RUNTIME_LOCKED(rt) 0 -#define JS_IS_OBJ_LOCKED(cx,obj) 1 -#define JS_IS_TITLE_LOCKED(cx,title) 1 #endif /* DEBUG */ @@ -229,13 +160,8 @@ extern JSBool js_IsTitleLocked(JSContext *cx, JSTitle *title); #define JS_LOCK_RUNTIME(rt) ((void)0) #define JS_UNLOCK_RUNTIME(rt) ((void)0) -#define JS_LOCK_OBJ(cx,obj) ((void)0) -#define JS_UNLOCK_OBJ(cx,obj) ((void)0) -#define CX_OWNS_OBJECT_TITLE(cx,obj) 1 #define JS_IS_RUNTIME_LOCKED(rt) 1 -#define JS_IS_OBJ_LOCKED(cx,obj) 1 -#define JS_IS_TITLE_LOCKED(cx,title) 1 #endif /* !JS_THREADSAFE */ diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp index 831dad7c8862..814dbf010562 100644 --- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -854,6 +854,16 @@ static JSFunctionSpec math_static_methods[] = { JS_FS_END }; +bool +js_IsMathFunction(JSNative native) +{ + for (size_t i=0; math_static_methods[i].name != NULL; i++) { + if (native == math_static_methods[i].call) + return true; + } + return false; +} + JSObject * js_InitMathClass(JSContext *cx, JSObject *obj) { diff --git a/js/src/jsmath.h b/js/src/jsmath.h index a2534f5c7594..4a47d32129db 100644 --- a/js/src/jsmath.h +++ b/js/src/jsmath.h @@ -87,6 +87,9 @@ extern js::Class js_MathClass; extern JSObject * js_InitMathClass(JSContext *cx, JSObject *obj); +extern bool +js_IsMathFunction(JSNative native); + extern void js_InitRandom(JSContext *cx); diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp index d9a0ade7bb01..d7859b5d866d 100644 --- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -104,14 +104,12 @@ JS_STATIC_ASSERT(uintptr_t(PTRDIFF_MAX) + uintptr_t(1) == uintptr_t(PTRDIFF_MIN) #endif /* JS_HAVE_STDINT_H */ -namespace { - /* * If we're accumulating a decimal number and the number is >= 2^53, then the * fast result from the loop in GetPrefixInteger may be inaccurate. Call * js_strtod_harder to get the correct answer. */ -bool +static bool ComputeAccurateDecimalInteger(JSContext *cx, const jschar *start, const jschar *end, jsdouble *dp) { size_t length = end - start; @@ -186,7 +184,7 @@ class BinaryDigitReader * down. An example occurs when reading the number 0x1000000000000081, which * rounds to 0x1000000000000000 instead of 0x1000000000000100. */ -jsdouble +static jsdouble ComputeAccurateBinaryBaseInteger(JSContext *cx, const jschar *start, const jschar *end, int base) { BinaryDigitReader bdr(base, start, end); @@ -226,8 +224,6 @@ ComputeAccurateBinaryBaseInteger(JSContext *cx, const jschar *start, const jscha return value; } -} // namespace - namespace js { bool @@ -346,9 +342,7 @@ ParseFloat(JSContext* cx, JSString* str) } #endif -namespace { - -bool +static bool ParseIntStringHelper(JSContext *cx, const jschar *ws, const jschar *end, int maybeRadix, bool stripPrefix, jsdouble *dp) { @@ -401,7 +395,7 @@ ParseIntStringHelper(JSContext *cx, const jschar *ws, const jschar *end, int may return true; } -jsdouble +static jsdouble ParseIntDoubleHelper(jsdouble d) { if (!JSDOUBLE_IS_FINITE(d)) @@ -413,8 +407,6 @@ ParseIntDoubleHelper(jsdouble d) return 0; } -} // namespace - /* See ECMA 15.1.2.2. */ static JSBool num_parseInt(JSContext *cx, uintN argc, Value *vp) diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index c5de941fbc5a..f54a41a206f7 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -246,7 +246,6 @@ MarkSharpObjects(JSContext *cx, JSObject *obj, JSIdArray **idap) v.set(shape->getterValue()); if (hasSetter) setter.set(shape->setterValue()); - JS_UNLOCK_OBJ(cx, obj2); } else { hasGetter = hasSetter = false; } @@ -573,7 +572,6 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp) idstr = js_ValueToString(cx, IdToValue(id)); if (!idstr) { ok = JS_FALSE; - obj2->dropProperty(cx, prop); goto error; } vp->setString(idstr); /* local root */ @@ -596,7 +594,6 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp) gsop[valcnt] = ATOM_TO_STRING(cx->runtime->atomState.setAtom); valcnt++; } - JS_UNLOCK_OBJ(cx, obj2); } if (doGet) { valcnt = 1; @@ -1092,8 +1089,9 @@ EvalCacheLookup(JSContext *cx, JSString *str, JSStackFrame *caller, uintN static return NULL; } +/* ES5 15.1.2.1. */ static JSBool -obj_eval(JSContext *cx, uintN argc, Value *vp) +eval(JSContext *cx, uintN argc, Value *vp) { if (argc < 1) { vp->setUndefined(); @@ -1253,6 +1251,16 @@ obj_eval(JSContext *cx, uintN argc, Value *vp) return ok; } +namespace js { + +bool +IsBuiltinEvalFunction(JSFunction *fun) +{ + return fun->maybeNative() == eval; +} + +} + #if JS_HAS_OBJ_WATCHPOINT static JSBool @@ -1394,12 +1402,7 @@ js_HasOwnPropertyHelper(JSContext *cx, LookupPropOp lookup, uintN argc, } if (!js_HasOwnProperty(cx, lookup, obj, id, &obj2, &prop)) return JS_FALSE; - if (prop) { - vp->setBoolean(true); - obj2->dropProperty(cx, prop); - } else { - vp->setBoolean(false); - } + vp->setBoolean(!!prop); return JS_TRUE; } @@ -1446,7 +1449,6 @@ js_HasOwnProperty(JSContext *cx, LookupPropOp lookup, JSObject *obj, jsid id, return true; } - (*objp)->dropProperty(cx, *propp); *propp = NULL; } return true; @@ -1506,7 +1508,6 @@ js_PropertyIsEnumerable(JSContext *cx, JSObject *obj, jsid id, Value *vp) Shape *shape = (Shape *) prop; shared = shape->isSharedPermanent(); attrs = shape->attributes(); - JS_UNLOCK_OBJ(cx, pobj); } else { shared = false; if (!pobj->getAttributes(cx, id, &attrs)) @@ -1604,7 +1605,6 @@ obj_lookupGetter(JSContext *cx, uintN argc, Value *vp) Shape *shape = (Shape *) prop; if (shape->hasGetterValue()) *vp = shape->getterValue(); - JS_UNLOCK_OBJ(cx, pobj); } } return JS_TRUE; @@ -1627,7 +1627,6 @@ obj_lookupSetter(JSContext *cx, uintN argc, Value *vp) Shape *shape = (Shape *) prop; if (shape->hasSetterValue()) *vp = shape->setterValue(); - JS_UNLOCK_OBJ(cx, pobj); } } return JS_TRUE; @@ -1726,7 +1725,6 @@ js_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, Value *vp) if (attrs & JSPROP_SETTER) roots[1] = shape->setterValue(); } - JS_UNLOCK_OBJ(cx, pobj); } else { if (!pobj->getAttributes(cx, id, &attrs)) return false; @@ -1977,14 +1975,6 @@ Reject(JSContext *cx, JSObject *obj, uintN errorNumber, bool throwError, bool *r return JS_TRUE; } -static JSBool -Reject(JSContext *cx, JSObject *obj, JSProperty *prop, uintN errorNumber, bool throwError, - jsid id, bool *rval) -{ - obj->dropProperty(cx, prop); - return Reject(cx, errorNumber, throwError, id, rval); -} - static JSBool DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropDesc &desc, bool throwError, bool *rval) @@ -2089,8 +2079,7 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropDesc &desc, */ if (!shape->configurable() && (!shape->hasDefaultGetter() || !shape->hasDefaultSetter())) { - return Reject(cx, obj2, current, JSMSG_CANT_REDEFINE_PROP, throwError, - desc.id, rval); + return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, desc.id, rval); } if (!js_NativeGet(cx, obj, obj2, shape, JSGET_NO_METHOD_BARRIER, &v)) { @@ -2119,7 +2108,6 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropDesc &desc, break; /* The conditions imposed by step 5 or step 6 apply. */ - obj2->dropProperty(cx, current); *rval = true; return JS_TRUE; } while (0); @@ -2136,7 +2124,7 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropDesc &desc, JS_ASSERT_IF(!desc.hasConfigurable, !desc.configurable()); if (desc.configurable() || (desc.hasEnumerable && desc.enumerable() != shape->enumerable())) { - return Reject(cx, obj2, current, JSMSG_CANT_REDEFINE_PROP, throwError, desc.id, rval); + return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, desc.id, rval); } } @@ -2147,15 +2135,14 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropDesc &desc, } else if (desc.isDataDescriptor() != shape->isDataDescriptor()) { /* 8.12.9 step 9. */ if (!shape->configurable()) - return Reject(cx, obj2, current, JSMSG_CANT_REDEFINE_PROP, throwError, desc.id, rval); + return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, desc.id, rval); } else if (desc.isDataDescriptor()) { /* 8.12.9 step 10. */ JS_ASSERT(shape->isDataDescriptor()); if (!shape->configurable() && !shape->writable()) { if ((desc.hasWritable && desc.writable()) || (desc.hasValue && !SameValue(desc.value, v, cx))) { - return Reject(cx, obj2, current, JSMSG_CANT_REDEFINE_PROP, throwError, desc.id, - rval); + return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, desc.id, rval); } } @@ -2168,8 +2155,7 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropDesc &desc, !SameValue(desc.setterValue(), shape->setterOrUndefined(), cx)) || (desc.hasGet && !SameValue(desc.getterValue(), shape->getterOrUndefined(), cx))) { - return Reject(cx, obj2, current, JSMSG_CANT_REDEFINE_PROP, throwError, desc.id, - rval); + return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, desc.id, rval); } } } @@ -2213,10 +2199,8 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropDesc &desc, * control point of view. */ Value dummy; - if (!CheckAccess(cx, obj2, desc.id, JSACC_WATCH, &dummy, &attrs)) { - obj2->dropProperty(cx, current); + if (!CheckAccess(cx, obj2, desc.id, JSACC_WATCH, &dummy, &attrs)) return JS_FALSE; - } JS_ASSERT_IF(shape->isMethod(), !(attrs & (JSPROP_GETTER | JSPROP_SETTER))); @@ -2249,7 +2233,6 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropDesc &desc, } *rval = true; - obj2->dropProperty(cx, current); /* * Since "data" properties implemented using native C functions may rely on @@ -2866,10 +2849,6 @@ js_CreateThisFromTrace(JSContext *cx, Class *clasp, JSObject *ctor) { JS_ASSERT(JS_ON_TRACE(cx)); JS_ASSERT(ctor->isFunction()); -#ifdef JS_THREADSAFE - if (ctor->title.ownercx != cx) - return NULL; -#endif if (!ctor->ensureClassReservedSlots(cx)) return NULL; @@ -3508,10 +3487,8 @@ js_InitObjectClass(JSContext *cx, JSObject *obj) return NULL; /* ECMA (15.1.2.1) says 'eval' is a property of the global object. */ - if (!js_DefineFunction(cx, obj, cx->runtime->atomState.evalAtom, obj_eval, 1, - JSFUN_STUB_GSOPS)) { + if (!js_DefineFunction(cx, obj, cx->runtime->atomState.evalAtom, eval, 1, JSFUN_STUB_GSOPS)) return NULL; - } return proto; } @@ -3531,30 +3508,20 @@ DefineStandardSlot(JSContext *cx, JSObject *obj, JSProtoKey key, JSAtom *atom, JS_ASSERT(obj->getClass()->flags & JSCLASS_IS_GLOBAL); JS_ASSERT(obj->isNative()); - JS_LOCK_OBJ(cx, obj); - if (!obj->ensureClassReservedSlots(cx)) { - JS_UNLOCK_OBJ(cx, obj); + if (!obj->ensureClassReservedSlots(cx)) return false; - } const Shape *shape = obj->nativeLookup(id); if (!shape) { uint32 slot = 2 * JSProto_LIMIT + key; - if (!js_SetReservedSlot(cx, obj, slot, v)) { - JS_UNLOCK_OBJ(cx, obj); + if (!js_SetReservedSlot(cx, obj, slot, v)) return false; - } - - shape = obj->addProperty(cx, id, PropertyStub, PropertyStub, slot, attrs, 0, 0); - - JS_UNLOCK_OBJ(cx, obj); - if (!shape) + if (!obj->addProperty(cx, id, PropertyStub, PropertyStub, slot, attrs, 0, 0)) return false; named = true; return true; } - JS_UNLOCK_OBJ(cx, obj); } named = obj->defineProperty(cx, id, v, PropertyStub, PropertyStub, attrs); @@ -3713,6 +3680,14 @@ js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto, if (!proto->getEmptyShape(cx, proto->clasp, FINALIZE_OBJECT0)) goto bad; + if (clasp->flags & (JSCLASS_FREEZE_PROTO|JSCLASS_FREEZE_CTOR)) { + JS_ASSERT_IF(ctor == proto, !(clasp->flags & JSCLASS_FREEZE_CTOR)); + if (proto && (clasp->flags & JSCLASS_FREEZE_PROTO) && !proto->freeze(cx)) + goto bad; + if (ctor && (clasp->flags & JSCLASS_FREEZE_CTOR) && !ctor->freeze(cx)) + goto bad; + } + /* If this is a standard class, cache its prototype. */ if (key != JSProto_Null && !js_SetClassObject(cx, obj, key, ctor, proto)) goto bad; @@ -3864,10 +3839,7 @@ SetProto(JSContext *cx, JSObject *obj, JSObject *proto, bool checkForCycles) JS_ASSERT(obj->isExtensible()); if (obj->isNative()) { - JS_LOCK_OBJ(cx, obj); - bool ok = obj->ensureClassReservedSlots(cx); - JS_UNLOCK_OBJ(cx, obj); - if (!ok) + if (!obj->ensureClassReservedSlots(cx)) return false; } @@ -3878,11 +3850,8 @@ SetProto(JSContext *cx, JSObject *obj, JSObject *proto, bool checkForCycles) */ JSObject *oldproto = obj; while (oldproto && oldproto->isNative()) { - JS_LOCK_OBJ(cx, oldproto); oldproto->protoShapeChange(cx); - JSObject *tmp = oldproto->getProto(); - JS_UNLOCK_OBJ(cx, oldproto); - oldproto = tmp; + oldproto = oldproto->getProto(); } if (!proto || !checkForCycles) { @@ -4023,11 +3992,10 @@ js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey protoKey, if (prop && pobj->isNative()) { shape = (Shape *) prop; if (pobj->containsSlot(shape->slot)) { - v = pobj->lockedGetSlot(shape->slot); + v = pobj->nativeGetSlot(shape->slot); if (v.isPrimitive()) v.setUndefined(); } - JS_UNLOCK_OBJ(cx, pobj); } *vp = v; return JS_TRUE; @@ -4246,12 +4214,10 @@ PurgeProtoChain(JSContext *cx, JSObject *obj, jsid id) obj = obj->getProto(); continue; } - JS_LOCK_OBJ(cx, obj); shape = obj->nativeLookup(id); if (shape) { PCMETER(JS_PROPERTY_CACHE(cx).pcpurges++); obj->shadowingShapeChange(cx, *shape); - JS_UNLOCK_OBJ(cx, obj); if (!obj->getParent()) { /* @@ -4263,11 +4229,7 @@ PurgeProtoChain(JSContext *cx, JSObject *obj, jsid id) } return JS_TRUE; } -#ifdef JS_THREADSAFE - JSObject *pobj = obj; -#endif obj = obj->getProto(); - JS_UNLOCK_OBJ(cx, pobj); } return JS_FALSE; } @@ -4297,8 +4259,6 @@ js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id, PropertyOp getter, PropertyOp setter, uint32 slot, uintN attrs, uintN flags, intN shortid) { - const Shape *shape; - JS_ASSERT(!(flags & Shape::METHOD)); /* @@ -4308,16 +4268,12 @@ js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id, */ js_PurgeScopeChain(cx, obj, id); - JS_LOCK_OBJ(cx, obj); - if (!obj->ensureClassReservedSlots(cx)) { - shape = NULL; - } else { - /* Convert string indices to integers if appropriate. */ - id = js_CheckForStringIndex(id); - shape = obj->putProperty(cx, id, getter, setter, slot, attrs, flags, shortid); - } - JS_UNLOCK_OBJ(cx, obj); - return shape; + if (!obj->ensureClassReservedSlots(cx)) + return NULL; + + /* Convert string indices to integers if appropriate. */ + id = js_CheckForStringIndex(id); + return obj->putProperty(cx, id, getter, setter, slot, attrs, flags, shortid); } const Shape * @@ -4325,12 +4281,9 @@ js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj, const Shape *shape, uintN attrs, uintN mask, PropertyOp getter, PropertyOp setter) { - JS_LOCK_OBJ(cx, obj); - shape = obj->ensureClassReservedSlots(cx) - ? obj->changeProperty(cx, shape, attrs, mask, getter, setter) - : NULL; - JS_UNLOCK_OBJ(cx, obj); - return shape; + if (!obj->ensureClassReservedSlots(cx)) + return NULL; + return obj->changeProperty(cx, shape, attrs, mask, getter, setter); } JSBool @@ -4357,7 +4310,7 @@ CallAddPropertyHook(JSContext *cx, Class *clasp, JSObject *obj, const Shape *sha return false; if (*vp != nominal) { if (obj->containsSlot(shape->slot)) - obj->lockedSetSlot(shape->slot, *vp); + obj->nativeSetSlot(shape->slot, *vp); } } return true; @@ -4411,11 +4364,9 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &valu ? setter : shape->setter()); - /* NB: obj == pobj, so we can share unlock code at the bottom. */ if (!shape) - goto error; + return false; } else if (prop) { - pobj->dropProperty(cx, prop); prop = NULL; shape = NULL; } @@ -4437,9 +4388,6 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &valu if (obj->isDelegate() && (attrs & (JSPROP_READONLY | JSPROP_SETTER))) cx->runtime->protoHazardShape = js_GenerateShape(cx, false); - /* Lock if object locking is required by this implementation. */ - JS_LOCK_OBJ(cx, obj); - /* Use the object's class getter and setter by default. */ clasp = obj->getClass(); if (!(defineHow & JSDNP_SET_METHOD)) { @@ -4451,7 +4399,7 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &valu /* Get obj's own scope if it has one, or create a new one for obj. */ if (!obj->ensureClassReservedSlots(cx)) - goto error; + return false; added = false; if (!shape) { @@ -4474,7 +4422,7 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &valu shape = obj->putProperty(cx, id, getter, setter, SHAPE_INVALID_SLOT, attrs, flags, shortid); if (!shape) - goto error; + return false; /* * If shape is a method, the above call to putProperty suffices to @@ -4488,13 +4436,13 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &valu /* Store value before calling addProperty, in case the latter GC's. */ if (obj->containsSlot(shape->slot)) - obj->lockedSetSlot(shape->slot, value); + obj->nativeSetSlot(shape->slot, value); /* XXXbe called with lock held */ valueCopy = value; if (!CallAddPropertyHook(cx, clasp, obj, shape, &valueCopy)) { obj->removeProperty(cx, id); - goto error; + return false; } if (defineHow & JSDNP_CACHE_RESULT) { @@ -4507,13 +4455,10 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &valu } if (propp) *propp = (JSProperty *) shape; - else - JS_UNLOCK_OBJ(cx, obj); - return JS_TRUE; + return true; -error: // TRACE_2 jumps here on error, as well. - JS_UNLOCK_OBJ(cx, obj); - return JS_FALSE; +error: // TRACE_2 jumps here on error. + return false; } JS_FRIEND_API(JSBool) @@ -4566,13 +4511,10 @@ CallResolveOp(JSContext *cx, JSObject *start, JSObject *obj, jsid id, uintN flag */ JSResolvingKey key = {obj, id}; JSResolvingEntry *entry; - if (!js_StartResolving(cx, &key, JSRESFLAG_LOOKUP, &entry)) { - JS_UNLOCK_OBJ(cx, obj); + if (!js_StartResolving(cx, &key, JSRESFLAG_LOOKUP, &entry)) return false; - } if (!entry) { /* Already resolving id in obj -- suppress recursion. */ - JS_UNLOCK_OBJ(cx, obj); *recursedp = true; return true; } @@ -4588,7 +4530,6 @@ CallResolveOp(JSContext *cx, JSObject *start, JSObject *obj, jsid id, uintN flag if (flags == JSRESOLVE_INFER) flags = js_InferFlags(cx, 0); JSObject *obj2 = (clasp->flags & JSCLASS_NEW_RESOLVE_GETS_START) ? start : NULL; - JS_UNLOCK_OBJ(cx, obj); { /* Protect id and all atoms from a GC nested in resolve. */ @@ -4598,21 +4539,14 @@ CallResolveOp(JSContext *cx, JSObject *start, JSObject *obj, jsid id, uintN flag if (!ok) goto cleanup; - JS_LOCK_OBJ(cx, obj); if (obj2) { - /* Resolved: juggle locks and lookup id again. */ - if (obj2 != obj) { - JS_UNLOCK_OBJ(cx, obj); - if (obj2->isNative()) - JS_LOCK_OBJ(cx, obj2); - } + /* Resolved: lookup id again for backward compatibility. */ if (!obj2->isNative()) { /* Whoops, newresolve handed back a foreign obj2. */ JS_ASSERT(obj2 != obj); ok = obj2->lookupProperty(cx, id, objp, propp); if (!ok || *propp) goto cleanup; - JS_LOCK_OBJ(cx, obj2); } else { /* * Require that obj2 not be empty now, as we do for old-style @@ -4627,10 +4561,6 @@ CallResolveOp(JSContext *cx, JSObject *start, JSObject *obj, jsid id, uintN flag if (shape) { JS_ASSERT(!obj2->nativeEmpty()); obj = obj2; - } else if (obj2 != obj) { - if (obj2->isNative()) - JS_UNLOCK_OBJ(cx, obj2); - JS_LOCK_OBJ(cx, obj); } } } else { @@ -4638,11 +4568,9 @@ CallResolveOp(JSContext *cx, JSObject *start, JSObject *obj, jsid id, uintN flag * Old resolve always requires id re-lookup if obj is not empty after * resolve returns. */ - JS_UNLOCK_OBJ(cx, obj); ok = resolve(cx, obj, id); if (!ok) goto cleanup; - JS_LOCK_OBJ(cx, obj); JS_ASSERT(obj->isNative()); if (!obj->nativeEmpty()) shape = obj->nativeLookup(id); @@ -4668,7 +4596,6 @@ js_LookupPropertyWithFlagsInline(JSContext *cx, JSObject *obj, jsid id, uintN fl JSObject *start = obj; int protoIndex; for (protoIndex = 0; ; protoIndex++) { - JS_LOCK_OBJ(cx, obj); const Shape *shape = obj->nativeLookup(id); if (shape) { SCOPE_DEPTH_ACCUM(&cx->runtime->protoLookupDepthStats, protoIndex); @@ -4695,7 +4622,6 @@ js_LookupPropertyWithFlagsInline(JSContext *cx, JSObject *obj, jsid id, uintN fl } JSObject *proto = obj->getProto(); - JS_UNLOCK_OBJ(cx, obj); if (!proto) break; if (!proto->isNative()) { @@ -4868,7 +4794,6 @@ js_FindIdentifierBase(JSContext *cx, JSObject *scopeChain, jsid id) JS_PROPERTY_CACHE(cx).fill(cx, scopeChain, scopeIndex, protoIndex, pobj, (Shape *) prop); JS_ASSERT(entry); - JS_UNLOCK_OBJ(cx, pobj); return obj; } @@ -4884,10 +4809,8 @@ js_FindIdentifierBase(JSContext *cx, JSObject *scopeChain, jsid id) JSProperty *prop; if (!obj->lookupProperty(cx, id, &pobj, &prop)) return NULL; - if (prop) { - pobj->dropProperty(cx, prop); + if (prop) break; - } /* * We conservatively assume that a resolve hook could mutate the scope @@ -4912,11 +4835,10 @@ js_NativeGetInline(JSContext *cx, JSObject *obj, JSObject *pobj, const Shape *sh int32 sample; JS_ASSERT(pobj->isNative()); - JS_ASSERT(JS_IS_OBJ_LOCKED(cx, pobj)); slot = shape->slot; if (slot != SHAPE_INVALID_SLOT) { - *vp = pobj->lockedGetSlot(slot); + *vp = pobj->nativeGetSlot(slot); JS_ASSERT(!vp->isMagic()); } else { vp->setUndefined(); @@ -4930,23 +4852,19 @@ js_NativeGetInline(JSContext *cx, JSObject *obj, JSObject *pobj, const Shape *sh } sample = cx->runtime->propertyRemovals; - JS_UNLOCK_OBJ(cx, pobj); { AutoShapeRooter tvr(cx, shape); AutoObjectRooter tvr2(cx, pobj); if (!shape->get(cx, obj, pobj, vp)) return false; } - JS_LOCK_OBJ(cx, pobj); if (pobj->containsSlot(slot) && (JS_LIKELY(cx->runtime->propertyRemovals == sample) || pobj->nativeContains(*shape))) { - if (!pobj->methodWriteBarrier(cx, *shape, *vp)) { - JS_UNLOCK_OBJ(cx, pobj); + if (!pobj->methodWriteBarrier(cx, *shape, *vp)) return false; - } - pobj->lockedSetSlot(slot, *vp); + pobj->nativeSetSlot(slot, *vp); } return true; @@ -4968,19 +4886,16 @@ js_NativeSet(JSContext *cx, JSObject *obj, const Shape *shape, bool added, Value int32 sample; JS_ASSERT(obj->isNative()); - JS_ASSERT(JS_IS_OBJ_LOCKED(cx, obj)); slot = shape->slot; if (slot != SHAPE_INVALID_SLOT) { - OBJ_CHECK_SLOT(obj, slot); + JS_ASSERT(obj->containsSlot(slot)); /* If shape has a stub setter, keep obj locked and just store *vp. */ if (shape->hasDefaultSetter()) { - if (!added && !obj->methodWriteBarrier(cx, *shape, *vp)) { - JS_UNLOCK_OBJ(cx, obj); + if (!added && !obj->methodWriteBarrier(cx, *shape, *vp)) return false; - } - obj->lockedSetSlot(slot, *vp); + obj->nativeSetSlot(slot, *vp); return true; } } else { @@ -4995,22 +4910,18 @@ js_NativeSet(JSContext *cx, JSObject *obj, const Shape *shape, bool added, Value } sample = cx->runtime->propertyRemovals; - JS_UNLOCK_OBJ(cx, obj); { AutoShapeRooter tvr(cx, shape); if (!shape->set(cx, obj, vp)) return false; } - JS_LOCK_OBJ(cx, obj); if (obj->containsSlot(slot) && (JS_LIKELY(cx->runtime->propertyRemovals == sample) || obj->nativeContains(*shape))) { - if (!added && !obj->methodWriteBarrier(cx, *shape, *vp)) { - JS_UNLOCK_OBJ(cx, obj); + if (!added && !obj->methodWriteBarrier(cx, *shape, *vp)) return false; - } - obj->lockedSetSlot(slot, *vp); + obj->setSlot(slot, *vp); } return true; @@ -5118,7 +5029,6 @@ js_GetPropertyHelperWithShapeInline(JSContext *cx, JSObject *obj, jsid id, if (!js_NativeGetInline(cx, obj, obj2, shape, getHow, vp)) return JS_FALSE; - JS_UNLOCK_OBJ(cx, obj2); return JS_TRUE; } @@ -5164,7 +5074,6 @@ js::GetPropertyDefault(JSContext *cx, JSObject *obj, jsid id, Value def, Value * return true; } - obj2->dropProperty(cx, prop); return js_GetProperty(cx, obj2, id, vp); } @@ -5283,10 +5192,6 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, /* * Now either shape is null, meaning id was not found in obj or one of its * prototypes; or shape is non-null, meaning id was found directly in pobj. - * If JS_THREADSAFE and shape is non-null, then pobj is locked, and shape - * is held: we must JSObject::dropProperty or else JS_UNLOCK_OBJ before we - * return (the two are equivalent for native objects; we use JS_UNLOCK_OBJ - * because it is cheaper). */ attrs = JSPROP_ENUMERATE; flags = 0; @@ -5299,7 +5204,6 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, /* ES5 8.12.4 [[Put]] step 2. */ if (shape->isAccessorDescriptor()) { if (shape->hasDefaultSetter()) { - JS_UNLOCK_OBJ(cx, pobj); if (defineHow & JSDNP_CACHE_RESULT) TRACE_2(SetPropHit, JS_NO_PROP_CACHE_FILL, shape); return js_ReportGetterOnlyAssignment(cx); @@ -5308,8 +5212,6 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, JS_ASSERT(shape->isDataDescriptor()); if (!shape->writable()) { - JS_UNLOCK_OBJ(cx, pobj); - PCMETER((defineHow & JSDNP_CACHE_RESULT) && JS_PROPERTY_CACHE(cx).rofills++); if (defineHow & JSDNP_CACHE_RESULT) { JS_ASSERT_NOT_ON_TRACE(cx); @@ -5335,13 +5237,8 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, /* * We found id in a prototype object: prepare to share or shadow. * - * NB: Thanks to the immutable, garbage-collected property tree - * maintained by jsscope.c in cx->runtime, we needn't worry about - * shape going away behind our back after we've unlocked pobj. + * Don't clone a prototype property that doesn't have a slot. */ - JS_UNLOCK_OBJ(cx, pobj); - - /* Don't clone a prototype property that doesn't have a slot. */ if (!shape->hasSlot()) { if (defineHow & JSDNP_CACHE_RESULT) { #ifdef JS_TRACER @@ -5424,11 +5321,8 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, js_PurgeScopeChain(cx, obj, id); /* Find or make a property descriptor with the right heritage. */ - JS_LOCK_OBJ(cx, obj); - if (!obj->ensureClassReservedSlots(cx)) { - JS_UNLOCK_OBJ(cx, obj); + if (!obj->ensureClassReservedSlots(cx)) return JS_FALSE; - } /* * Check for Object class here to avoid defining a method on a class @@ -5448,10 +5342,8 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, shape = obj->putProperty(cx, id, getter, setter, SHAPE_INVALID_SLOT, attrs, flags, shortid); - if (!shape) { - JS_UNLOCK_OBJ(cx, obj); + if (!shape) return JS_FALSE; - } /* * Initialize the new property value (passed to setter) to undefined. @@ -5459,12 +5351,11 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, * in js_DefineNativeProperty. */ if (obj->containsSlot(shape->slot)) - obj->lockedSetSlot(shape->slot, UndefinedValue()); + obj->nativeSetSlot(shape->slot, UndefinedValue()); /* XXXbe called with obj locked */ if (!CallAddPropertyHook(cx, clasp, obj, shape, vp)) { obj->removeProperty(cx, id); - JS_UNLOCK_OBJ(cx, obj); return JS_FALSE; } added = true; @@ -5479,11 +5370,7 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, TRACE_2(SetPropHit, entry, shape); } - if (!js_NativeSet(cx, obj, shape, added, vp)) - return NULL; - - JS_UNLOCK_OBJ(cx, obj); - return JS_TRUE; + return js_NativeSet(cx, obj, shape, added, vp); } JSBool @@ -5507,7 +5394,6 @@ js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) const Shape *shape = (Shape *)prop; *attrsp = shape->attributes(); - JS_UNLOCK_OBJ(cx, obj); return true; } @@ -5515,10 +5401,8 @@ JSBool js_SetNativeAttributes(JSContext *cx, JSObject *obj, Shape *shape, uintN attrs) { JS_ASSERT(obj->isNative()); - bool ok = !!js_ChangeNativePropertyAttrs(cx, obj, shape, attrs, 0, - shape->getter(), shape->setter()); - JS_UNLOCK_OBJ(cx, obj); - return ok; + return !!js_ChangeNativePropertyAttrs(cx, obj, shape, attrs, 0, + shape->getter(), shape->setter()); } JSBool @@ -5540,7 +5424,6 @@ js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool str JSObject *proto; JSProperty *prop; const Shape *shape; - JSBool ok; rval->setBoolean(true); @@ -5559,13 +5442,11 @@ js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool str if (prop && proto->isNative()) { shape = (Shape *)prop; if (shape->isSharedPermanent()) { - JS_UNLOCK_OBJ(cx, proto); if (strict) return obj->reportNotConfigurable(cx, id); rval->setBoolean(false); return true; } - JS_UNLOCK_OBJ(cx, proto); } /* @@ -5578,21 +5459,17 @@ js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool str shape = (Shape *)prop; if (!shape->configurable()) { - JS_UNLOCK_OBJ(cx, obj); if (strict) return obj->reportNotConfigurable(cx, id); rval->setBoolean(false); return true; } - /* XXXbe called with obj locked */ - if (!CallJSPropertyOp(cx, obj->getClass()->delProperty, obj, SHAPE_USERID(shape), rval)) { - JS_UNLOCK_OBJ(cx, obj); + if (!CallJSPropertyOp(cx, obj->getClass()->delProperty, obj, SHAPE_USERID(shape), rval)) return false; - } if (obj->containsSlot(shape->slot)) { - const Value &v = obj->lockedGetSlot(shape->slot); + const Value &v = obj->nativeGetSlot(shape->slot); GC_POKE(cx, v); /* @@ -5626,10 +5503,7 @@ js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool str } } - ok = obj->removeProperty(cx, id); - JS_UNLOCK_OBJ(cx, obj); - - return ok && js_SuppressDeletedProperty(cx, obj, id); + return obj->removeProperty(cx, id) && js_SuppressDeletedProperty(cx, obj, id); } namespace js { @@ -5648,35 +5522,26 @@ ClassMethodIsNative(JSContext *cx, JSObject *obj, Class *classp, jsid methodid, { JS_ASSERT(obj->getClass() == classp); - JS_LOCK_OBJ(cx, obj); - JSObject *lockedobj = obj; const Shape *shape = obj->nativeLookup(methodid); JSObject *pobj = obj; if (!shape) { pobj = obj->getProto(); - if (pobj && pobj->getClass() == classp) { - JS_UNLOCK_OBJ(cx, obj); - JS_LOCK_OBJ(cx, pobj); - lockedobj = pobj; + if (pobj && pobj->getClass() == classp) shape = pobj->nativeLookup(methodid); - } } if (shape && shape->hasDefaultGetter() && pobj->containsSlot(shape->slot)) { - const Value &fval = pobj->lockedGetSlot(shape->slot); + const Value &fval = pobj->nativeGetSlot(shape->slot); JSObject *funobj; if (IsFunctionObject(fval, &funobj)) { JSFunction *fun = funobj->getFunctionPrivate(); - if (fun->maybeNative() == native) { - JS_UNLOCK_OBJ(cx, lockedobj); + if (fun->maybeNative() == native) return true; - } } } - JS_UNLOCK_OBJ(cx, lockedobj); return false; } @@ -5826,11 +5691,10 @@ CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, *attrsp = shape->attributes(); if (!writing) { if (pobj->containsSlot(shape->slot)) - *vp = pobj->lockedGetSlot(shape->slot); + *vp = pobj->nativeGetSlot(shape->slot); else vp->setUndefined(); } - JS_UNLOCK_OBJ(cx, pobj); } /* @@ -5873,14 +5737,6 @@ js_TypeOf(JSContext *cx, JSObject *obj) return JSTYPE_OBJECT; } -#ifdef JS_THREADSAFE -void -js_DropProperty(JSContext *cx, JSObject *obj, JSProperty *prop) -{ - JS_UNLOCK_OBJ(cx, obj); -} -#endif - bool js_IsDelegate(JSContext *cx, JSObject *obj, const Value &v) { @@ -6326,7 +6182,6 @@ js_ClearNative(JSContext *cx, JSObject *obj) * Clear obj of all obj's properties. FIXME: we do not clear reserved slots * lying below JSSLOT_FREE(clasp). JS_ClearScope does that. */ - JS_LOCK_OBJ(cx, obj); if (!obj->nativeEmpty()) { /* Now that we're done using real properties, clear obj. */ obj->clear(cx); @@ -6337,7 +6192,6 @@ js_ClearNative(JSContext *cx, JSObject *obj) for (uint32 i = freeslot; i < n; ++i) obj->setSlot(i, UndefinedValue()); } - JS_UNLOCK_OBJ(cx, obj); } bool @@ -6348,12 +6202,10 @@ js_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 slot, Value *vp) return true; } - JS_LOCK_OBJ(cx, obj); if (slot < obj->numSlots()) *vp = obj->getSlot(slot); else vp->setUndefined(); - JS_UNLOCK_OBJ(cx, obj); return true; } @@ -6365,19 +6217,15 @@ js_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 slot, const Value &v) Class *clasp = obj->getClass(); - JS_LOCK_OBJ(cx, obj); if (slot >= obj->numSlots()) { uint32 nslots = JSSLOT_FREE(clasp); JS_ASSERT(slot < nslots); - if (!obj->allocSlots(cx, nslots)) { - JS_UNLOCK_OBJ(cx, obj); + if (!obj->allocSlots(cx, nslots)) return false; - } } obj->setSlot(slot, v); GC_POKE(cx, JS_NULL); - JS_UNLOCK_OBJ(cx, obj); return true; } diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 2429e29ea7ac..2db2a05d0cd8 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -196,10 +196,9 @@ struct JSObjectMap { /* * Unlike js_DefineNativeProperty, propp must be non-null. On success, and if - * id was found, return true with *objp non-null and locked, and with a held - * property stored in *propp. If successful but id was not found, return true - * with both *objp and *propp null. Therefore all callers who receive a - * non-null *propp must later call (*objp)->dropProperty(cx, *propp). + * id was found, return true with *objp non-null and with a property of *objp + * stored in *propp. If successful but id was not found, return true with both + * *objp and *propp null. */ extern JS_FRIEND_API(JSBool) js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, @@ -356,10 +355,6 @@ struct JSObject : js::gc::Cell { uint32 flags; /* flags */ uint32 objShape; /* copy of lastProp->shape, or override if different */ -#ifdef JS_THREADSAFE - JSTitle title; -#endif - /* If prototype, lazily filled array of empty shapes for each object size. */ js::EmptyShape **emptyShapes; @@ -612,26 +607,33 @@ struct JSObject : js::gc::Cell { return slots[slot]; } + js::Value &nativeGetSlotRef(uintN slot) { + JS_ASSERT(isNative()); + JS_ASSERT(containsSlot(slot)); + return getSlotRef(slot); + } + const js::Value &getSlot(uintN slot) const { JS_ASSERT(slot < capacity); return slots[slot]; } + const js::Value &nativeGetSlot(uintN slot) const { + JS_ASSERT(isNative()); + JS_ASSERT(containsSlot(slot)); + return getSlot(slot); + } + void setSlot(uintN slot, const js::Value &value) { JS_ASSERT(slot < capacity); slots[slot] = value; } - inline const js::Value &lockedGetSlot(uintN slot) const; - inline void lockedSetSlot(uintN slot, const js::Value &value); - - /* - * These ones are for multi-threaded ("MT") objects. Use getSlot(), - * getSlotRef(), setSlot() to directly manipulate slots in obj when only - * one thread can access obj. - */ - inline js::Value getSlotMT(JSContext *cx, uintN slot); - inline void setSlotMT(JSContext *cx, uintN slot, const js::Value &value); + void nativeSetSlot(uintN slot, const js::Value &value) { + JS_ASSERT(isNative()); + JS_ASSERT(containsSlot(slot)); + return setSlot(slot, value); + } inline js::Value getReservedSlot(uintN index) const; @@ -1105,8 +1107,6 @@ struct JSObject : js::gc::Cell { static bool thisObject(JSContext *cx, const js::Value &v, js::Value *vp); - inline void dropProperty(JSContext *cx, JSProperty *prop); - inline JSCompartment *getCompartment() const; inline JSObject *getThrowTypeError() const; @@ -1175,8 +1175,6 @@ struct JSObject_Slots16 : JSObject { js::Value fslots[16]; }; #define JSSLOT_FREE(clasp) JSCLASS_RESERVED_SLOTS(clasp) -#define OBJ_CHECK_SLOT(obj,slot) JS_ASSERT((obj)->containsSlot(slot)) - #ifdef JS_THREADSAFE /* @@ -1476,9 +1474,7 @@ const uintN JSDNP_UNQUALIFIED = 8; /* Unqualified property set. Only used in /* * On error, return false. On success, if propp is non-null, return true with * obj locked and with a held property in *propp; if propp is null, return true - * but release obj's lock first. Therefore all callers who pass non-null propp - * result parameters must later call obj->dropProperty(cx, *propp) both to drop - * the held property, and to release the lock on obj. + * but release obj's lock first. */ extern JSBool js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value &value, @@ -1718,12 +1714,11 @@ namespace js { extern bool SetProto(JSContext *cx, JSObject *obj, JSObject *proto, bool checkForCycles); -} - -namespace js { - extern JSString * obj_toStringHelper(JSContext *cx, JSObject *obj); +extern bool +IsBuiltinEvalFunction(JSFunction *fun); + } #endif /* jsobj_h___ */ diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index f103023f5a65..3ccc2809167e 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -63,14 +63,6 @@ #include "jsgcinlines.h" #include "jsprobes.h" -inline void -JSObject::dropProperty(JSContext *cx, JSProperty *prop) -{ - JS_ASSERT(prop); - if (isNative()) - JS_UNLOCK_OBJ(cx, this); -} - inline bool JSObject::preventExtensions(JSContext *cx, js::AutoIdVector *props) { @@ -194,7 +186,7 @@ inline bool JSObject::methodWriteBarrier(JSContext *cx, const js::Shape &shape, const js::Value &v) { if (flags & (BRANDED | METHOD_BARRIER)) { - const js::Value &prev = lockedGetSlot(shape.slot); + const js::Value &prev = nativeGetSlot(shape.slot); if (ChangesMethodValue(prev, v)) { JS_FUNCTION_METER(cx, mwritebarrier); @@ -208,7 +200,7 @@ inline bool JSObject::methodWriteBarrier(JSContext *cx, uint32 slot, const js::Value &v) { if (flags & (BRANDED | METHOD_BARRIER)) { - const js::Value &prev = lockedGetSlot(slot); + const js::Value &prev = nativeGetSlot(slot); if (ChangesMethodValue(prev, v)) { JS_FUNCTION_METER(cx, mwslotbarrier); @@ -224,42 +216,6 @@ JSObject::ensureClassReservedSlots(JSContext *cx) return !nativeEmpty() || ensureClassReservedSlotsForEmptyObject(cx); } -inline js::Value -JSObject::getSlotMT(JSContext *cx, uintN slot) -{ -#ifdef JS_THREADSAFE - /* - * If thread-safe, define a getSlotMT() that bypasses, for a native object, - * the lock-free "fast path" test of (obj->title.ownercx == cx), to avoid - * needlessly switching from lock-free to lock-full scope when doing GC on - * a different context from the last one to own the scope. The caller in - * this case is probably a JSClass.mark function, e.g., fun_mark, or maybe - * a finalizer. - */ - OBJ_CHECK_SLOT(this, slot); - return (title.ownercx == cx) - ? this->lockedGetSlot(slot) - : js::Valueify(js_GetSlotThreadSafe(cx, this, slot)); -#else - return this->lockedGetSlot(slot); -#endif -} - -inline void -JSObject::setSlotMT(JSContext *cx, uintN slot, const js::Value &value) -{ -#ifdef JS_THREADSAFE - /* Thread-safe way to set a slot. */ - OBJ_CHECK_SLOT(this, slot); - if (title.ownercx == cx) - this->lockedSetSlot(slot, value); - else - js_SetSlotThreadSafe(cx, this, slot, js::Jsvalify(value)); -#else - this->lockedSetSlot(slot, value); -#endif -} - inline js::Value JSObject::getReservedSlot(uintN index) const { @@ -659,10 +615,6 @@ JSObject::init(JSContext *cx, js::Class *aclasp, JSObject *proto, JSObject *pare JS_ASSERT(capacity == numFixedSlots()); ClearValueRange(slots, capacity, useHoles); -#ifdef JS_THREADSAFE - js_InitTitle(cx, &title); -#endif - emptyShapes = NULL; } @@ -677,9 +629,6 @@ JSObject::finish(JSContext *cx) freeSlotsArray(cx); if (emptyShapes) cx->free(emptyShapes); -#ifdef JS_THREADSAFE - js_FinishTitle(cx, &title); -#endif } inline bool @@ -730,8 +679,6 @@ JSObject::hasProperty(JSContext *cx, jsid id, bool *foundp, uintN flags) if (!lookupProperty(cx, id, &pobj, &prop)) return false; *foundp = !!prop; - if (prop) - pobj->dropProperty(cx, prop); return true; } @@ -807,14 +754,10 @@ InitScopeForObject(JSContext* cx, JSObject* obj, js::Class *clasp, JSObject* pro js::EmptyShape *empty = NULL; if (proto) { - JS_LOCK_OBJ(cx, proto); if (proto->canProvideEmptyShape(clasp)) { empty = proto->getEmptyShape(cx, clasp, kind); - JS_UNLOCK_OBJ(cx, proto); if (!empty) goto bad; - } else { - JS_UNLOCK_OBJ(cx, proto); } } @@ -864,10 +807,8 @@ NewNativeClassInstance(JSContext *cx, Class *clasp, JSObject *proto, bool useHoles = (clasp == &js_ArrayClass); obj->init(cx, clasp, proto, parent, NULL, useHoles); - JS_LOCK_OBJ(cx, proto); JS_ASSERT(proto->canProvideEmptyShape(clasp)); js::EmptyShape *empty = proto->getEmptyShape(cx, clasp, kind); - JS_UNLOCK_OBJ(cx, proto); if (empty) obj->setMap(empty); @@ -1106,20 +1047,6 @@ NewObjectGCKind(JSContext *cx, js::Class *clasp) return gc::FINALIZE_OBJECT4; } -class AutoPropertyDropper { - JSContext *cx; - JSObject *holder; - JSProperty *prop; - - public: - AutoPropertyDropper(JSContext *cx, JSObject *obj, JSProperty *prop) - : cx(cx), holder(obj), prop(prop) - { JS_ASSERT(prop); } - - ~AutoPropertyDropper() - { holder->dropProperty(cx, prop); } -}; - } /* namespace js */ #endif /* jsobjinlines_h___ */ diff --git a/js/src/jsopcode.tbl b/js/src/jsopcode.tbl index 1f4fd8d21b42..9c0a0bd1d920 100644 --- a/js/src/jsopcode.tbl +++ b/js/src/jsopcode.tbl @@ -126,8 +126,8 @@ OPDEF(JSOP_IFNE, 8, "ifne", NULL, 3, 1, 0, 0, JOF_JUMP|J OPDEF(JSOP_ARGUMENTS, 9, js_arguments_str, js_arguments_str, 1, 0, 1, 18, JOF_BYTE) /* ECMA-compliant for-in loop with argument or local loop control. */ -OPDEF(JSOP_FORARG, 10, "forarg", NULL, 3, 1, 1, 19, JOF_QARG|JOF_NAME|JOF_FOR) -OPDEF(JSOP_FORLOCAL, 11, "forlocal", NULL, 3, 1, 1, 19, JOF_LOCAL|JOF_NAME|JOF_FOR) +OPDEF(JSOP_FORARG, 10, "forarg", NULL, 3, 1, 1, 19, JOF_QARG|JOF_NAME|JOF_FOR|JOF_TMPSLOT) +OPDEF(JSOP_FORLOCAL, 11, "forlocal", NULL, 3, 1, 1, 19, JOF_LOCAL|JOF_NAME|JOF_FOR|JOF_TMPSLOT) /* More long-standing bytecodes. */ OPDEF(JSOP_DUP, 12, "dup", NULL, 1, 1, 2, 0, JOF_BYTE) @@ -267,8 +267,8 @@ OPDEF(JSOP_LOCALDEC, 102,"localdec", NULL, 3, 0, 1, 15, JOF_LOCAL| OPDEF(JSOP_IMACOP, 103,"imacop", NULL, 1, 0, 0, 0, JOF_BYTE) /* ECMA-compliant for/in ops. */ -OPDEF(JSOP_FORNAME, 104,"forname", NULL, 3, 1, 1, 19, JOF_ATOM|JOF_NAME|JOF_FOR) -OPDEF(JSOP_FORPROP, 105,"forprop", NULL, 3, 2, 1, 18, JOF_ATOM|JOF_PROP|JOF_FOR) +OPDEF(JSOP_FORNAME, 104,"forname", NULL, 3, 1, 1, 19, JOF_ATOM|JOF_NAME|JOF_FOR|JOF_TMPSLOT3) +OPDEF(JSOP_FORPROP, 105,"forprop", NULL, 3, 2, 1, 18, JOF_ATOM|JOF_PROP|JOF_FOR|JOF_TMPSLOT3) OPDEF(JSOP_FORELEM, 106,"forelem", NULL, 1, 1, 2, 18, JOF_BYTE |JOF_ELEM|JOF_FOR) OPDEF(JSOP_POPN, 107,"popn", NULL, 3, -1, 0, 0, JOF_UINT16) @@ -313,7 +313,7 @@ OPDEF(JSOP_EVAL, 121,"eval", NULL, 3, -1, 1, 18, JOF_UINT16 /* * ECMA-compliant helper for 'for (x[i] in o)' loops. */ -OPDEF(JSOP_ENUMELEM, 122,"enumelem", NULL, 1, 3, 0, 3, JOF_BYTE |JOF_SET) +OPDEF(JSOP_ENUMELEM, 122,"enumelem", NULL, 1, 3, 0, 3, JOF_BYTE |JOF_SET|JOF_TMPSLOT) /* * Getter and setter prefix bytecodes. These modify the next bytecode, either diff --git a/js/src/jsparse.cpp b/js/src/jsparse.cpp index b7aadc241fde..99fd76400cff 100644 --- a/js/src/jsparse.cpp +++ b/js/src/jsparse.cpp @@ -1054,8 +1054,6 @@ Compiler::defineGlobals(JSContext *cx, GlobalScope &globalScope, JSScript *scrip JS_ASSERT(prop); const Shape *shape = (const Shape *)prop; def.knownSlot = shape->slot; - - globalObj->dropProperty(cx, prop); } js::Vector worklist(cx); @@ -3481,7 +3479,6 @@ DefineGlobal(JSParseNode *pn, JSCodeGenerator *cg, JSAtom *atom) JSAtomListElement *ale = globalScope->names.lookup(atom); if (!ale) { JSContext *cx = cg->parser->context; - AutoObjectLocker locker(cx, globalObj); JSObject *holder; JSProperty *prop; @@ -3492,8 +3489,6 @@ DefineGlobal(JSParseNode *pn, JSCodeGenerator *cg, JSAtom *atom) GlobalScope::GlobalDef def; if (prop) { - AutoPropertyDropper dropper(cx, globalObj, prop); - /* * A few cases where we don't bother aggressively caching: * 1) Function value changes. diff --git a/js/src/jspropertycache.cpp b/js/src/jspropertycache.cpp index d7fcc5dc8416..21e4be185b80 100644 --- a/js/src/jspropertycache.cpp +++ b/js/src/jspropertycache.cpp @@ -154,15 +154,13 @@ PropertyCache::fill(JSContext *cx, JSObject *obj, uintN scopeIndex, uintN protoI */ JS_ASSERT(pobj->hasMethodBarrier()); JSObject &funobj = shape->methodObject(); - JS_ASSERT(&funobj == &pobj->lockedGetSlot(shape->slot).toObject()); + JS_ASSERT(&funobj == &pobj->nativeGetSlot(shape->slot).toObject()); vword.setFunObj(funobj); break; } - if (!pobj->generic() && - shape->hasDefaultGetter() && - pobj->containsSlot(shape->slot)) { - const Value &v = pobj->lockedGetSlot(shape->slot); + if (!pobj->generic() && shape->hasDefaultGetter() && pobj->containsSlot(shape->slot)) { + const Value &v = pobj->nativeGetSlot(shape->slot); JSObject *funobj; if (IsFunctionObject(v, &funobj)) { diff --git a/js/src/jspropertycacheinlines.h b/js/src/jspropertycacheinlines.h index 88ef6bb2d16a..509f8a760f8d 100644 --- a/js/src/jspropertycacheinlines.h +++ b/js/src/jspropertycacheinlines.h @@ -51,7 +51,7 @@ using namespace js; /* static */ inline bool PropertyCache::matchShape(JSContext *cx, JSObject *obj, uint32 shape) { - return CX_OWNS_OBJECT_TITLE(cx, obj) && obj->shape() == shape; + return obj->shape() == shape; } /* @@ -112,7 +112,7 @@ PropertyCache::testForSet(JSContext *cx, jsbytecode *pc, JSObject *obj, PCMETER(tests++); PCMETER(settests++); JS_ASSERT(entry->kshape < SHAPE_OVERFLOW_BIT); - if (entry->kpc == pc && entry->kshape == shape && CX_OWNS_OBJECT_TITLE(cx, obj)) + if (entry->kpc == pc && entry->kshape == shape) return true; #ifdef DEBUG diff --git a/js/src/jsprvtd.h b/js/src/jsprvtd.h index 8006387fdee4..dc5c0d79f72a 100644 --- a/js/src/jsprvtd.h +++ b/js/src/jsprvtd.h @@ -293,8 +293,7 @@ typedef struct JSDebugHooks { * * If JSLookupPropOp succeeds and returns with *propp non-null, that pointer * may be passed as the prop parameter to a JSAttributesOp, as a short-cut - * that bypasses id re-lookup. In any case, a non-null *propp result after a - * successful lookup must be dropped via JSObject::dropProperty. + * that bypasses id re-lookup. * * NB: successful return with non-null *propp means the implementation may * have locked *objp and added a reference count associated with *propp, so diff --git a/js/src/jsregexp.cpp b/js/src/jsregexp.cpp index da52752667f3..a973f0ec7cf8 100644 --- a/js/src/jsregexp.cpp +++ b/js/src/jsregexp.cpp @@ -117,13 +117,9 @@ Class js::regexp_statics_class = { static void SwapObjectRegExp(JSContext *cx, JSObject *obj, RegExp &newRegExp) { - RegExp *oldRegExp; - { - AutoObjectLocker lock(cx, obj); - oldRegExp = RegExp::extractFrom(obj); - obj->setPrivate(&newRegExp); - obj->zeroRegExpLastIndex(); - } + RegExp *oldRegExp = RegExp::extractFrom(obj); + obj->setPrivate(&newRegExp); + obj->zeroRegExpLastIndex(); if (oldRegExp) oldRegExp->decref(cx); } @@ -302,7 +298,6 @@ RegExp::createFlagged(JSContext *cx, JSString *str, JSString *opt) if (!obj) \ return true; \ } \ - AutoObjectLocker(cx, obj); \ RegExp *re = RegExp::extractFrom(obj); \ code; \ return true; \ @@ -577,10 +572,8 @@ js_regexp_toString(JSContext *cx, JSObject *obj, Value *vp) static const jschar empty_regexp_ucstr[] = {'(', '?', ':', ')', 0}; if (!InstanceOf(cx, obj, &js_RegExpClass, vp + 2)) return false; - JS_LOCK_OBJ(cx, obj); RegExp *re = RegExp::extractFrom(obj); if (!re) { - JS_UNLOCK_OBJ(cx, obj); *vp = StringValue(cx->runtime->emptyString); return true; } @@ -596,7 +589,6 @@ js_regexp_toString(JSContext *cx, JSObject *obj, Value *vp) uint32 nflags = re->flagCount(); jschar *chars = (jschar*) cx->malloc((length + nflags + 1) * sizeof(jschar)); if (!chars) { - JS_UNLOCK_OBJ(cx, obj); return false; } @@ -613,7 +605,6 @@ js_regexp_toString(JSContext *cx, JSObject *obj, Value *vp) if (re->sticky()) chars[length++] = 'y'; } - JS_UNLOCK_OBJ(cx, obj); chars[length] = 0; JSString *str = js_NewString(cx, chars, length); @@ -709,7 +700,6 @@ regexp_compile_sub(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value } RegExp *clone; { - AutoObjectLocker lock(cx, &sourceObj); RegExp *re = RegExp::extractFrom(&sourceObj); if (!re) return false; @@ -758,12 +748,10 @@ regexp_exec_sub(JSContext *cx, JSObject *obj, uintN argc, Value *argv, JSBool te bool ok = InstanceOf(cx, obj, &js_RegExpClass, argv); if (!ok) return JS_FALSE; - JS_LOCK_OBJ(cx, obj); + RegExp *re = RegExp::extractFrom(obj); - if (!re) { - JS_UNLOCK_OBJ(cx, obj); + if (!re) return JS_TRUE; - } /* NB: we must reach out: after this paragraph, in order to drop re. */ re->incref(cx); @@ -782,7 +770,6 @@ regexp_exec_sub(JSContext *cx, JSObject *obj, uintN argc, Value *argv, JSBool te } else { lastIndex = 0; } - JS_UNLOCK_OBJ(cx, obj); /* Now that obj is unlocked, it's safe to (potentially) grab the GC lock. */ RegExpStatics *res = cx->regExpStatics(); diff --git a/js/src/jsregexpinlines.h b/js/src/jsregexpinlines.h index e7b07637da1d..abbaf67b1722 100644 --- a/js/src/jsregexpinlines.h +++ b/js/src/jsregexpinlines.h @@ -60,9 +60,9 @@ namespace js { extern Class regexp_statics_class; static inline JSObject * -regexp_statics_construct(JSContext *cx) +regexp_statics_construct(JSContext *cx, JSObject *parent) { - JSObject *obj = NewObject(cx, ®exp_statics_class, NULL, NULL); + JSObject *obj = NewObject(cx, ®exp_statics_class, NULL, parent); if (!obj) return NULL; RegExpStatics *res = cx->create(); diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index d6080f8c62dd..daef03699cbe 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -138,7 +138,7 @@ JS_FRIEND_DATA(JSScopeStats) js_scope_stats = {0}; #endif bool -PropertyTable::init(JSContext *cx, Shape *lastProp) +PropertyTable::init(Shape *lastProp, JSContext *cx) { int sizeLog2; @@ -156,12 +156,15 @@ PropertyTable::init(JSContext *cx, Shape *lastProp) sizeLog2 = MIN_SIZE_LOG2; } - entries = (Shape **) js_calloc(JS_BIT(sizeLog2) * sizeof(Shape *)); + /* + * Use cx->runtime->calloc for memory accounting and overpressure handling + * without OOM reporting. See PropertyTable::change. + */ + entries = (Shape **) cx->runtime->calloc(JS_BIT(sizeLog2) * sizeof(Shape *)); if (!entries) { METER(tableAllocFails); return false; } - cx->runtime->updateMallocCounter(JS_BIT(sizeLog2) * sizeof(Shape *)); hashShift = JS_DHASH_BITS - sizeLog2; for (Shape::Range r = lastProp->all(); !r.empty(); r.popFront()) { @@ -187,7 +190,7 @@ Shape::maybeHash(JSContext *cx) uint32 nentries = entryCount(); if (nentries >= PropertyTable::HASH_THRESHOLD) { table = cx->create(nentries); - return table && table->init(cx, this); + return table && table->init(this, cx); } return true; } @@ -384,7 +387,7 @@ PropertyTable::search(jsid id, bool adding) } bool -PropertyTable::change(JSContext *cx, int change) +PropertyTable::change(int log2Delta, JSContext *cx) { int oldlog2, newlog2; uint32 oldsize, newsize, nbytes; @@ -392,13 +395,18 @@ PropertyTable::change(JSContext *cx, int change) JS_ASSERT(entries); - /* Grow, shrink, or compress by changing this->entries. */ + /* + * Grow, shrink, or compress by changing this->entries. Here, we prefer + * cx->runtime->calloc to js_calloc, which on OOM waits for a background + * thread to finish sweeping and retry, if appropriate. Avoid cx->calloc + * so our caller can be in charge of whether to JS_ReportOutOfMemory. + */ oldlog2 = JS_DHASH_BITS - hashShift; - newlog2 = oldlog2 + change; + newlog2 = oldlog2 + log2Delta; oldsize = JS_BIT(oldlog2); newsize = JS_BIT(newlog2); nbytes = PROPERTY_TABLE_NBYTES(newsize); - newTable = (Shape **) cx->calloc(nbytes); + newTable = (Shape **) cx->runtime->calloc(nbytes); if (!newTable) { METER(tableAllocFails); return false; @@ -410,9 +418,6 @@ PropertyTable::change(JSContext *cx, int change) oldTable = entries; entries = newTable; - /* Treat the above calloc as a JS_malloc, to match CreateScopeTable. */ - cx->runtime->updateMallocCounter(nbytes); - /* Copy only live entries, leaving removed and free ones behind. */ for (oldspp = oldTable; oldsize != 0; oldspp++) { shape = SHAPE_FETCH(oldspp); @@ -426,8 +431,12 @@ PropertyTable::change(JSContext *cx, int change) oldsize--; } - /* Finally, free the old entries storage. */ - cx->free(oldTable); + /* + * Finally, free the old entries storage. Note that cx->runtime->free just + * calls js_free. Use js_free here to match PropertyTable::~PropertyTable, + * which cannot have a cx or rt parameter. + */ + js_free(oldTable); return true; } @@ -746,13 +755,15 @@ JSObject::addPropertyInternal(JSContext *cx, jsid id, /* Check whether we need to grow, if the load factor is >= .75. */ uint32 size = table->capacity(); if (table->entryCount + table->removedCount >= size - (size >> 2)) { - int change = table->removedCount < size >> 2; - if (!change) + int delta = table->removedCount < size >> 2; + if (!delta) METER(compresses); else METER(grows); - if (!table->change(cx, change) && table->entryCount + table->removedCount == size - 1) + if (!table->change(delta, cx) && table->entryCount + table->removedCount == size - 1) { + JS_ReportOutOfMemory(cx); return NULL; + } METER(searches); METER(changeSearches); spp = table->search(id, true); @@ -1190,7 +1201,7 @@ JSObject::removeProperty(JSContext *cx, jsid id) uint32 size = table->capacity(); if (size > PropertyTable::MIN_SIZE && table->entryCount <= size >> 2) { METER(shrinks); - (void) table->change(cx, -1); + (void) table->change(-1, cx); } } @@ -1270,7 +1281,7 @@ JSObject::methodShapeChange(JSContext *cx, const Shape &shape) JS_ASSERT(!JSID_IS_VOID(shape.id)); if (shape.isMethod()) { #ifdef DEBUG - const Value &prev = lockedGetSlot(shape.slot); + const Value &prev = nativeGetSlot(shape.slot); JS_ASSERT(&shape.methodObject() == &prev.toObject()); JS_ASSERT(canHaveMethodBarrier()); JS_ASSERT(hasMethodBarrier()); diff --git a/js/src/jsscope.h b/js/src/jsscope.h index e7979ac6e93b..c6329a37c42c 100644 --- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -249,10 +249,11 @@ struct PropertyTable { /* * NB: init and change are fallible but do not report OOM, so callers can - * cope or ignore. They do update the malloc counter on success. + * cope or ignore. They do however use JSRuntime's calloc method in order + * to update the malloc counter on success. */ - bool init(JSContext *cx, js::Shape *lastProp); - bool change(JSContext *cx, int change); + bool init(js::Shape *lastProp, JSContext *cx); + bool change(int log2Delta, JSContext *cx); js::Shape **search(jsid id, bool adding); }; @@ -260,20 +261,6 @@ struct PropertyTable { struct JSObject; -inline const js::Value & -JSObject::lockedGetSlot(uintN slot) const -{ - OBJ_CHECK_SLOT(this, slot); - return this->getSlot(slot); -} - -inline void -JSObject::lockedSetSlot(uintN slot, const js::Value &value) -{ - OBJ_CHECK_SLOT(this, slot); - this->setSlot(slot, value); -} - namespace js { class PropertyTree; @@ -861,18 +848,6 @@ Shape::isSharedPermanent() const return (~attrs & (JSPROP_SHARED | JSPROP_PERMANENT)) == 0; } -class AutoObjectLocker { - JSContext * const cx; - JSObject * const obj; - public: - AutoObjectLocker(JSContext *cx, JSObject *obj) - : cx(cx), obj(obj) { - JS_LOCK_OBJ(cx, obj); - } - - ~AutoObjectLocker() { JS_UNLOCK_OBJ(cx, obj); } -}; - } #ifdef _MSC_VER diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 8eb714160843..2281c5f35125 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -982,7 +982,7 @@ str_substring(JSContext *cx, uintN argc, Value *vp) return JS_FALSE; length = str->length(); begin = js_DoubleToInteger(d); - if (argc == 1) { + if (argc == 1 || vp[3].isUndefined()) { end = length; } else { if (!ValueToNumber(cx, vp[3], &d)) @@ -1226,8 +1226,6 @@ js_BoyerMooreHorspool(const jschar *text, jsuint textlen, return -1; } -namespace { - struct MemCmp { typedef jsuint Extent; static JS_ALWAYS_INLINE Extent computeExtent(const jschar *, jsuint patlen) { @@ -1252,8 +1250,6 @@ struct ManualCmp { } }; -} - template static jsint UnrolledMatch(const jschar *text, jsuint textlen, const jschar *pat, jsuint patlen) @@ -2719,7 +2715,7 @@ str_substr(JSContext *cx, uintN argc, Value *vp) begin = length; } - if (argc == 1) { + if (argc == 1 || vp[3].isUndefined()) { end = length; } else { if (!ValueToNumber(cx, vp[3], &d)) @@ -2816,7 +2812,7 @@ str_slice(JSContext *cx, uintN argc, Value *vp) begin = length; } - if (argc == 1) { + if (argc == 1 || vp[3].isUndefined()) { end = length; } else { if (!ValueToNumber(cx, vp[3], &end)) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 9e0a2cd7d75b..44d1815e8b24 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -298,8 +298,18 @@ ValueToTypeChar(const Value &v) /* Skip this many hits before attempting recording again, after an aborted attempt. */ #define BL_BACKOFF 32 -/* Minimum number of times a loop must execute, or else it is blacklisted. */ -#define MIN_LOOP_ITERS 8 +/* + * If, after running a trace CHECK_LOOP_ITERS times, it hasn't done MIN_LOOP_ITERS + * iterations, we blacklist it. +*/ +#define MIN_LOOP_ITERS 200 +#define LOOP_CHECK_ITERS 10 + +#ifdef DEBUG +#define LOOP_COUNT_MAX 100000000 +#else +#define LOOP_COUNT_MAX MIN_LOOP_ITERS +#endif /* Number of times we wait to exit on a side exit before we try to extend the tree. */ #define HOTEXIT 1 @@ -396,6 +406,11 @@ jitstats_getProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) *vp = INT_TO_JSVAL(HOTLOOP); return JS_TRUE; } + + if (strcmp(JS_GetStringBytes(str), "profiler") == 0) { + *vp = BOOLEAN_TO_JSVAL(cx->profilingEnabled); + return JS_TRUE; + } } if (JSID_IS_INT(id)) @@ -544,6 +559,7 @@ InitJITLogController() " abort show trace recording aborts\n" " stats show trace recording stats\n" " regexp show compilation & entry for regexps\n" + " profiler show loop profiles as they are profiled\n" " treevis spew that tracevis/tree.py can parse\n" " ------ options for Nanojit ------\n" " fragprofile count entries and exits for each fragment\n" @@ -569,6 +585,7 @@ InitJITLogController() if (strstr(tmf, "abort") || strstr(tmf, "full")) bits |= LC_TMAbort; if (strstr(tmf, "stats") || strstr(tmf, "full")) bits |= LC_TMStats; if (strstr(tmf, "regexp") || strstr(tmf, "full")) bits |= LC_TMRegexp; + if (strstr(tmf, "profiler") || strstr(tmf, "full")) bits |= LC_TMProfiler; if (strstr(tmf, "treevis")) bits |= LC_TMTreeVis; /* flags for nanojit */ @@ -1568,6 +1585,7 @@ TreeFragment::initialize(JSContext* cx, SlotList *globalSlots, bool speculate) this->maxNativeStackSlots = nStackTypes; this->maxCallDepth = 0; this->execs = 0; + this->iters = 0; } UnstableExit* @@ -2523,7 +2541,7 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag LIns* counterPtr = INS_CONSTPTR((void *) &JS_THREAD_DATA(cx)->iterationCounter); LIns* counterValue = lir->insLoad(LIR_ldi, counterPtr, 0, ACCSET_LOAD_ANY, LOAD_VOLATILE); - LIns* test = lir->ins2ImmI(LIR_lti, counterValue, MIN_LOOP_ITERS); + LIns* test = lir->ins2ImmI(LIR_lti, counterValue, LOOP_COUNT_MAX); LIns *branch = unoptimizableCondBranch(LIR_jf, test); counterValue = lir->ins2(LIR_addi, counterValue, INS_CONST(1)); /* @@ -2609,7 +2627,7 @@ TraceRecorder::finishAbort(const char* reason) AUDIT(recorderAborted); #ifdef DEBUG - debug_only_printf(LC_TMAbort, + debug_only_printf(LC_TMMinimal, "Abort recording of tree %s:%d@%d at %s:%d@%d: %s.\n", tree->treeFileName, tree->treeLineNumber, @@ -2912,6 +2930,8 @@ TraceMonitor::flush() FragProfiling_FragFinalizer(f->head, this); ) + flushEpoch++; + frameCache->reset(); dataAlloc->reset(); traceAlloc->reset(); @@ -2919,6 +2939,7 @@ TraceMonitor::flush() tempAlloc->reset(); reTempAlloc->reset(); oracle->clear(); + loopProfiles->clear(); Allocator& alloc = *dataAlloc; @@ -5663,18 +5684,11 @@ CheckGlobalObjectShape(JSContext* cx, TraceMonitor* tm, JSObject* globalObj, * that it isn't the global at run time. */ if (!globalObj->hasOwnShape()) { - JS_LOCK_OBJ(cx, globalObj); - bool ok = globalObj->globalObjectOwnShapeChange(cx); - JS_UNLOCK_OBJ(cx, globalObj); - if (!ok) { + if (!globalObj->globalObjectOwnShapeChange(cx)) { debug_only_print0(LC_TMTracer, "Can't record: failed to give globalObj a unique shape.\n"); return false; } - } else { - /* Claim the title so we don't abort at the top of recordLoopEdge. */ - JS_LOCK_OBJ(cx, globalObj); - JS_UNLOCK_OBJ(cx, globalObj); } uint32 globalShape = globalObj->shape(); @@ -6051,6 +6065,10 @@ AttemptToExtendTree(JSContext* cx, VMSideExit* anchor, VMSideExit* exitedFrom, * tail duplication. */ if (f->branchCount >= MAX_BRANCHES) { +#ifdef JS_METHODJIT + if (cx->methodJitEnabled && cx->profilingEnabled) + Blacklist((jsbytecode *)f->ip); +#endif #ifdef MOZ_TRACEVIS if (tvso) tvso->r = R_FAIL_EXTEND_MAX_BRANCHES; #endif @@ -6112,7 +6130,7 @@ AttemptToExtendTree(JSContext* cx, VMSideExit* anchor, VMSideExit* exitedFrom, } JS_ASSERT(ngslots >= anchor->numGlobalSlots); bool rv = TraceRecorder::startRecorder(cx, anchor, c, stackSlots, ngslots, typeMap, - exitedFrom, outerScript, outerPC, entryFrameArgc(cx), + exitedFrom, outerScript, outerPC, f->argc, hits < maxHits); #ifdef MOZ_TRACEVIS if (!rv && tvso) @@ -6143,14 +6161,6 @@ RecordingIfTrue(bool b) JS_REQUIRES_STACK MonitorResult TraceRecorder::recordLoopEdge(JSContext* cx, TraceRecorder* r, uintN& inlineCallCount) { -#ifdef JS_THREADSAFE - /* If changing this, see "Claim the title" in CheckGlobalObjectShape. */ - if (cx->fp()->scopeChain().getGlobal()->title.ownercx != cx) { - AbortRecording(cx, "Global object not owned by this context"); - return MONITOR_NOT_RECORDING; /* we stay away from shared global objects */ - } -#endif - TraceMonitor* tm = &JS_TRACE_MONITOR(cx); /* Process needFlush and deep abort requests. */ @@ -6743,11 +6753,13 @@ ExecuteTree(JSContext* cx, TreeFragment* f, uintN& inlineCallCount, /* Execute trace. */ JS_THREAD_DATA(cx)->iterationCounter = 0; + debug_only(int64 t0 = PRMJ_Now();) #ifdef MOZ_TRACEVIS VMSideExit* lr = (TraceVisStateObj(cx, S_NATIVE), ExecuteTrace(cx, f, state)); #else VMSideExit* lr = ExecuteTrace(cx, f, state); #endif + debug_only(int64 t1 = PRMJ_Now();) JS_ASSERT(*(uint64*)&tm->storage->global()[globalSlots] == 0xdeadbeefdeadbeefLL); JS_ASSERT_IF(lr->exitType == LOOP_EXIT, !lr->calldepth); @@ -6759,11 +6771,33 @@ ExecuteTree(JSContext* cx, TreeFragment* f, uintN& inlineCallCount, bool ok = !(state.builtinStatus & BUILTIN_ERROR); JS_ASSERT_IF(cx->throwing, !ok); + size_t iters = JS_THREAD_DATA(cx)->iterationCounter; + + f->execs++; + f->iters += iters; + +#ifdef DEBUG + JSStackFrame *fp = cx->fp(); + const char *prefix = ""; + if (iters == LOOP_COUNT_MAX) + prefix = ">"; + debug_only_printf(LC_TMMinimal, " [%.3f ms] Tree at line %u executed for %s%u iterations;" + " executed %u times; leave for %s at %s:%u (%s)\n", + double(t1-t0) / PRMJ_USEC_PER_MSEC, + f->treeLineNumber, prefix, (uintN)iters, f->execs, + getExitName(lr->exitType), + fp->script()->filename, + js_FramePCToLineNumber(cx, fp), + js_CodeName[fp->hasImacropc() ? *fp->imacropc() : *cx->regs->pc]); +#endif + #ifdef JS_METHODJIT if (cx->methodJitEnabled) { - if (lr->exitType == LOOP_EXIT && JS_THREAD_DATA(cx)->iterationCounter < MIN_LOOP_ITERS) { - debug_only_printf(LC_TMTracer, "tree %p executed only %d iterations, blacklisting\n", - (void*)f, f->execs); + if (lr->exitType == LOOP_EXIT && f->iters < MIN_LOOP_ITERS + && f->execs >= LOOP_CHECK_ITERS) + { + debug_only_printf(LC_TMMinimal, " Blacklisting at line %u (executed only %d iters)\n", + f->treeLineNumber, f->iters); Blacklist((jsbytecode *)f->ip); } } @@ -7114,7 +7148,7 @@ LeaveTree(TraceMonitor *tm, TracerState& state, VMSideExit* lr) } JS_REQUIRES_STACK MonitorResult -MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount) +RecordLoopEdge(JSContext* cx, uintN& inlineCallCount) { #ifdef MOZ_TRACEVIS TraceVisStateObj tvso(cx, S_MONITOR); @@ -7139,7 +7173,7 @@ MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount) * one. If we arrive here, that tree didn't run to completion and * instead we mis-matched or the inner tree took a side exit other than * the loop exit. We are thus no longer guaranteed to be parked on the - * same loop header js_MonitorLoopEdge was called for. In fact, this + * same loop header RecordLoopEdge was called for. In fact, this * might not even be a loop header at all. Hence if the program counter * no longer hovers over the inner loop header, return to the * interpreter and do not attempt to trigger or record a new tree at @@ -7754,10 +7788,18 @@ InitJIT(TraceMonitor *tm) tm->oracle = new Oracle(); + tm->profile = NULL; + tm->recordAttempts = new RecordAttemptMap; if (!tm->recordAttempts->init(PC_HASH_COUNT)) abort(); + tm->loopProfiles = new LoopProfileMap; + if (!tm->loopProfiles->init(PC_HASH_COUNT)) + abort(); + + tm->flushEpoch = 0; + JS_ASSERT(!tm->dataAlloc && !tm->traceAlloc && !tm->codeAlloc); tm->dataAlloc = new VMAllocator(); tm->traceAlloc = new VMAllocator(); @@ -7836,6 +7878,7 @@ FinishJIT(TraceMonitor *tm) #endif delete tm->recordAttempts; + delete tm->loopProfiles; delete tm->oracle; #ifdef DEBUG @@ -8177,23 +8220,16 @@ TraceRecorder::scopeChainProp(JSObject* chainHead, Value*& vp, LIns*& ins, NameR LIns *obj_ins; CHECK_STATUS_A(traverseScopeChain(chainHead, head_ins, obj, obj_ins)); - if (obj2 != obj) { - obj2->dropProperty(cx, prop); + if (obj2 != obj) RETURN_STOP_A("prototype property"); - } Shape* shape = (Shape*) prop; - if (!isValidSlot(obj, shape)) { - JS_UNLOCK_OBJ(cx, obj2); + if (!isValidSlot(obj, shape)) return ARECORD_STOP; - } - if (!lazilyImportGlobalSlot(shape->slot)) { - JS_UNLOCK_OBJ(cx, obj2); + if (!lazilyImportGlobalSlot(shape->slot)) RETURN_STOP_A("lazy import of global slot failed"); - } vp = &obj->getSlotRef(shape->slot); ins = get(vp); - JS_UNLOCK_OBJ(cx, obj2); nr.tracked = true; return ARECORD_CONTINUE; } @@ -8201,11 +8237,9 @@ TraceRecorder::scopeChainProp(JSObject* chainHead, Value*& vp, LIns*& ins, NameR if (obj == obj2 && obj->isCall()) { AbortableRecordingStatus status = InjectStatus(callProp(obj, prop, ATOM_TO_JSID(atom), vp, ins, nr)); - JS_UNLOCK_OBJ(cx, obj); return status; } - obj2->dropProperty(cx, prop); RETURN_STOP_A("fp->scopeChain is not global or active call object"); } @@ -9599,7 +9633,6 @@ TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2 RETURN_STOP_A("cannot cache name"); } else { TraceMonitor &localtm = *traceMonitor; - JSContext *localcx = cx; int protoIndex = js_LookupPropertyWithFlags(cx, aobj, id, cx->resolveFlags, &obj2, &prop); @@ -9608,11 +9641,8 @@ TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2 RETURN_ERROR_A("error in js_LookupPropertyWithFlags"); /* js_LookupPropertyWithFlags can reenter the interpreter and kill |this|. */ - if (!localtm.recorder) { - if (prop) - obj2->dropProperty(localcx, prop); + if (!localtm.recorder) return ARECORD_ABORTED; - } if (prop) { if (!obj2->isNative()) @@ -9637,7 +9667,6 @@ TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2 return ARECORD_CONTINUE; } - obj2->dropProperty(cx, prop); if (!entry) RETURN_STOP_A("failed to fill property cache"); } @@ -9647,7 +9676,7 @@ TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2 // enough to share mutable objects on the scope or proto chain, but we // don't care about such insane embeddings. Anyway, the (scope, proto) // entry->vcap coordinates must reach obj2 from aobj at this point. - JS_ASSERT(cx->thread->requestDepth); + JS_ASSERT(cx->thread->data.requestDepth); #endif return InjectStatus(guardPropertyCacheHit(obj_ins, aobj, obj2, entry, pcval)); @@ -10550,13 +10579,6 @@ TraceRecorder::record_LeaveFrame() { debug_only_stmt(JSStackFrame *fp = cx->fp();) - debug_only_printf(LC_TMTracer, - "LeaveFrame (back to %s), callDepth=%d\n", - fp->isFunctionFrame() - ? js_AtomToPrintableString(cx, fp->fun()->atom) - : "global code", - callDepth); - JS_ASSERT(js_CodeSpec[js_GetOpcode(cx, fp->script(), cx->regs->pc)].length == JSOP_CALL_LENGTH); @@ -11818,7 +11840,16 @@ DeleteIntKey(JSContext* cx, JSObject* obj, int32 i, JSBool strict) { LeaveTraceIfGlobalObject(cx, obj); Value v = BooleanValue(false); - jsid id = INT_TO_JSID(i); + jsid id; + if (INT_FITS_IN_JSID(i)) { + id = INT_TO_JSID(i); + } else { + if (!js_ValueToStringId(cx, Int32Value(i), &id)) { + SetBuiltinError(cx); + return false; + } + } + if (!obj->deleteProperty(cx, id, &v, strict)) SetBuiltinError(cx); return v.toBoolean(); @@ -12611,7 +12642,6 @@ GetPropertyWithNativeGetter(JSContext* cx, JSObject* obj, Shape* shape, Value* v JSObject* pobj; JS_ASSERT(obj->lookupProperty(cx, shape->id, &pobj, &prop)); JS_ASSERT(prop == (JSProperty*) shape); - pobj->dropProperty(cx, prop); #endif // Shape::get contains a special case for With objects. We can elide it @@ -15128,7 +15158,6 @@ TraceRecorder::record_JSOP_IN() x = lir->ins2ImmI(LIR_eqi, x, 1); TraceMonitor &localtm = *traceMonitor; - JSContext *localcx = cx; JSObject* obj2; JSProperty* prop; @@ -15138,15 +15167,10 @@ TraceRecorder::record_JSOP_IN() RETURN_ERROR_A("obj->lookupProperty failed in JSOP_IN"); /* lookupProperty can reenter the interpreter and kill |this|. */ - if (!localtm.recorder) { - if (prop) - obj2->dropProperty(localcx, prop); + if (!localtm.recorder) return ARECORD_ABORTED; - } bool cond = prop != NULL; - if (prop) - obj2->dropProperty(cx, prop); /* * The interpreter fuses comparisons and the following branch, so we have @@ -15964,6 +15988,12 @@ TraceRecorder::record_JSOP_CALLELEM() JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_STOP() { + /* A return from callDepth 0 terminates the current loop, except for recursion. */ + if (callDepth == 0) { + AUDIT(returnLoopExits); + return endLoop(); + } + JSStackFrame *fp = cx->fp(); if (fp->hasImacropc()) { @@ -16610,21 +16640,21 @@ TraceRecorder::determineGlobalTypes(JSValueType* typeMap) class AutoRetBlacklist { jsbytecode* pc; - bool& blacklist; + bool* blacklist; public: - AutoRetBlacklist(jsbytecode* pc, bool& blacklist) + AutoRetBlacklist(jsbytecode* pc, bool* blacklist) : pc(pc), blacklist(blacklist) { } ~AutoRetBlacklist() { - blacklist = IsBlacklisted(pc); + *blacklist = IsBlacklisted(pc); } }; JS_REQUIRES_STACK TracePointAction -MonitorTracePoint(JSContext* cx, uintN& inlineCallCount, bool& blacklist) +RecordTracePoint(JSContext* cx, uintN& inlineCallCount, bool* blacklist, bool execAllowed) { JSStackFrame* fp = cx->fp(); TraceMonitor* tm = &JS_TRACE_MONITOR(cx); @@ -16658,6 +16688,12 @@ MonitorTracePoint(JSContext* cx, uintN& inlineCallCount, bool& blacklist) VMSideExit* lr = NULL; VMSideExit* innermostNestedGuard = NULL; + if (!execAllowed) { + /* We've already compiled a trace for it, but we don't want to use that trace. */ + Blacklist((jsbytecode*)tree->root->ip); + return TPA_Nothing; + } + /* Best case - just go and execute. */ if (!ExecuteTree(cx, match, inlineCallCount, &innermostNestedGuard, &lr)) return TPA_Error; @@ -16721,11 +16757,564 @@ MonitorTracePoint(JSContext* cx, uintN& inlineCallCount, bool& blacklist) if (!Interpret(cx, fp, inlineCallCount, JSINTERP_RECORD)) return TPA_Error; + JS_ASSERT(!cx->throwing); + return TPA_RanStuff; } +LoopProfile::LoopProfile(JSScript *script, jsbytecode *top, jsbytecode *bottom) + : script(script), + top(top), + bottom(bottom), + hits(0), + profiled(false), + traceOK(false), + numAllOps(0), + numSelfOps(0), + numSelfOpsMult(0), + branchMultiplier(1), + shortLoop(false), + maybeShortLoop(false), + numInnerLoops(0), + loopStackDepth(0), + sp(0) +{ + memset(allOps, 0, sizeof(allOps)); + memset(selfOps, 0, sizeof(selfOps)); +} + +MonitorResult +LoopProfile::profileLoopEdge(JSContext* cx, uintN& inlineCallCount) +{ + if (cx->regs->pc == top) { + debug_only_print0(LC_TMProfiler, "Profiling complete (edge)\n"); + decide(cx); + } else { + /* Record an inner loop invocation. */ + JSScript *script = cx->fp()->script(); + jsbytecode *pc = cx->regs->pc; + bool found = false; + + /* We started with the most deeply nested one first, since it gets hit most often.*/ + for (int i = int(numInnerLoops)-1; i >= 0; i--) { + if (innerLoops[i].script == script && innerLoops[i].top == pc) { + innerLoops[i].iters++; + found = true; + } + } + + if (!found && numInnerLoops < PROFILE_MAX_INNER_LOOPS) + innerLoops[numInnerLoops++] = InnerLoop(script, pc, NULL); + } + + return MONITOR_NOT_RECORDING; +} + + +static const uintN PROFILE_HOTLOOP = 61; +static const uintN MAX_PROFILE_OPS = 4096; + +static jsbytecode * +GetLoopBottom(JSContext *cx) +{ + jsbytecode* pc = cx->regs->pc; + JSScript *script = cx->fp()->script(); + jssrcnote *sn = js_GetSrcNote(script, pc); + if (!sn) + return NULL; + return pc + js_GetSrcNoteOffset(sn, 0); +} + +static LoopProfile * +LookupOrAddProfile(JSContext *cx, TraceMonitor *tm, void** traceData, uintN *traceEpoch) +{ + LoopProfile *prof; + + /* + * We try to keep a pointer to the loop profile inside the TRACE IC. + * We also keep a pointer inside a hashtable for when we need to + * look up nested loops (or when ICs are disabled). + * + * Memory for the profile is allocated in the dataAlloc for the + * trace monitor. Since this thing can get flushed periodically, + * we use epochs to decide if the profile in the MIC is valid, as + * follows. Every time the trace monitor is flushed, + * |tm->flushEpoch| is incremented. When storing the profile in + * the IC, we store the current |tm->flushEpoch| along with it. + * Before pulling a profile out of the IC, we check that its + * stored epoch is still up-to-date with |tm->flushEpoch|. + * This ensures that no flush has happened in between. + */ + +#if JS_MONOIC + if (*traceData && *traceEpoch == tm->flushEpoch) { + prof = (LoopProfile *)*traceData; + } else { + jsbytecode* pc = cx->regs->pc; + jsbytecode* bottom = GetLoopBottom(cx); + if (!bottom) + return NULL; + prof = new (*tm->dataAlloc) LoopProfile(cx->fp()->script(), pc, bottom); + *traceData = prof; + *traceEpoch = tm->flushEpoch; + tm->loopProfiles->put(pc, prof); + } +#else + LoopProfileMap &table = *tm->loopProfiles; + jsbytecode* pc = cx->regs->pc; + if (LoopProfileMap::AddPtr p = table.lookupForAdd(pc)) { + prof = p->value; + } else { + jsbytecode* bottom = GetLoopBottom(cx); + if (!bottom) + return NULL; + prof = new (*tm->dataAlloc) LoopProfile(cx->fp()->script(), pc, bottom); + table.add(p, pc, prof); + } #endif + return prof; +} + +JS_REQUIRES_STACK TracePointAction +MonitorTracePoint(JSContext *cx, uintN& inlineCallCount, bool* blacklist, + void** traceData, uintN *traceEpoch) +{ + if (!cx->profilingEnabled) + return RecordTracePoint(cx, inlineCallCount, blacklist, true); + + *blacklist = false; + + TraceMonitor *tm = &JS_TRACE_MONITOR(cx); + /* + * We may have re-entered Interpret while profiling. We don't profile + * the nested invocation. + */ + if (tm->profile) + return TPA_Nothing; + + LoopProfile *prof = LookupOrAddProfile(cx, tm, traceData, traceEpoch); + if (!prof) { + *blacklist = true; + return TPA_Nothing; + } + + if (prof->hits++ < PROFILE_HOTLOOP) + return TPA_Nothing; + + AutoRetBlacklist autoRetBlacklist(cx->regs->pc, blacklist); + + if (prof->profiled) { + if (prof->traceOK) { + return RecordTracePoint(cx, inlineCallCount, blacklist, prof->execOK); + } else { + return TPA_Nothing; + } + } + + debug_only_printf(LC_TMProfiler, "Profiling at line %d\n", + js_FramePCToLineNumber(cx, cx->fp())); + + tm->profile = prof; + + if (!Interpret(cx, cx->fp(), inlineCallCount, JSINTERP_PROFILE)) + return TPA_Error; + + JS_ASSERT(!cx->throwing); + + return TPA_RanStuff; +} + +/* + * Returns true if pc is within the given loop. + * If we're in a different script, then we must have come from + * a call instruction within the loop (since we check if we're within + * the loop before each instruction) so we're still in the loop. + */ +template +static inline bool +PCWithinLoop(JSScript *script, jsbytecode *pc, T& loop) +{ + return script != loop.script || (pc >= loop.top && pc <= loop.bottom); +} + +LoopProfile::ProfileAction +LoopProfile::profileOperation(JSContext* cx, JSOp op) +{ + TraceMonitor* tm = &JS_TRACE_MONITOR(cx); + + if (profiled) { + tm->profile = NULL; + return ProfComplete; + } + + jsbytecode *pc = cx->regs->pc; + JSScript *script = cx->fp()->maybeScript(); + + if (!PCWithinLoop(script, pc, *this)) { + debug_only_printf(LC_TMProfiler, "Profiling complete (loop exit) at %d (line %u)\n", + (int)(cx->regs->pc - cx->fp()->script()->code), + js_FramePCToLineNumber(cx, cx->fp())); + tm->profile->decide(cx); + tm->profile = NULL; + return ProfComplete; + } + + while (loopStackDepth > 0 && !PCWithinLoop(script, pc, loopStack[loopStackDepth-1])) { + debug_only_print0(LC_TMProfiler, "Profiler: Exiting inner loop\n"); + loopStackDepth--; + } + + if (op == JSOP_TRACE || op == JSOP_NOTRACE) { + if (pc != top && (loopStackDepth == 0 || pc != loopStack[loopStackDepth-1].top)) { + if (loopStackDepth == PROFILE_MAX_INNER_LOOPS) { + debug_only_print0(LC_TMProfiler, "Profiling complete (maxnest)\n"); + tm->profile->decide(cx); + tm->profile = NULL; + return ProfComplete; + } + + debug_only_print0(LC_TMProfiler, "Profiler: Entering inner loop\n"); + loopStack[loopStackDepth++] = InnerLoop(script, pc, GetLoopBottom(cx)); + } + } + + numAllOps++; + if (loopStackDepth == 0) { + numSelfOps++; + numSelfOpsMult += branchMultiplier; + } + + if (op == JSOP_ADD || op == JSOP_SUB || op == JSOP_MUL || op == JSOP_DIV) { + Value& v1 = cx->regs->sp[-1]; + Value& v2 = cx->regs->sp[-2]; + + /* If either operand is a double, treat it as a floating-point op. */ + if (v1.isDouble() || v2.isDouble()) + increment(OP_FLOAT); + else if (v1.isInt32() || v2.isInt32()) + increment(OP_INT); + } + + if (op == JSOP_EQ || op == JSOP_NE) + increment(OP_EQ); + + if (op == JSOP_BITOR || op == JSOP_BITXOR || op == JSOP_BITAND + || op == JSOP_LSH || op == JSOP_RSH || op == JSOP_URSH || op == JSOP_BITNOT) + { + increment(OP_BIT); + } + + if (op == JSOP_EVAL) + increment(OP_EVAL); + + if (op == JSOP_NEW) + increment(OP_NEW); + + if (op == JSOP_GETELEM || op == JSOP_SETELEM) { + Value& lval = cx->regs->sp[op == JSOP_GETELEM ? -2 : -3]; + if (lval.isObject() && js_IsTypedArray(&lval.toObject())) + increment(OP_TYPED_ARRAY); + } + + if (op == JSOP_CALL) { + increment(OP_CALL); + + uintN argc = GET_ARGC(cx->regs->pc); + Value &v = cx->regs->sp[-((int)argc + 2)]; + JSObject *callee; + if (IsFunctionObject(v, &callee)) { + JSFunction *fun = callee->getFunctionPrivate(); + if (fun->isInterpreted()) { + if (cx->fp()->isFunctionFrame() && fun == cx->fp()->fun()) + increment(OP_RECURSIVE); + } else { + js::Native native = fun->u.n.native; + if (js_IsMathFunction(JS_JSVALIFY_NATIVE(native))) + increment(OP_FLOAT); + } + } + } + + if (op == JSOP_CALLPROP && loopStackDepth == 0) + branchMultiplier *= mjit::GetCallTargetCount(cx->fp()->script(), cx->regs->pc); + + if (numAllOps >= MAX_PROFILE_OPS) { + debug_only_print0(LC_TMProfiler, "Profiling complete (maxops)\n"); + tm->profile->decide(cx); + tm->profile = NULL; + return ProfComplete; + } + + /* These are the places where the interpreter skips over branches. */ + jsbytecode *testPC = cx->regs->pc; + if (op == JSOP_EQ || op == JSOP_NE || op == JSOP_LT || op == JSOP_GT + || op == JSOP_LE || op == JSOP_GE || op == JSOP_IN || op == JSOP_MOREITER) + { + const JSCodeSpec *cs = &js_CodeSpec[op]; + ptrdiff_t oplen = cs->length; + JSScript *script = cx->fp()->script(); + JS_ASSERT(oplen != -1); + + if (cx->regs->pc - script->code + oplen < ptrdiff_t(script->length)) + if (cx->regs->pc[oplen] == JSOP_IFEQ || cx->regs->pc[oplen] == JSOP_IFNE) + testPC = cx->regs->pc + oplen; + } + + /* Check if we're exiting the loop being profiled. */ + JSOp testOp = js_GetOpcode(cx, cx->fp()->script(), testPC); + if (testOp == JSOP_IFEQ || testOp == JSOP_IFNE || testOp == JSOP_GOTO + || testOp == JSOP_AND || testOp == JSOP_OR) + { + ptrdiff_t len = GET_JUMP_OFFSET(testPC); + if (testPC + len == top && (op == JSOP_LT || op == JSOP_LE)) { + StackValue v = stackAt(-1); + if (v.hasValue && v.value < 8) + shortLoop = true; + } + + if (testPC + len == top && (op == JSOP_LT || op == JSOP_LE) + && cx->regs->sp[-2].isInt32() && cx->regs->sp[-2].toInt32() < 16) + { + maybeShortLoop = true; + } + + if (testOp != JSOP_GOTO && len > 0) { + bool isConst; + if (testOp == JSOP_IFEQ || testOp == JSOP_IFNE) + isConst = stackAt(-1).isConst && stackAt(-2).isConst; + else + isConst = stackAt(-1).isConst; + + increment(OP_FWDJUMP); + if (loopStackDepth == 0 && !isConst) + branchMultiplier *= 2; + } + } + + if (op == JSOP_INT8) { + stackPush(StackValue(true, GET_INT8(cx->regs->pc))); + } else if (op == JSOP_STRING) { + stackPush(StackValue(true)); + } else if (op == JSOP_TYPEOF || op == JSOP_TYPEOFEXPR) { + stackPush(StackValue(true)); + } else if (op == JSOP_EQ || op == JSOP_NE) { + StackValue v1 = stackAt(-1); + StackValue v2 = stackAt(-2); + stackPush(StackValue(v1.isConst && v2.isConst)); + } else if (op == JSOP_AND) { + bool b = !!js_ValueToBoolean(cx->regs->sp[-1]); + StackValue v = stackAt(-1); + if (b) + stackPop(); + } else { + stackClear(); + } + + return ProfContinue; +} + +static LoopProfile * +LookupLoopProfile(JSContext *cx, jsbytecode *pc) +{ + TraceMonitor* tm = &JS_TRACE_MONITOR(cx); + LoopProfileMap &table = *tm->loopProfiles; + if (LoopProfileMap::Ptr p = table.lookup(pc)) { + JS_ASSERT(p->value->top == pc); + return p->value; + } else + return NULL; +} + +/* + * Returns true if the loop would probably take a long time to + * compile. Since this function recurses into nested loops, we + * pass a depth argument to ensure that we don't recurse too + * far and overflow the stack. Mostly, we're guarding against + * the possibility that we (incorrectly) track a loop as being + * nested inside itself, leading to infinite recursion. + */ +bool +LoopProfile::isCompilationExpensive(JSContext *cx, uintN depth) +{ + if (depth == 0) + return true; + + /* Too many ops to compile? */ + if (numSelfOps == MAX_PROFILE_OPS) + return true; + + /* Is the code too branchy? */ + if (numSelfOpsMult >= numSelfOps*100000) + return true; + + /* Ensure that inner loops aren't too expensive. */ + for (uintN i=0; iisCompilationExpensive(cx, depth-1)) + return true; + } + + return false; +} + +/* + * This function recognizes loops that are short and that contain + * jumps. The tracer does badly with these loops because it + * needs to do a lot of side exits, which are somewhat + * expensive. + */ +bool +LoopProfile::isCompilationUnprofitable(JSContext *cx, uintN depth) +{ + if (depth == 0) + return true; + + if (numAllOps < 15 && allOps[OP_FWDJUMP]) + return true; + + /* Ensure that inner loops aren't fleeting. */ + for (uintN i=0; iisCompilationUnprofitable(cx, depth-1)) + return true; + } + + return false; +} + +/* After profiling is done, this method decides whether to trace the loop. */ +void +LoopProfile::decide(JSContext *cx) +{ + profiled = true; + +#ifdef DEBUG + uintN line = js_PCToLineNumber(cx, script, top); + + debug_only_printf(LC_TMProfiler, "LOOP %s:%d\n", script->filename, line); + + for (uintN i=0; iscript, prof->top); + debug_only_printf(LC_TMProfiler, "NESTED %s:%d (%d iters)\n", + prof->script->filename, line, loop.iters); + } + } + debug_only_printf(LC_TMProfiler, "FEATURE float %d\n", allOps[OP_FLOAT]); + debug_only_printf(LC_TMProfiler, "FEATURE int %d\n", allOps[OP_INT]); + debug_only_printf(LC_TMProfiler, "FEATURE bit %d\n", allOps[OP_BIT]); + debug_only_printf(LC_TMProfiler, "FEATURE equality %d\n", allOps[OP_EQ]); + debug_only_printf(LC_TMProfiler, "FEATURE eval %d\n", allOps[OP_EVAL]); + debug_only_printf(LC_TMProfiler, "FEATURE new %d\n", allOps[OP_NEW]); + debug_only_printf(LC_TMProfiler, "FEATURE call %d\n", allOps[OP_CALL]); + debug_only_printf(LC_TMProfiler, "FEATURE typedarray %d\n", allOps[OP_TYPED_ARRAY]); + debug_only_printf(LC_TMProfiler, "FEATURE fwdjump %d\n", allOps[OP_FWDJUMP]); + debug_only_printf(LC_TMProfiler, "FEATURE recursive %d\n", allOps[OP_RECURSIVE]); + debug_only_printf(LC_TMProfiler, "FEATURE shortLoop %d\n", shortLoop); + debug_only_printf(LC_TMProfiler, "FEATURE maybeShortLoop %d\n", maybeShortLoop); + debug_only_printf(LC_TMProfiler, "FEATURE numAllOps %d\n", numAllOps); + debug_only_printf(LC_TMProfiler, "FEATURE selfOps %d\n", numSelfOps); + debug_only_printf(LC_TMProfiler, "FEATURE selfOpsMult %g\n", numSelfOpsMult); +#endif + + traceOK = false; + if (count(OP_RECURSIVE)) { + /* don't trace */ + } else if (count(OP_EVAL)) { + /* don't trace */ + } else if (numInnerLoops > 3) { + /* don't trace */ + } else if (shortLoop) { + /* don't trace */ + } else if (maybeShortLoop && numInnerLoops < 2) { + /* don't trace */ + } else if (isCompilationExpensive(cx, 4)) { + /* don't trace */ + } else if (isCompilationUnprofitable(cx, 4)) { + /* don't trace */ + } else { + uintN goodOps = 0; + + /* The tracer handles these ops well because of type specialization. */ + goodOps += count(OP_FLOAT)*10 + count(OP_BIT)*10 + count(OP_INT)*5; + + /* The tracer handles these ops well because of inlining. */ + goodOps += (count(OP_CALL) + count(OP_NEW))*20; + + /* The tracer specialized typed array access. */ + goodOps += count(OP_TYPED_ARRAY)*10; + + debug_only_printf(LC_TMProfiler, "FEATURE goodOps %u\n", goodOps); + + if (goodOps >= numAllOps) + traceOK = true; + } + + debug_only_printf(LC_TMProfiler, "TRACE %s:%d = %d\n", script->filename, line, traceOK); + + if (traceOK) { + /* Unblacklist the inner loops. */ + for (uintN i=0; iprofiled = true; + prof->traceOK = true; + if (IsBlacklisted(loop.top)) + debug_only_printf(LC_TMProfiler, "Unblacklisting at %d\n", + js_PCToLineNumber(cx, loop.script, loop.top)); + Unblacklist(loop.script, loop.top); + } + } + } + + if (!traceOK) { + debug_only_printf(LC_TMProfiler, "Blacklisting at %d\n", line); + Blacklist(top); + } + + debug_only_print0(LC_TMProfiler, "\n"); + + execOK = traceOK; +} + +JS_REQUIRES_STACK MonitorResult +MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount) +{ + TraceMonitor *tm = &JS_TRACE_MONITOR(cx); + if (tm->profile) + return tm->profile->profileLoopEdge(cx, inlineCallCount); + else + return RecordLoopEdge(cx, inlineCallCount); +} + +void +AbortProfiling(JSContext *cx) +{ + debug_only_print0(LC_TMProfiler, "Profiling complete (aborted)\n"); + TraceMonitor *tm = &JS_TRACE_MONITOR(cx); + tm->profile->numSelfOps = MAX_PROFILE_OPS; + tm->profile->decide(cx); + tm->profile = NULL; +} + +#else /* JS_METHODJIT */ + +JS_REQUIRES_STACK MonitorResult +MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount) +{ + return RecordLoopEdge(cx, inlineCallCount); +} + +#endif /* JS_METHODJIT */ + } /* namespace js */ diff --git a/js/src/jstracer.h b/js/src/jstracer.h index 3c96f9dff8c4..bd773db1e43b 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -243,7 +243,8 @@ enum LC_TMBits { LC_TMAbort = 1<<19, LC_TMStats = 1<<20, LC_TMRegexp = 1<<21, - LC_TMTreeVis = 1<<22 + LC_TMTreeVis = 1<<22, + LC_TMProfiler = 1<<23 }; #endif @@ -633,7 +634,10 @@ struct TreeFragment : public LinkableFragment Queue gcthings; Queue shapes; unsigned maxNativeStackSlots; + /* Gives the number of times we have entered this trace. */ uintN execs; + /* Gives the total number of iterations executed by the trace (up to a limit). */ + uintN iters; inline unsigned nGlobalTypes() { return typeMap.length() - nStackTypes; @@ -656,6 +660,180 @@ VMFragment::toTreeFragment() return static_cast(this); } +enum MonitorResult { + MONITOR_RECORDING, + MONITOR_NOT_RECORDING, + MONITOR_ERROR +}; + +const uintN PROFILE_MAX_INNER_LOOPS = 8; +const uintN PROFILE_MAX_STACK = 6; + +/* + * A loop profile keeps track of the instruction mix of a hot loop. We use this + * information to predict whether tracing would be beneficial for the loop. + */ +class LoopProfile +{ +public: + /* Instructions are divided into a few categories. */ + enum OpKind { + OP_FLOAT, // Floating point arithmetic + OP_INT, // Integer arithmetic + OP_BIT, // Bit operations + OP_EQ, // == and != + OP_EVAL, // Calls to eval() + OP_CALL, // JSOP_CALL instructions + OP_FWDJUMP, // Jumps with positive delta + OP_NEW, // JSOP_NEW instructions + OP_RECURSIVE, // Recursive calls + OP_TYPED_ARRAY, // Accesses to typed arrays + OP_LIMIT + }; + + /* The script in which the loop header lives. */ + JSScript *script; + + /* The bytecode locations of the loop header and the back edge. */ + jsbytecode *top, *bottom; + + /* Number of times we have seen this loop executed; used to decide when to profile. */ + uintN hits; + + /* Whether we have run a complete profile of the loop. */ + bool profiled; + + /* If we have profiled the loop, this saves the decision of whether to trace it. */ + bool traceOK; + + /* + * Sometimes loops are not good tracing opportunities, but they are nested inside + * loops that we want to trace. In that case, we set their traceOK flag to true, + * but we set execOK to false. That way, the loop is traced so that it can be + * integrated into the outer trace. But we never execute the trace on its only. + */ + bool execOK; + + /* Instruction mix for the loop and total number of instructions. */ + uintN allOps[OP_LIMIT]; + uintN numAllOps; + + /* Instruction mix and total for the loop, excluding nested inner loops. */ + uintN selfOps[OP_LIMIT]; + uintN numSelfOps; + + /* + * A prediction of the number of instructions we would have to compile + * for the loop. This takes into account the fact that a branch may cause us to + * compile every instruction after it twice. Polymorphic calls are + * treated as n-way branches. + */ + double numSelfOpsMult; + + /* + * This keeps track of the number of times that every succeeding instruction + * in the trace will have to be compiled. Every time we hit a branch, we + * double this number. Polymorphic calls multiply it by n (for n-way + * polymorphism). + */ + double branchMultiplier; + + /* Set to true if the loop is short (i.e., has fewer than 8 iterations). */ + bool shortLoop; + + /* Set to true if the loop may be short (has few iterations at profiling time). */ + bool maybeShortLoop; + + /* + * When we hit a nested loop while profiling, we record where it occurs + * and how many iterations we execute it. + */ + struct InnerLoop { + JSScript *script; + jsbytecode *top, *bottom; + uintN iters; + + InnerLoop() {} + InnerLoop(JSScript *script, jsbytecode *top, jsbytecode *bottom) + : script(script), top(top), bottom(bottom), iters(0) {} + }; + + /* These two variables track all the inner loops seen while profiling (up to a limit). */ + InnerLoop innerLoops[PROFILE_MAX_INNER_LOOPS]; + uintN numInnerLoops; + + /* + * These two variables track the loops that we are currently nested + * inside while profiling. Loops get popped off here when they exit. + */ + InnerLoop loopStack[PROFILE_MAX_INNER_LOOPS]; + uintN loopStackDepth; + + /* + * These fields keep track of values on the JS stack. If the stack grows larger + * than PROFILE_MAX_STACK, we continue to track sp, but we return conservative results + * for stackTop(). + */ + struct StackValue { + bool isConst; + bool hasValue; + int value; + + StackValue() : isConst(false), hasValue(false) {} + StackValue(bool isConst) : isConst(isConst), hasValue(false) {} + StackValue(bool isConst, int value) : isConst(isConst), hasValue(true), value(value) {} + }; + StackValue stack[PROFILE_MAX_STACK]; + uintN sp; + + inline void stackClear() { sp = 0; } + + inline void stackPush(const StackValue &v) { + if (sp < PROFILE_MAX_STACK) + stack[sp++] = v; + else + stackClear(); + } + + inline void stackPop() { if (sp > 0) sp--; } + + inline StackValue stackAt(int pos) { + pos += sp; + if (pos >= 0 && uintN(pos) < PROFILE_MAX_STACK) + return stack[pos]; + else + return StackValue(false); + } + + LoopProfile(JSScript *script, jsbytecode *top, jsbytecode *bottom); + + enum ProfileAction { + ProfContinue, + ProfComplete + }; + + /* These two functions track the instruction mix. */ + inline void increment(OpKind kind) + { + allOps[kind]++; + if (loopStackDepth == 0) + selfOps[kind]++; + } + + inline uintN count(OpKind kind) { return allOps[kind]; } + + /* Called for every back edge being profiled. */ + MonitorResult profileLoopEdge(JSContext* cx, uintN& inlineCallCount); + + /* Called for every instruction being profiled. */ + ProfileAction profileOperation(JSContext *cx, JSOp op); + + /* Once a loop's profile is done, these decide whether it should be traced. */ + bool isCompilationExpensive(JSContext *cx, uintN depth); + bool isCompilationUnprofitable(JSContext *cx, uintN depth); + void decide(JSContext *cx); +}; + /* * BUILTIN_NO_FIXUP_NEEDED indicates that after the initial LeaveTree of a deep * bail, the builtin call needs no further fixup when the trace exits and calls @@ -815,12 +993,6 @@ enum TypeConsensus TypeConsensus_Bad /* Typemaps are not compatible */ }; -enum MonitorResult { - MONITOR_RECORDING, - MONITOR_NOT_RECORDING, - MONITOR_ERROR -}; - enum TracePointAction { TPA_Nothing, TPA_RanStuff, @@ -836,6 +1008,9 @@ typedef HashMap GuardedShapeTable; # define AbortRecording(cx, reason) AbortRecordingImpl(cx) #endif +void +AbortProfiling(JSContext *cx); + class TraceRecorder { /*************************************************************** Recording session constants */ @@ -1441,9 +1616,9 @@ class TraceRecorder friend class DetermineTypesVisitor; friend class RecursiveSlotMap; friend class UpRecursiveSlotMap; - friend MonitorResult MonitorLoopEdge(JSContext*, uintN&); - friend TracePointAction MonitorTracePoint(JSContext*, uintN &inlineCallCount, - bool &blacklist); + friend MonitorResult RecordLoopEdge(JSContext*, uintN&); + friend TracePointAction RecordTracePoint(JSContext*, uintN &inlineCallCount, + bool *blacklist); friend AbortResult AbortRecording(JSContext*, const char*); friend class BoxArg; friend void TraceMonitor::sweep(); @@ -1497,6 +1672,7 @@ class TraceRecorder #define TRACING_ENABLED(cx) ((cx)->traceJitEnabled) #define REGEX_JIT_ENABLED(cx) ((cx)->traceJitEnabled || (cx)->methodJitEnabled) #define TRACE_RECORDER(cx) (JS_TRACE_MONITOR(cx).recorder) +#define TRACE_PROFILER(cx) (JS_TRACE_MONITOR(cx).profile) #define SET_TRACE_RECORDER(cx,tr) (JS_TRACE_MONITOR(cx).recorder = (tr)) #define JSOP_IN_RANGE(op,lo,hi) (uintN((op) - (lo)) <= uintN((hi) - (lo))) @@ -1528,8 +1704,15 @@ class TraceRecorder extern JS_REQUIRES_STACK MonitorResult MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount); +extern JS_REQUIRES_STACK MonitorResult +ProfileLoopEdge(JSContext* cx, uintN& inlineCallCount); + extern JS_REQUIRES_STACK TracePointAction -MonitorTracePoint(JSContext*, uintN& inlineCallCount, bool& blacklist); +RecordTracePoint(JSContext*, uintN& inlineCallCount, bool* blacklist); + +extern JS_REQUIRES_STACK TracePointAction +MonitorTracePoint(JSContext*, uintN& inlineCallCount, bool* blacklist, + void** traceData, uintN *traceEpoch); extern JS_REQUIRES_STACK TraceRecorder::AbortResult AbortRecording(JSContext* cx, const char* reason); diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index db37811214e2..6ffdc14764fe 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -527,7 +527,6 @@ class TypedArrayTemplate shape = (Shape *) prop; if (!js_NativeGet(cx, obj, obj2, shape, JSGET_METHOD_BARRIER, vp)) return false; - JS_UNLOCK_OBJ(cx, obj2); } } } diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index 0b913606bb8d..063297a548f2 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -1763,7 +1763,9 @@ ParseXMLSource(JSContext *cx, JSString *src) { Parser parser(cx); if (parser.init(chars, length, NULL, filename, lineno)) { - JSObject *scopeChain = &js_GetTopStackFrame(cx)->scopeChain(); + JSObject *scopeChain = JS_GetScopeChain(cx); + if (!scopeChain) + return NULL; JSParseNode *pn = parser.parseXMLText(scopeChain, false); uintN flags; if (pn && GetXMLSettingFlags(cx, &flags)) { @@ -4592,9 +4594,7 @@ HasFunctionProperty(JSContext *cx, JSObject *obj, jsid funid, JSBool *found) if (!js_LookupProperty(cx, obj, funid, &pobj, &prop)) return false; - if (prop) { - pobj->dropProperty(cx, prop); - } else { + if (!prop) { xml = (JSXML *) obj->getPrivate(); if (HasSimpleContent(xml)) { AutoObjectRooter tvr(cx); @@ -4609,8 +4609,6 @@ HasFunctionProperty(JSContext *cx, JSObject *obj, jsid funid, JSBool *found) JS_ASSERT(tvr.object()); if (!js_LookupProperty(cx, tvr.object(), funid, &pobj, &prop)) return false; - if (prop) - pobj->dropProperty(cx, prop); } } *found = (prop != NULL); @@ -4724,7 +4722,6 @@ xml_lookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, if (!shape) return JS_FALSE; - JS_LOCK_OBJ(cx, obj); *objp = obj; *propp = (JSProperty *) shape; } @@ -7126,9 +7123,7 @@ js_InitXMLClass(JSContext *cx, JSObject *obj) } JS_ASSERT(prop); shape = (Shape *) prop; - JS_ASSERT(pobj->containsSlot(shape->slot)); - cval = Jsvalify(pobj->getSlotMT(cx, shape->slot)); - JS_UNLOCK_OBJ(cx, pobj); + cval = Jsvalify(pobj->nativeGetSlot(shape->slot)); JS_ASSERT(VALUE_IS_FUNCTION(cx, cval)); /* Set default settings. */ @@ -7427,7 +7422,6 @@ js_FindXMLProperty(JSContext *cx, const Value &nameval, JSObject **objp, jsid *i if (!target->lookupProperty(cx, funid, &pobj, &prop)) return JS_FALSE; if (prop) { - pobj->dropProperty(cx, prop); *idp = funid; *objp = target; return JS_TRUE; diff --git a/js/src/lirasm/lirasm.cpp b/js/src/lirasm/lirasm.cpp index fdc066172064..3253e1917316 100644 --- a/js/src/lirasm/lirasm.cpp +++ b/js/src/lirasm/lirasm.cpp @@ -2235,6 +2235,7 @@ usageAndQuit(const string& progname) " --[no-]optimize enable or disable optimization of the LIR (default=off)\n" " --random [N] generate a random LIR block of size N (default=1000)\n" " --word-size prints the word size (32 or 64) for this build of lirasm and exits\n" + " --endianness prints endianness (little-endian or big-endian) for this build of librasm and exits\n" " i386-specific options:\n" " --sse use SSE2 instructions\n" " ARM-specific options:\n" @@ -2313,6 +2314,15 @@ processCmdLine(int argc, char **argv, CmdLineOptions& opts) cout << sizeof(void*) * 8 << "\n"; exit(0); } + else if (arg == "--endianness") { + int32_t x = 0x01020304; + if (*(char*)&x == 0x1) { + cout << "big-endian" << "\n"; + } else { + cout << "little-endian" << "\n"; + } + exit(0); + } // Architecture-specific flags. #if defined NANOJIT_IA32 diff --git a/js/src/lirasm/testlirc.sh b/js/src/lirasm/testlirc.sh index c4b0eff1ba44..217488e3fc9d 100755 --- a/js/src/lirasm/testlirc.sh +++ b/js/src/lirasm/testlirc.sh @@ -77,6 +77,24 @@ then done fi +# little endian +if [[ $($LIRASM --endianness 2>/dev/null) != "big-endian" ]] +then + for infile in "$TESTS_DIR"/littleendian/*.in + do + runtest $infile + done +fi + +# big endian +if [[ $($LIRASM --endianness 2>/dev/null) == "big-endian" ]] +then + for infile in "$TESTS_DIR"/bigendian/*.in + do + runtest $infile + done +fi + # ARM if [[ $(uname -m) == arm* ]] then diff --git a/js/src/lirasm/tests/bigendian/fuzz-527178.in b/js/src/lirasm/tests/bigendian/fuzz-527178.in new file mode 100644 index 000000000000..2065f31e64f8 --- /dev/null +++ b/js/src/lirasm/tests/bigendian/fuzz-527178.in @@ -0,0 +1,5 @@ +base = allocp 512 +five = immi 5 +sti five base 256 +x = ldus2ui base 258 +reti x diff --git a/js/src/lirasm/tests/bigendian/fuzz-527178.out b/js/src/lirasm/tests/bigendian/fuzz-527178.out new file mode 100644 index 000000000000..3af948296171 --- /dev/null +++ b/js/src/lirasm/tests/bigendian/fuzz-527178.out @@ -0,0 +1 @@ +Output is: 5 diff --git a/js/src/lirasm/tests/bigendian/ldc2i.in b/js/src/lirasm/tests/bigendian/ldc2i.in new file mode 100644 index 000000000000..24233eed2f73 --- /dev/null +++ b/js/src/lirasm/tests/bigendian/ldc2i.in @@ -0,0 +1,26 @@ +full = immi 1288908529 ; 0x4cd32ef1 +p = allocp 4 +sti full p 0 + +n0chk = immi -15 ; sign_extend(0xf1) +n1chk = immi 46 ; sign_extend(0x2e) +n2chk = immi -45 ; sign_extend(0xd3) +n3chk = immi 76 ; sign_extend(0x4c) + +n0 = ldc2i p 3 +n1 = ldc2i p 2 +n2 = ldc2i p 1 +n3 = ldc2i p 0 + +; Collate the results. +r0 = xori n0chk n0 +r1 = xori n1chk n1 +r2 = xori n2chk n2 +r3 = xori n3chk n3 + +r0_1 = ori r0 r1 +r2_3 = ori r2 r3 + +r = ori r0_1 r2_3 +reti r + diff --git a/js/src/lirasm/tests/bigendian/ldc2i.out b/js/src/lirasm/tests/bigendian/ldc2i.out new file mode 100644 index 000000000000..e1b88ffcb7d9 --- /dev/null +++ b/js/src/lirasm/tests/bigendian/ldc2i.out @@ -0,0 +1 @@ +Output is: 0 diff --git a/js/src/lirasm/tests/bigendian/lds2i.in b/js/src/lirasm/tests/bigendian/lds2i.in new file mode 100644 index 000000000000..1b179294f5b5 --- /dev/null +++ b/js/src/lirasm/tests/bigendian/lds2i.in @@ -0,0 +1,17 @@ +full = immi -249334698 ; 0xf1237456 +p = allocp 4 +sti full p 0 + +n0chk = immi 29782 ; sign_extend(0x7456) +n1chk = immi -3805 ; sign_extend(0xf123) + +n0 = lds2i p 2 +n1 = lds2i p 0 + +; Collate the results. +r0 = xori n0chk n0 +r1 = xori n1chk n1 + +r = ori r0 r1 +reti r + diff --git a/js/src/lirasm/tests/bigendian/lds2i.out b/js/src/lirasm/tests/bigendian/lds2i.out new file mode 100644 index 000000000000..e1b88ffcb7d9 --- /dev/null +++ b/js/src/lirasm/tests/bigendian/lds2i.out @@ -0,0 +1 @@ +Output is: 0 diff --git a/js/src/lirasm/tests/bigendian/lduc2ui.in b/js/src/lirasm/tests/bigendian/lduc2ui.in new file mode 100644 index 000000000000..dd767636b7a7 --- /dev/null +++ b/js/src/lirasm/tests/bigendian/lduc2ui.in @@ -0,0 +1,26 @@ +full = immi -992746767 ; 0xc4d3e2f1 +p = allocp 4 +sti full p 0 + +n0chk = immi 241 ; 0xf1 +n1chk = immi 226 ; 0xe2 +n2chk = immi 211 ; 0xd3 +n3chk = immi 196 ; 0xc4 + +n0 = lduc2ui p 3 +n1 = lduc2ui p 2 +n2 = lduc2ui p 1 +n3 = lduc2ui p 0 + +; Collate the results. +r0 = xori n0chk n0 +r1 = xori n1chk n1 +r2 = xori n2chk n2 +r3 = xori n3chk n3 + +r0_1 = ori r0 r1 +r2_3 = ori r2 r3 + +r = ori r0_1 r2_3 +reti r + diff --git a/js/src/lirasm/tests/bigendian/lduc2ui.out b/js/src/lirasm/tests/bigendian/lduc2ui.out new file mode 100644 index 000000000000..e1b88ffcb7d9 --- /dev/null +++ b/js/src/lirasm/tests/bigendian/lduc2ui.out @@ -0,0 +1 @@ +Output is: 0 diff --git a/js/src/lirasm/tests/bigendian/ldus2ui.in b/js/src/lirasm/tests/bigendian/ldus2ui.in new file mode 100644 index 000000000000..c4351c7b3ff1 --- /dev/null +++ b/js/src/lirasm/tests/bigendian/ldus2ui.in @@ -0,0 +1,17 @@ +full = immi -249334698 ; 0xf1237456 +p = allocp 4 +sti full p 0 + +n0chk = immi 29782 ; sign_extend(0x7456) +n1chk = immi 61731 ; sign_extend(0xf123) + +n0 = ldus2ui p 2 +n1 = ldus2ui p 0 + +; Collate the results. +r0 = xori n0chk n0 +r1 = xori n1chk n1 + +r = ori r0 r1 +reti r + diff --git a/js/src/lirasm/tests/bigendian/ldus2ui.out b/js/src/lirasm/tests/bigendian/ldus2ui.out new file mode 100644 index 000000000000..e1b88ffcb7d9 --- /dev/null +++ b/js/src/lirasm/tests/bigendian/ldus2ui.out @@ -0,0 +1 @@ +Output is: 0 diff --git a/js/src/lirasm/tests/littleendian/fuzz-527178.in b/js/src/lirasm/tests/littleendian/fuzz-527178.in new file mode 100644 index 000000000000..12403ddcd003 --- /dev/null +++ b/js/src/lirasm/tests/littleendian/fuzz-527178.in @@ -0,0 +1,5 @@ +base = allocp 512 +five = immi 5 +sti five base 256 +x = ldus2ui base 256 +reti x diff --git a/js/src/lirasm/tests/littleendian/fuzz-527178.out b/js/src/lirasm/tests/littleendian/fuzz-527178.out new file mode 100644 index 000000000000..3af948296171 --- /dev/null +++ b/js/src/lirasm/tests/littleendian/fuzz-527178.out @@ -0,0 +1 @@ +Output is: 5 diff --git a/js/src/lirasm/tests/littleendian/ldc2i.in b/js/src/lirasm/tests/littleendian/ldc2i.in new file mode 100644 index 000000000000..8db7961a2fa6 --- /dev/null +++ b/js/src/lirasm/tests/littleendian/ldc2i.in @@ -0,0 +1,26 @@ +full = immi 1288908529 ; 0x4cd32ef1 +p = allocp 4 +sti full p 0 + +n0chk = immi -15 ; sign_extend(0xf1) +n1chk = immi 46 ; sign_extend(0x2e) +n2chk = immi -45 ; sign_extend(0xd3) +n3chk = immi 76 ; sign_extend(0x4c) + +n0 = ldc2i p 0 +n1 = ldc2i p 1 +n2 = ldc2i p 2 +n3 = ldc2i p 3 + +; Collate the results. +r0 = xori n0chk n0 +r1 = xori n1chk n1 +r2 = xori n2chk n2 +r3 = xori n3chk n3 + +r0_1 = ori r0 r1 +r2_3 = ori r2 r3 + +r = ori r0_1 r2_3 +reti r + diff --git a/js/src/lirasm/tests/littleendian/ldc2i.out b/js/src/lirasm/tests/littleendian/ldc2i.out new file mode 100644 index 000000000000..e1b88ffcb7d9 --- /dev/null +++ b/js/src/lirasm/tests/littleendian/ldc2i.out @@ -0,0 +1 @@ +Output is: 0 diff --git a/js/src/lirasm/tests/littleendian/lds2i.in b/js/src/lirasm/tests/littleendian/lds2i.in new file mode 100644 index 000000000000..9546cb87f3d5 --- /dev/null +++ b/js/src/lirasm/tests/littleendian/lds2i.in @@ -0,0 +1,17 @@ +full = immi -249334698 ; 0xf1237456 +p = allocp 4 +sti full p 0 + +n0chk = immi 29782 ; sign_extend(0x7456) +n1chk = immi -3805 ; sign_extend(0xf123) + +n0 = lds2i p 0 +n1 = lds2i p 2 + +; Collate the results. +r0 = xori n0chk n0 +r1 = xori n1chk n1 + +r = ori r0 r1 +reti r + diff --git a/js/src/lirasm/tests/littleendian/lds2i.out b/js/src/lirasm/tests/littleendian/lds2i.out new file mode 100644 index 000000000000..e1b88ffcb7d9 --- /dev/null +++ b/js/src/lirasm/tests/littleendian/lds2i.out @@ -0,0 +1 @@ +Output is: 0 diff --git a/js/src/lirasm/tests/littleendian/lduc2ui.in b/js/src/lirasm/tests/littleendian/lduc2ui.in new file mode 100644 index 000000000000..3a4fb0d43564 --- /dev/null +++ b/js/src/lirasm/tests/littleendian/lduc2ui.in @@ -0,0 +1,26 @@ +full = immi -992746767 ; 0xc4d3e2f1 +p = allocp 4 +sti full p 0 + +n0chk = immi 241 ; 0xf1 +n1chk = immi 226 ; 0xe2 +n2chk = immi 211 ; 0xd3 +n3chk = immi 196 ; 0xc4 + +n0 = lduc2ui p 0 +n1 = lduc2ui p 1 +n2 = lduc2ui p 2 +n3 = lduc2ui p 3 + +; Collate the results. +r0 = xori n0chk n0 +r1 = xori n1chk n1 +r2 = xori n2chk n2 +r3 = xori n3chk n3 + +r0_1 = ori r0 r1 +r2_3 = ori r2 r3 + +r = ori r0_1 r2_3 +reti r + diff --git a/js/src/lirasm/tests/littleendian/lduc2ui.out b/js/src/lirasm/tests/littleendian/lduc2ui.out new file mode 100644 index 000000000000..e1b88ffcb7d9 --- /dev/null +++ b/js/src/lirasm/tests/littleendian/lduc2ui.out @@ -0,0 +1 @@ +Output is: 0 diff --git a/js/src/lirasm/tests/littleendian/ldus2ui.in b/js/src/lirasm/tests/littleendian/ldus2ui.in new file mode 100644 index 000000000000..69811e7721d2 --- /dev/null +++ b/js/src/lirasm/tests/littleendian/ldus2ui.in @@ -0,0 +1,17 @@ +full = immi -249334698 ; 0xf1237456 +p = allocp 4 +sti full p 0 + +n0chk = immi 29782 ; sign_extend(0x7456) +n1chk = immi 61731 ; sign_extend(0xf123) + +n0 = ldus2ui p 0 +n1 = ldus2ui p 2 + +; Collate the results. +r0 = xori n0chk n0 +r1 = xori n1chk n1 + +r = ori r0 r1 +reti r + diff --git a/js/src/lirasm/tests/littleendian/ldus2ui.out b/js/src/lirasm/tests/littleendian/ldus2ui.out new file mode 100644 index 000000000000..e1b88ffcb7d9 --- /dev/null +++ b/js/src/lirasm/tests/littleendian/ldus2ui.out @@ -0,0 +1 @@ +Output is: 0 diff --git a/js/src/methodjit/BaseAssembler.h b/js/src/methodjit/BaseAssembler.h index 449c95672c6b..bd230d6b0b4c 100644 --- a/js/src/methodjit/BaseAssembler.h +++ b/js/src/methodjit/BaseAssembler.h @@ -49,10 +49,73 @@ #include "assembler/moco/MocoStubs.h" #include "methodjit/MethodJIT.h" #include "methodjit/MachineRegs.h" +#include "CodeGenIncludes.h" namespace js { namespace mjit { +class MaybeRegisterID { + typedef JSC::MacroAssembler::RegisterID RegisterID; + + public: + MaybeRegisterID() + : reg_(Registers::ReturnReg), set(false) + { } + + MaybeRegisterID(RegisterID reg) + : reg_(reg), set(true) + { } + + inline RegisterID reg() const { JS_ASSERT(set); return reg_; } + inline void setReg(const RegisterID r) { reg_ = r; set = true; } + inline bool isSet() const { return set; } + + MaybeRegisterID & operator =(const MaybeRegisterID &other) { + set = other.set; + reg_ = other.reg_; + return *this; + } + + MaybeRegisterID & operator =(RegisterID r) { + setReg(r); + return *this; + } + + private: + RegisterID reg_; + bool set; +}; + +// Represents an int32 property name in generated code, which must be either +// a RegisterID or a constant value. +struct Int32Key { + typedef JSC::MacroAssembler::RegisterID RegisterID; + + MaybeRegisterID reg_; + int32 index_; + + Int32Key() : index_(0) { } + + static Int32Key FromRegister(RegisterID reg) { + Int32Key key; + key.reg_ = reg; + return key; + } + static Int32Key FromConstant(int32 index) { + Int32Key key; + key.index_ = index; + return key; + } + + int32 index() const { + JS_ASSERT(!reg_.isSet()); + return index_; + } + + RegisterID reg() const { return reg_.reg(); } + bool isConstant() const { return !reg_.isSet(); } +}; + class MaybeJump { typedef JSC::MacroAssembler::Jump Jump; public: @@ -72,8 +135,6 @@ class MaybeJump { bool set; }; -//#define JS_METHODJIT_PROFILE_STUBS - struct FrameAddress : JSC::MacroAssembler::Address { FrameAddress(int32 offset) @@ -88,7 +149,7 @@ struct ImmIntPtr : public JSC::MacroAssembler::ImmPtr { } }; -class BaseAssembler : public JSC::MacroAssembler +class Assembler : public ValueAssembler { struct CallPatch { CallPatch(Call cl, void *fun) @@ -116,7 +177,7 @@ class BaseAssembler : public JSC::MacroAssembler // This callLabel is to record the Label exactly after the call. Label callLabel; #endif - BaseAssembler() + Assembler() : callPatches(SystemAllocPolicy()) { startLabel = label(); @@ -125,15 +186,6 @@ class BaseAssembler : public JSC::MacroAssembler /* Total number of floating-point registers. */ static const uint32 TotalFPRegisters = FPRegisters::TotalFPRegisters; - /* - * JSFrameReg is used to home the current JSStackFrame*. - */ -#if defined(JS_CPU_X86) || defined(JS_CPU_X64) - static const RegisterID JSFrameReg = JSC::X86Registers::ebx; -#elif defined(JS_CPU_ARM) - static const RegisterID JSFrameReg = JSC::ARMRegisters::r11; -#endif - /* Register pair storing returned type/data for calls. */ #if defined(JS_CPU_X86) || defined(JS_CPU_X64) static const JSC::MacroAssembler::RegisterID JSReturnReg_Type = JSC::X86Registers::ecx; @@ -145,14 +197,6 @@ static const JSC::MacroAssembler::RegisterID JSReturnReg_Data = JSC::ARMRegiste static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::ARMRegisters::r1; #endif - bool addressUsesRegister(Address address, RegisterID reg) { - return address.base == reg; - } - - bool addressUsesRegister(BaseIndex address, RegisterID reg) { - return (address.base == reg) || (address.index == reg); - } - size_t distanceOf(Label l) { return differenceBetween(startLabel, l); } @@ -270,13 +314,6 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::ARMRegiste } Call wrapCall(void *pfun) { -#ifdef JS_METHODJIT_PROFILE_STUBS - push(Registers::ArgReg0); - push(Registers::ArgReg1); - call(JS_FUNC_TO_DATA_PTR(void *, mjit::ProfileStubCall)); - pop(Registers::ArgReg1); - pop(Registers::ArgReg0); -#endif #if defined(JS_NO_FASTCALL) && defined(JS_CPU_X86) push(Registers::ArgReg1); push(Registers::ArgReg0); @@ -335,6 +372,61 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::ARMRegiste linker.link(patch.call, JSC::FunctionPtr(patch.fun)); } } + + struct FastArrayLoadFails { + Jump rangeCheck; + Jump holeCheck; + }; + + // Load a jsval from an array slot, given a key. |objReg| is clobbered. + FastArrayLoadFails fastArrayLoad(RegisterID objReg, const Int32Key &key, + RegisterID typeReg, RegisterID dataReg) { + JS_ASSERT(objReg != typeReg); + + FastArrayLoadFails fails; + Address capacity(objReg, offsetof(JSObject, capacity)); + + // Check that the id is within range. + if (key.isConstant()) { + JS_ASSERT(key.index() >= 0); + fails.rangeCheck = branch32(BelowOrEqual, payloadOf(capacity), Imm32(key.index())); + } else { + fails.rangeCheck = branch32(BelowOrEqual, payloadOf(capacity), key.reg()); + } + + RegisterID dslotsReg = objReg; + loadPtr(Address(objReg, offsetof(JSObject, slots)), dslotsReg); + + // Load the slot out of the array. + if (key.isConstant()) { + Address slot(objReg, key.index() * sizeof(Value)); + fails.holeCheck = fastArrayLoadSlot(slot, typeReg, dataReg); + } else { + BaseIndex slot(objReg, key.reg(), JSVAL_SCALE); + fails.holeCheck = fastArrayLoadSlot(slot, typeReg, dataReg); + } + + return fails; + } + + void loadObjClass(RegisterID objReg, RegisterID destReg) { + loadPtr(Address(objReg, offsetof(JSObject, clasp)), destReg); + } + + Jump testClass(Condition cond, RegisterID claspReg, js::Class *clasp) { + return branchPtr(cond, claspReg, ImmPtr(clasp)); + } + + Jump testObjClass(Condition cond, RegisterID objReg, js::Class *clasp) { + return branchPtr(cond, Address(objReg, offsetof(JSObject, clasp)), ImmPtr(clasp)); + } + + void rematPayload(const StateRemat &remat, RegisterID reg) { + if (remat.inMemory()) + loadPayload(remat.address(), reg); + else + move(remat.reg(), reg); + } }; /* Return f if the script is strict mode code, f otherwise. */ @@ -343,10 +435,9 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::ARMRegiste f, f)) /* Save some typing. */ -static const JSC::MacroAssembler::RegisterID JSFrameReg = BaseAssembler::JSFrameReg; -static const JSC::MacroAssembler::RegisterID JSReturnReg_Type = BaseAssembler::JSReturnReg_Type; -static const JSC::MacroAssembler::RegisterID JSReturnReg_Data = BaseAssembler::JSReturnReg_Data; -static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = BaseAssembler::JSParamReg_Argc; +static const JSC::MacroAssembler::RegisterID JSReturnReg_Type = Assembler::JSReturnReg_Type; +static const JSC::MacroAssembler::RegisterID JSReturnReg_Data = Assembler::JSReturnReg_Data; +static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = Assembler::JSParamReg_Argc; struct FrameFlagsAddress : JSC::MacroAssembler::Address { diff --git a/js/src/methodjit/BytecodeAnalyzer.cpp b/js/src/methodjit/BytecodeAnalyzer.cpp deleted file mode 100644 index 3332911ef752..000000000000 --- a/js/src/methodjit/BytecodeAnalyzer.cpp +++ /dev/null @@ -1,325 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=4 sw=4 et tw=99: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (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.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released - * May 28, 2008. - * - * The Initial Developer of the Original Code is - * Brendan Eich - * - * Contributor(s): - * David Anderson - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "BytecodeAnalyzer.h" -#include "jsautooplen.h" -#include "jsemit.h" -#include "Retcon.h" - -using namespace js; - -BytecodeAnalyzer::~BytecodeAnalyzer() -{ - cx->free(ops); -} - -bool -BytecodeAnalyzer::addEdge(jsbytecode *pc, int32 offset, uint32 stackDepth) -{ - uint32 idx = (uint32)((pc + offset) - script->code); - - JS_ASSERT_IF(ops[idx].visited || ops[idx].nincoming, - ops[idx].stackDepth == stackDepth); - - if (!ops[idx].visited && !doList.append(pc + offset)) - return false; - - ops[idx].stackDepth = stackDepth; - ops[idx].nincoming++; - - return true; -} - -bool -BytecodeAnalyzer::analyze(uint32 index) -{ - mjit::AutoScriptRetrapper trapper(cx, script); - jsbytecode *pc = doList[index]; - uint32 stackDepth = ops[pc - script->code].stackDepth; - - for (;;) { - JSOp op = JSOp(pc[0]); - OpcodeStatus &status = ops[pc - script->code]; - - if (status.visited) - return true; - - status.visited = true; - status.stackDepth = stackDepth; - - if (op == JSOP_TRAP) { - status.trap = true; - if (!trapper.untrap(pc)) - return false; - op = JSOp(pc[0]); - } - - uint32 nuses, ndefs; - if (js_CodeSpec[op].nuses == -1) - nuses = js_GetVariableStackUses(op, pc); - else - nuses = js_CodeSpec[op].nuses; - - if (js_CodeSpec[op].ndefs == -1) - ndefs = js_GetEnterBlockStackDefs(cx, script, pc); - else - ndefs = js_CodeSpec[op].ndefs; - - JS_ASSERT(nuses <= stackDepth); - stackDepth -= nuses; - stackDepth += ndefs; - - uint32 offs; - jsbytecode *newpc; - switch (op) { - case JSOP_TRAP: - return false; - - case JSOP_SETRVAL: - case JSOP_POPV: - usesRval = true; - break; - - case JSOP_NAME: - case JSOP_CALLNAME: - case JSOP_BINDNAME: - case JSOP_SETNAME: - case JSOP_DELNAME: - case JSOP_INCNAME: - case JSOP_DECNAME: - case JSOP_NAMEINC: - case JSOP_NAMEDEC: - usesScope = true; - break; - - case JSOP_DEFAULT: - case JSOP_GOTO: - offs = (pc + JSOP_GOTO_LENGTH) - script->code; - if (!ops[offs].visited && ops[offs].nincoming && !doList.append(pc + JSOP_GOTO_LENGTH)) - return false; - pc += GET_JUMP_OFFSET(pc); - ops[pc - script->code].nincoming++; - continue; - - case JSOP_DEFAULTX: - case JSOP_GOTOX: - offs = (pc + JSOP_GOTOX_LENGTH) - script->code; - if (!ops[offs].visited && ops[offs].nincoming && !doList.append(pc + JSOP_GOTOX_LENGTH)) - return false; - pc += GET_JUMPX_OFFSET(pc); - ops[pc - script->code].nincoming++; - continue; - - case JSOP_IFEQ: - case JSOP_IFNE: - if (!addEdge(pc, GET_JUMP_OFFSET(pc), stackDepth)) - return false; - break; - - case JSOP_OR: - case JSOP_AND: - /* If the jump is taken, the condition is pushed. */ - if (!addEdge(pc, GET_JUMP_OFFSET(pc), stackDepth + 1)) - return false; - break; - - case JSOP_IFEQX: - case JSOP_IFNEX: - if (!addEdge(pc, GET_JUMPX_OFFSET(pc), stackDepth)) - return false; - break; - - case JSOP_ORX: - case JSOP_ANDX: - if (!addEdge(pc, GET_JUMPX_OFFSET(pc), stackDepth + 1)) - return false; - break; - - case JSOP_CASE: - /* If the jump is taken, the extra value is not pushed. */ - if (!addEdge(pc, GET_JUMP_OFFSET(pc), stackDepth - 1)) - return false; - break; - - case JSOP_CASEX: - /* If the jump is taken, the extra value is not pushed. */ - if (!addEdge(pc, GET_JUMPX_OFFSET(pc), stackDepth - 1)) - return false; - break; - - case JSOP_GOSUB: - case JSOP_GOSUBX: - case JSOP_IFPRIMTOP: - case JSOP_FILTER: - case JSOP_ENDFILTER: - case JSOP_TABLESWITCHX: - case JSOP_LOOKUPSWITCHX: - return false; - - case JSOP_TABLESWITCH: - { - jsint def = GET_JUMP_OFFSET(pc); - if (!addEdge(pc, def, stackDepth)) - return false; - - newpc = pc + JUMP_OFFSET_LEN; - jsint low = GET_JUMP_OFFSET(newpc); - newpc += JUMP_OFFSET_LEN; - jsint high = GET_JUMP_OFFSET(newpc); - newpc += JUMP_OFFSET_LEN; - uint32 ncases = (uint32)(high - low + 1); - - for (uint32 i = 0; i < ncases; i++) { - jsint offs = GET_JUMP_OFFSET(newpc); - newpc += JUMP_OFFSET_LEN; - if (!offs) - offs = def; - if (!addEdge(pc, offs, stackDepth)) - return false; - } - pc = newpc + 1; - - break; - } - - case JSOP_LOOKUPSWITCH: - { - if (!addEdge(pc, GET_JUMP_OFFSET(pc), stackDepth)) - return false; - - newpc = pc + JUMP_OFFSET_LEN; - uint32 npairs = GET_UINT16(newpc); - newpc += UINT16_LEN; - - JS_ASSERT(npairs); - for (uint32 i = 0; i < npairs; i++) { - newpc += INDEX_LEN ; - if (!addEdge(pc, GET_JUMP_OFFSET(newpc), stackDepth)) - return false; - newpc += JUMP_OFFSET_LEN; - } - pc = newpc + 1; - - break; - } - - case JSOP_RETRVAL: - case JSOP_RETURN: - { - /* - * If there is nothing incoming, just leave. - * This is to defeat the emitter doing things like: - * leaveblock 1 - * retrval - * leaveblock 1 - * (see testNullCallee in trace-tests) - */ - JS_ASSERT(js_CodeSpec[op].length == 1); - uint32 offs = (pc + 1) - script->code; - if (ops[offs].visited || !ops[offs].nincoming) - return true; - - /* Otherwise, restore the stack depth and continue. */ - stackDepth = ops[offs].stackDepth; - break; - } - - case JSOP_THROW: - /* Control flow stops here. */ - return true; - - case JSOP_STOP: - JS_ASSERT(uint32(pc - script->code) + 1 == script->length); - return true; - - default: -#ifdef DEBUG - uint32 type = JOF_TYPE(js_CodeSpec[op].format); - JS_ASSERT(type != JOF_JUMP && type != JOF_JUMPX); -#endif - break; - } - - if (js_CodeSpec[op].length != -1) - pc += js_CodeSpec[op].length; - } -} - -bool -BytecodeAnalyzer::analyze() -{ - ops = (OpcodeStatus *)cx->malloc(sizeof(OpcodeStatus) * script->length); - if (!ops) - return false; - memset(ops, 0, sizeof(OpcodeStatus) * script->length); - - if (!doList.append(script->code)) - return false; - - if (script->trynotesOffset) { - JSTryNoteArray *tnarray = script->trynotes(); - for (unsigned i = 0; i < tnarray->length; ++i) { - JSTryNote &tn = tnarray->vector[i]; - unsigned pcstart = script->main + tn.start - script->code; - unsigned pcoff = pcstart + tn.length; - - for (unsigned j = pcstart; j < pcoff; j++) - ops[j].inTryBlock = true; - - if (tn.kind == JSTRY_ITER) - continue; - - ops[pcoff].exceptionEntry = true; - ops[pcoff].nincoming = 1; - ops[pcoff].stackDepth = tn.stackDepth; - if (!doList.append(script->code + pcoff)) - return false; - } - } - - for (size_t i = 0; i < doList.length(); i++) { - if (ops[doList[i] - script->code].visited) - continue; - if (!analyze(i)) - return false; - } - - return true; -} - diff --git a/js/src/methodjit/BytecodeAnalyzer.h b/js/src/methodjit/BytecodeAnalyzer.h deleted file mode 100644 index 911219fe03e7..000000000000 --- a/js/src/methodjit/BytecodeAnalyzer.h +++ /dev/null @@ -1,118 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=4 sw=4 et tw=99: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (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.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released - * May 28, 2008. - * - * The Initial Developer of the Original Code is - * Brendan Eich - * - * Contributor(s): - * David Anderson - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#if !defined jsjaeger_bytecodeAnalyzer_h__ && defined JS_METHODJIT -#define jsjaeger_bytecodeAnalyzer_h__ - -#include "jsapi.h" -#include "jscntxt.h" -#include "jsscript.h" -#include "jsopcode.h" - -namespace js -{ - struct OpcodeStatus - { - bool visited; /* flag for CFG traversal */ - bool exceptionEntry; /* true iff this is a catch/finally entry point */ - bool safePoint; /* false by default */ - bool trap; /* It's a trap! */ - bool inTryBlock; /* true if in try block */ - uint32 nincoming; /* number of CFG inedges here */ - uint32 stackDepth; /* stack depth before this opcode */ - }; - - class BytecodeAnalyzer - { - JSContext *cx; - JSScript *script; - OpcodeStatus *ops; - Vector doList; - - /* Whether there are POPV/SETRVAL bytecodes which can write to the frame's rval. */ - bool usesRval; - - /* Whether there are NAME bytecodes which can access the frame's scope chain. */ - bool usesScope; - - public: - BytecodeAnalyzer(JSContext *cx, JSScript *script) - : cx(cx), script(script), ops(NULL), - doList(ContextAllocPolicy(cx)), - usesRval(false), usesScope(false) - { - } - ~BytecodeAnalyzer(); - - bool analyze(uint32 offs); - bool addEdge(jsbytecode *pc, int32 offset, uint32 stackDepth); - - public: - - bool usesReturnValue() const { return usesRval; } - bool usesScopeChain() const { return usesScope; } - - inline const OpcodeStatus & operator [](uint32 offs) const { - JS_ASSERT(offs < script->length); - return ops[offs]; - } - - inline OpcodeStatus & operator [](uint32 offs) { - JS_ASSERT(offs < script->length); - return ops[offs]; - } - - inline const OpcodeStatus & operator [](jsbytecode *pc) const { - JS_ASSERT(pc < script->code + script->length); - return ops[pc - script->code]; - } - - inline OpcodeStatus & operator [](jsbytecode *pc) { - JS_ASSERT(pc < script->code + script->length); - return ops[pc - script->code]; - } - - inline bool OOM() { return !ops; } - - bool analyze(); - }; -} - -#endif /* jsjaeger_bytecodeAnalyzer_h__ */ - diff --git a/js/src/methodjit/CodeGenIncludes.h b/js/src/methodjit/CodeGenIncludes.h index 4f90a78c546c..50ab15abebb9 100644 --- a/js/src/methodjit/CodeGenIncludes.h +++ b/js/src/methodjit/CodeGenIncludes.h @@ -48,6 +48,7 @@ #else # error "Neither JS_NUNBOX32 nor JS_PUNBOX64 is defined." #endif +#include "BaseAssembler.h" /* Get a label for assertion purposes. Prevent #ifdef clutter. */ #ifdef DEBUG diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 86e100fcace0..76ba19bce336 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -93,7 +93,7 @@ mjit::Compiler::Compiler(JSContext *cx, JSStackFrame *fp) ? fp->fun() : NULL), isConstructing(fp->isConstructing()), - analysis(cx, script), jumpMap(NULL), frame(cx, script, masm), + analysis(NULL), jumpMap(NULL), frame(cx, script, masm), branchPatches(ContextAllocPolicy(cx)), #if defined JS_MONOIC mics(ContextAllocPolicy(cx)), @@ -156,14 +156,20 @@ mjit::Compiler::performCompilation(JITScript **jitp) JaegerSpew(JSpew_Scripts, "compiling script (file \"%s\") (line \"%d\") (length \"%d\")\n", script->filename, script->lineno, script->length); - /* Perform bytecode analysis. */ - if (!analysis.analyze()) { - if (analysis.OOM()) - return Compile_Error; + analyze::Script analysis; + PodZero(&analysis); + + analysis.analyze(cx, script); + + if (analysis.OOM()) + return Compile_Error; + if (analysis.failed()) { JaegerSpew(JSpew_Abort, "couldn't analyze bytecode; probably switchX or OOM\n"); return Compile_Abort; } + this->analysis = &analysis; + uint32 nargs = fun ? fun->nargs : 0; if (!frame.init(nargs) || !stubcc.init(nargs)) return Compile_Abort; @@ -291,10 +297,16 @@ mjit::Compiler::generatePrologue() stubcc.crossJump(stubcc.masm.jump(), masm.label()); } - /* Set locals to undefined, as in initCallFrameLatePrologue */ + /* + * Set locals to undefined, as in initCallFrameLatePrologue. + * Skip locals which aren't closed and are known to be defined before used, + * :FIXME: bug 604541: write undefined if we might be using the tracer, so it works. + */ for (uint32 i = 0; i < script->nfixed; i++) { - Address local(JSFrameReg, sizeof(JSStackFrame) + i * sizeof(Value)); - masm.storeValue(UndefinedValue(), local); + if (analysis->localHasUseBeforeDef(i) || addTraceHints) { + Address local(JSFrameReg, sizeof(JSStackFrame) + i * sizeof(Value)); + masm.storeValue(UndefinedValue(), local); + } } /* Create the call object. */ @@ -305,7 +317,7 @@ mjit::Compiler::generatePrologue() j.linkTo(masm.label(), &masm); - if (analysis.usesScopeChain() && !fun->isHeavyweight()) { + if (analysis->usesScopeChain() && !fun->isHeavyweight()) { /* * Load the scope chain into the frame if necessary. The scope chain * is always set for global and eval frames, and will have been set by @@ -400,7 +412,8 @@ mjit::Compiler::finishThisUp(JITScript **jitp) for (size_t i = 0; i < script->length; i++) { Label L = jumpMap[i]; - if (analysis[i].safePoint) { + analyze::Bytecode *opinfo = analysis->maybeCode(i); + if (opinfo && opinfo->safePoint) { JS_ASSERT(L.isValid()); nmap[i] = (uint8 *)(result + masm.distanceOf(L)); } @@ -551,6 +564,7 @@ mjit::Compiler::finishThisUp(JITScript **jitp) scriptTICs[i].traceHint = fullCode.locationOf(traceICs[i].traceHint); scriptTICs[i].jumpTarget = fullCode.locationOf(jumpMap[offs]); scriptTICs[i].stubEntry = stubCode.locationOf(traceICs[i].stubEntry); + scriptTICs[i].traceData = NULL; #ifdef DEBUG scriptTICs[i].jumpTargetPC = traceICs[i].jumpTarget; #endif @@ -584,15 +598,15 @@ mjit::Compiler::finishThisUp(JITScript **jitp) for (size_t i = 0; i < pics.length(); i++) { pics[i].copySimpleMembersTo(scriptPICs[i]); scriptPICs[i].fastPathStart = fullCode.locationOf(pics[i].fastPathStart); - scriptPICs[i].storeBack = fullCode.locationOf(pics[i].storeBack); + scriptPICs[i].fastPathRejoin = fullCode.locationOf(pics[i].fastPathRejoin); scriptPICs[i].slowPathStart = stubCode.locationOf(pics[i].slowPathStart); - scriptPICs[i].callReturn = uint16((uint8*)stubCode.locationOf(pics[i].callReturn).executableAddress() - - (uint8*)scriptPICs[i].slowPathStart.executableAddress()); + scriptPICs[i].slowPathCall = stubCode.locationOf(pics[i].slowPathCall); scriptPICs[i].shapeGuard = masm.distanceOf(pics[i].shapeGuard) - masm.distanceOf(pics[i].fastPathStart); JS_ASSERT(scriptPICs[i].shapeGuard == masm.distanceOf(pics[i].shapeGuard) - masm.distanceOf(pics[i].fastPathStart)); scriptPICs[i].shapeRegHasBaseShape = true; + scriptPICs[i].pc = pics[i].pc; # if defined JS_CPU_X64 memcpy(&scriptPICs[i].labels, &pics[i].labels, sizeof(PICLabels)); @@ -611,7 +625,7 @@ mjit::Compiler::finishThisUp(JITScript **jitp) } new (&scriptPICs[i].execPools) ic::PICInfo::ExecPoolVector(SystemAllocPolicy()); scriptPICs[i].reset(); - stubCode.patch(pics[i].addrLabel, &scriptPICs[i]); + stubCode.patch(pics[i].paramAddr, &scriptPICs[i]); } } #endif /* JS_POLYIC */ @@ -692,22 +706,17 @@ mjit::Compiler::generateMethod() for (;;) { JSOp op = JSOp(*PC); + bool trap = (op == JSOP_TRAP); - OpcodeStatus &opinfo = analysis[PC]; - frame.setInTryBlock(opinfo.inTryBlock); - if (opinfo.nincoming || opinfo.trap) { - frame.syncAndForgetEverything(opinfo.stackDepth); - opinfo.safePoint = true; - } - jumpMap[uint32(PC - script->code)] = masm.label(); - - if (opinfo.trap) { + if (trap) { if (!trapper.untrap(PC)) return Compile_Error; op = JSOp(*PC); } - if (!opinfo.visited) { + analyze::Bytecode *opinfo = analysis->maybeCode(PC); + + if (!opinfo) { if (op == JSOP_STOP) break; if (js_CodeSpec[op].length != -1) @@ -717,10 +726,17 @@ mjit::Compiler::generateMethod() continue; } - SPEW_OPCODE(); - JS_ASSERT(frame.stackDepth() == opinfo.stackDepth); + frame.setInTryBlock(opinfo->inTryBlock); + if (opinfo->jumpTarget || trap) { + frame.syncAndForgetEverything(opinfo->stackDepth); + opinfo->safePoint = true; + } + jumpMap[uint32(PC - script->code)] = masm.label(); - if (opinfo.trap) { + SPEW_OPCODE(); + JS_ASSERT(frame.stackDepth() == opinfo->stackDepth); + + if (trap) { prepareStubCall(Uses(0)); masm.move(ImmPtr(PC), Registers::ArgReg1); stubCall(stubs::Trap); @@ -795,6 +811,12 @@ mjit::Compiler::generateMethod() frame.pushSynced(); END_CASE(JSOP_ARGUMENTS) + BEGIN_CASE(JSOP_FORARG) + iterNext(); + jsop_setarg(GET_SLOTNO(PC), true); + frame.pop(); + END_CASE(JSOP_FORARG) + BEGIN_CASE(JSOP_FORLOCAL) iterNext(); frame.storeLocal(GET_SLOTNO(PC), true); @@ -825,7 +847,7 @@ mjit::Compiler::generateMethod() /* Detect fusions. */ jsbytecode *next = &PC[JSOP_GE_LENGTH]; JSOp fused = JSOp(*next); - if ((fused != JSOP_IFEQ && fused != JSOP_IFNE) || analysis[next].nincoming) + if ((fused != JSOP_IFEQ && fused != JSOP_IFNE) || analysis->jumpTarget(next)) fused = JSOP_NOP; /* Get jump target, if any. */ @@ -1153,8 +1175,11 @@ mjit::Compiler::generateMethod() frame.pushSynced(); END_CASE(JSOP_CALLNAME) - BEGIN_CASE(JSOP_CALL) BEGIN_CASE(JSOP_EVAL) + jsop_eval(); + END_CASE(JSOP_EVAL) + + BEGIN_CASE(JSOP_CALL) BEGIN_CASE(JSOP_APPLY) { JaegerSpew(JSpew_Insns, " --- SCRIPTED CALL --- \n"); @@ -1300,17 +1325,7 @@ mjit::Compiler::generateMethod() END_CASE(JSOP_BINDGNAME) BEGIN_CASE(JSOP_SETARG) - { - uint32 slot = GET_SLOTNO(PC); - FrameEntry *top = frame.peek(-1); - - bool popped = PC[JSOP_SETARG_LENGTH] == JSOP_POP; - - RegisterID reg = frame.allocReg(); - Address address = Address(JSFrameReg, JSStackFrame::offsetOfFormalArg(fun, slot)); - frame.storeTo(top, address, popped); - frame.freeReg(reg); - } + jsop_setarg(GET_SLOTNO(PC), JSOp(PC[JSOP_SETARG_LENGTH]) == JSOP_POP); END_CASE(JSOP_SETARG) BEGIN_CASE(JSOP_GETLOCAL) @@ -1323,7 +1338,7 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_SETLOCAL) { jsbytecode *next = &PC[JSOP_SETLOCAL_LENGTH]; - bool pop = JSOp(*next) == JSOP_POP && !analysis[next].nincoming; + bool pop = JSOp(*next) == JSOP_POP && !analysis->jumpTarget(next); frame.storeLocal(GET_SLOTNO(PC), pop); if (pop) { frame.pop(); @@ -1390,7 +1405,7 @@ mjit::Compiler::generateMethod() { jsbytecode *next = &PC[JSOP_ARGINC_LENGTH]; bool popped = false; - if (JSOp(*next) == JSOP_POP && !analysis[next].nincoming) + if (JSOp(*next) == JSOP_POP && !analysis->jumpTarget(next)) popped = true; jsop_arginc(op, GET_SLOTNO(PC), popped); PC += JSOP_ARGINC_LENGTH; @@ -1400,12 +1415,6 @@ mjit::Compiler::generateMethod() } END_CASE(JSOP_ARGDEC) - BEGIN_CASE(JSOP_FORNAME) - prepareStubCall(Uses(1)); - masm.move(ImmPtr(script->getAtom(fullAtomIndex(PC))), Registers::ArgReg1); - stubCall(STRICT_VARIANT(stubs::ForName)); - END_CASE(JSOP_FORNAME) - BEGIN_CASE(JSOP_INCLOCAL) BEGIN_CASE(JSOP_DECLOCAL) BEGIN_CASE(JSOP_LOCALINC) @@ -1413,7 +1422,7 @@ mjit::Compiler::generateMethod() { jsbytecode *next = &PC[JSOP_LOCALINC_LENGTH]; bool popped = false; - if (JSOp(*next) == JSOP_POP && !analysis[next].nincoming) + if (JSOp(*next) == JSOP_POP && !analysis->jumpTarget(next)) popped = true; /* These manually advance the PC. */ jsop_localinc(op, GET_SLOTNO(PC), popped); @@ -1424,6 +1433,41 @@ mjit::Compiler::generateMethod() } END_CASE(JSOP_LOCALDEC) + BEGIN_CASE(JSOP_FORNAME) + // Before: ITER + // After: ITER SCOPEOBJ + jsop_bindname(fullAtomIndex(PC), false); + + // Fall through to FORPROP. + + BEGIN_CASE(JSOP_FORPROP) + // Before: ITER OBJ + // After: ITER OBJ ITER + frame.dupAt(-2); + + // Before: ITER OBJ ITER + // After: ITER OBJ ITER VALUE + iterNext(); + + // Before: ITER OBJ ITER VALUE + // After: ITER OBJ VALUE + frame.shimmy(1); + + // Before: ITER OBJ VALUE + // After: ITER VALUE + jsop_setprop(script->getAtom(fullAtomIndex(PC)), false); + + // Before: ITER VALUE + // After: ITER + frame.pop(); + END_CASE(JSOP_FORPROP) + + BEGIN_CASE(JSOP_FORELEM) + // This opcode is for the decompiler; it is succeeded by an + // ENUMELEM, which performs the actual array store. + iterNext(); + END_CASE(JSOP_FORELEM) + BEGIN_CASE(JSOP_BINDNAME) jsop_bindname(fullAtomIndex(PC), true); END_CASE(JSOP_BINDNAME) @@ -1474,6 +1518,29 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_LINENO) END_CASE(JSOP_LINENO) + BEGIN_CASE(JSOP_ENUMELEM) + // Normally, SETELEM transforms the stack + // from: OBJ ID VALUE + // to: VALUE + // + // Here, the stack transition is + // from: VALUE OBJ ID + // to: + // So we make the stack look like a SETELEM, and re-use it. + + // Before: VALUE OBJ ID + // After: VALUE OBJ ID VALUE + frame.dupAt(-3); + + // Before: VALUE OBJ ID VALUE + // After: VALUE VALUE + jsop_setelem(); + + // Before: VALUE VALUE + // After: + frame.popn(2); + END_CASE(JSOP_ENUMELEM) + BEGIN_CASE(JSOP_BLOCKCHAIN) END_CASE(JSOP_BLOCKCHAIN) @@ -1738,7 +1805,7 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_TRACE) BEGIN_CASE(JSOP_NOTRACE) { - if (analysis[PC].nincoming > 0) + if (analysis->jumpTarget(PC)) interruptCheckHelper(); } END_CASE(JSOP_TRACE) @@ -1789,6 +1856,12 @@ mjit::Compiler::generateMethod() break; END_CASE(JSOP_GLOBALINC) + BEGIN_CASE(JSOP_FORGLOBAL) + iterNext(); + jsop_setglobal(GET_SLOTNO(PC)); + frame.pop(); + END_CASE(JSOP_FORGLOBAL) + default: /* Sorry, this opcode isn't implemented yet. */ #ifdef JS_METHODJIT_SPEW @@ -1944,13 +2017,13 @@ mjit::Compiler::loadReturnValue(Assembler *masm, FrameEntry *fe) } } } else { - frame.loadTo(fe, typeReg, dataReg, Registers::ReturnReg); + frame.loadForReturn(fe, typeReg, dataReg, Registers::ReturnReg); } } else { // Load a return value from POPV or SETRVAL into the return registers, // otherwise return undefined. masm->loadValueAsComponents(UndefinedValue(), typeReg, dataReg); - if (analysis.usesReturnValue()) { + if (analysis->usesReturnValue()) { Jump rvalClear = masm->branchTest32(Assembler::Zero, FrameFlagsAddress(), Imm32(JSFRAME_HAS_RVAL)); @@ -2031,13 +2104,6 @@ mjit::Compiler::emitReturn(FrameEntry *fe) /* There will always be a call object. */ prepareStubCall(Uses(fe ? 1 : 0)); stubCall(stubs::PutActivationObjects); - - if (fe) { - emitReturnValue(&masm, fe); - emitFinalReturn(masm); - frame.discardFrame(); - return; - } } else { /* if (hasCallObj() || hasArgsObj()) stubs::PutActivationObjects() */ Jump putObjs = masm.branchTest32(Assembler::NonZero, @@ -2078,23 +2144,54 @@ mjit::Compiler::stubCall(void *ptr) void mjit::Compiler::interruptCheckHelper() { - RegisterID cxreg = frame.allocReg(); - masm.loadPtr(FrameAddress(offsetof(VMFrame, cx)), cxreg); + RegisterID reg = frame.allocReg(); + + /* + * Bake in and test the address of the interrupt counter for the runtime. + * This is faster than doing two additional loads for the context's + * thread data, but will cause this thread to run slower if there are + * pending interrupts on some other thread. For non-JS_THREADSAFE builds + * we can skip this, as there is only one flag to poll. + */ #ifdef JS_THREADSAFE - masm.loadPtr(Address(cxreg, offsetof(JSContext, thread)), cxreg); - Address flag(cxreg, offsetof(JSThread, data.interruptFlags)); + void *interrupt = (void*) &cx->runtime->interruptCounter; #else - masm.loadPtr(Address(cxreg, offsetof(JSContext, runtime)), cxreg); - Address flag(cxreg, offsetof(JSRuntime, threadData.interruptFlags)); + void *interrupt = (void*) &JS_THREAD_DATA(cx)->interruptFlags; #endif - Jump jump = masm.branchTest32(Assembler::NonZero, flag); - frame.freeReg(cxreg); - stubcc.linkExit(jump, Uses(0)); - stubcc.leave(); + +#if defined(JS_CPU_X86) || defined(JS_CPU_ARM) + Jump jump = masm.branch32(Assembler::NotEqual, AbsoluteAddress(interrupt), Imm32(0)); +#else + /* Handle processors that can't load from absolute addresses. */ + masm.move(ImmPtr(interrupt), reg); + Jump jump = masm.branchTest32(Assembler::NonZero, Address(reg, 0)); +#endif + + stubcc.linkExitDirect(jump, stubcc.masm.label()); + +#ifdef JS_THREADSAFE + /* + * Do a slightly slower check for an interrupt on this thread. + * We don't want this thread to slow down excessively if the pending + * interrupt is on another thread. + */ + stubcc.masm.loadPtr(FrameAddress(offsetof(VMFrame, cx)), reg); + stubcc.masm.loadPtr(Address(reg, offsetof(JSContext, thread)), reg); + Address flag(reg, offsetof(JSThread, data.interruptFlags)); + Jump noInterrupt = stubcc.masm.branchTest32(Assembler::Zero, flag); +#endif + + frame.sync(stubcc.masm, Uses(0)); stubcc.masm.move(ImmPtr(PC), Registers::ArgReg1); stubcc.call(stubs::Interrupt); ADD_CALLSITE(true); stubcc.rejoin(Changes(0)); + +#ifdef JS_THREADSAFE + stubcc.linkRejoin(noInterrupt); +#endif + + frame.freeReg(reg); } void @@ -2498,7 +2595,7 @@ mjit::Compiler::passMICAddress(MICGenInfo &mic) void mjit::Compiler::passPICAddress(PICGenInfo &pic) { - pic.addrLabel = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1); + pic.paramAddr = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1); } bool @@ -2573,7 +2670,7 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck, bool usePropCache) stubcc.leave(); passPICAddress(pic); - pic.callReturn = stubcc.call(ic::GetProp); + pic.slowPathCall = stubcc.call(ic::GetProp); /* Load dslots. */ #if defined JS_NUNBOX32 @@ -2597,25 +2694,25 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck, bool usePropCache) Label inlineValueLoadLabel = masm.loadValueAsComponents(slot, shapeReg, objReg); #endif - pic.storeBack = masm.label(); + pic.fastPathRejoin = masm.label(); /* Assert correctness of hardcoded offsets. */ RETURN_IF_OOM(false); #if defined JS_NUNBOX32 - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDslotsLoad) == GETPROP_DSLOTS_LOAD); - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgTypeLoad) == GETPROP_TYPE_LOAD); - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDataLoad) == GETPROP_DATA_LOAD); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDslotsLoad) == GETPROP_DSLOTS_LOAD); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgTypeLoad) == GETPROP_TYPE_LOAD); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDataLoad) == GETPROP_DATA_LOAD); JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineShapeLabel) == GETPROP_INLINE_SHAPE_OFFSET); JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP); #elif defined JS_PUNBOX64 - pic.labels.getprop.dslotsLoadOffset = masm.differenceBetween(pic.storeBack, dslotsLoadLabel); - JS_ASSERT(pic.labels.getprop.dslotsLoadOffset == masm.differenceBetween(pic.storeBack, dslotsLoadLabel)); + pic.labels.getprop.dslotsLoadOffset = masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel); + JS_ASSERT(pic.labels.getprop.dslotsLoadOffset == masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel)); pic.labels.getprop.inlineShapeOffset = masm.differenceBetween(pic.shapeGuard, inlineShapeLabel); JS_ASSERT(pic.labels.getprop.inlineShapeOffset == masm.differenceBetween(pic.shapeGuard, inlineShapeLabel)); - pic.labels.getprop.inlineValueOffset = masm.differenceBetween(pic.storeBack, inlineValueLoadLabel); - JS_ASSERT(pic.labels.getprop.inlineValueOffset == masm.differenceBetween(pic.storeBack, inlineValueLoadLabel)); + pic.labels.getprop.inlineValueOffset = masm.differenceBetween(pic.fastPathRejoin, inlineValueLoadLabel); + JS_ASSERT(pic.labels.getprop.inlineValueOffset == masm.differenceBetween(pic.fastPathRejoin, inlineValueLoadLabel)); JS_ASSERT(masm.differenceBetween(inlineShapeLabel, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP); #endif @@ -2675,7 +2772,7 @@ mjit::Compiler::jsop_getelem_pic(FrameEntry *obj, FrameEntry *id, RegisterID obj stubcc.leave(); passPICAddress(pic); - pic.callReturn = stubcc.call(ic::GetElem); + pic.slowPathCall = stubcc.call(ic::GetElem); /* Load dslots. */ #if defined JS_NUNBOX32 @@ -2696,23 +2793,23 @@ mjit::Compiler::jsop_getelem_pic(FrameEntry *obj, FrameEntry *id, RegisterID obj Label inlineValueOffsetLabel = masm.loadValueAsComponents(slot, shapeReg, objReg); #endif - pic.storeBack = masm.label(); + pic.fastPathRejoin = masm.label(); pic.objReg = objReg; pic.idReg = idReg; RETURN_IF_OOM(false); #if defined JS_NUNBOX32 - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDslotsLoad) == GETELEM_DSLOTS_LOAD); - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgTypeLoad) == GETELEM_TYPE_LOAD); - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDataLoad) == GETELEM_DATA_LOAD); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDslotsLoad) == GETPROP_DSLOTS_LOAD); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgTypeLoad) == GETPROP_TYPE_LOAD); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDataLoad) == GETPROP_DATA_LOAD); JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineAtomOffsetLabel) == GETELEM_INLINE_ATOM_OFFSET); JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineAtomJump) == GETELEM_INLINE_ATOM_JUMP); JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel) == GETELEM_INLINE_SHAPE_OFFSET); JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineShapeJump) == GETELEM_INLINE_SHAPE_JUMP); #elif defined JS_PUNBOX64 - pic.labels.getelem.dslotsLoadOffset = masm.differenceBetween(pic.storeBack, dslotsLoadLabel); - JS_ASSERT(pic.labels.getelem.dslotsLoadOffset == masm.differenceBetween(pic.storeBack, dslotsLoadLabel)); + pic.labels.getprop.dslotsLoadOffset = masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel); + JS_ASSERT(pic.labels.getprop.dslotsLoadOffset == masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel)); pic.labels.getelem.inlineShapeOffset = masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel); JS_ASSERT(pic.labels.getelem.inlineShapeOffset == masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel)); @@ -2720,8 +2817,8 @@ mjit::Compiler::jsop_getelem_pic(FrameEntry *obj, FrameEntry *id, RegisterID obj pic.labels.getelem.inlineAtomOffset = masm.differenceBetween(pic.shapeGuard, inlineAtomOffsetLabel); JS_ASSERT(pic.labels.getelem.inlineAtomOffset == masm.differenceBetween(pic.shapeGuard, inlineAtomOffsetLabel)); - pic.labels.getelem.inlineValueOffset = masm.differenceBetween(pic.storeBack, inlineValueOffsetLabel); - JS_ASSERT(pic.labels.getelem.inlineValueOffset == masm.differenceBetween(pic.storeBack, inlineValueOffsetLabel)); + pic.labels.getelem.inlineValueOffset = masm.differenceBetween(pic.fastPathRejoin, inlineValueOffsetLabel); + JS_ASSERT(pic.labels.getelem.inlineValueOffset == masm.differenceBetween(pic.fastPathRejoin, inlineValueOffsetLabel)); JS_ASSERT(masm.differenceBetween(inlineShapeOffsetLabel, dbgInlineShapeJump) == GETELEM_INLINE_SHAPE_JUMP); JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineAtomJump) == @@ -2752,6 +2849,8 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom) PICGenInfo pic(ic::PICInfo::CALL, true); + pic.pc = PC; + /* Guard that the type is an object. */ pic.typeReg = frame.copyTypeIntoReg(top); @@ -2803,7 +2902,7 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom) /* Slow path. */ stubcc.leave(); passPICAddress(pic); - pic.callReturn = stubcc.call(ic::CallProp); + pic.slowPathCall = stubcc.call(ic::CallProp); /* Adjust the frame. None of this will generate code. */ frame.pop(); @@ -2831,26 +2930,26 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom) Label inlineValueLoadLabel = masm.loadValueAsComponents(slot, shapeReg, objReg); #endif - pic.storeBack = masm.label(); + pic.fastPathRejoin = masm.label(); /* Assert correctness of hardcoded offsets. */ RETURN_IF_OOM(false); JS_ASSERT(masm.differenceBetween(pic.fastPathStart, dbgInlineTypeGuard) == GETPROP_INLINE_TYPE_GUARD); #if defined JS_NUNBOX32 - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDslotsLoad) == GETPROP_DSLOTS_LOAD); - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgTypeLoad) == GETPROP_TYPE_LOAD); - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDataLoad) == GETPROP_DATA_LOAD); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDslotsLoad) == GETPROP_DSLOTS_LOAD); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgTypeLoad) == GETPROP_TYPE_LOAD); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDataLoad) == GETPROP_DATA_LOAD); JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineShapeLabel) == GETPROP_INLINE_SHAPE_OFFSET); JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP); #elif defined JS_PUNBOX64 - pic.labels.getprop.dslotsLoadOffset = masm.differenceBetween(pic.storeBack, dslotsLoadLabel); - JS_ASSERT(pic.labels.getprop.dslotsLoadOffset == masm.differenceBetween(pic.storeBack, dslotsLoadLabel)); + pic.labels.getprop.dslotsLoadOffset = masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel); + JS_ASSERT(pic.labels.getprop.dslotsLoadOffset == masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel)); pic.labels.getprop.inlineShapeOffset = masm.differenceBetween(pic.shapeGuard, inlineShapeLabel); JS_ASSERT(pic.labels.getprop.inlineShapeOffset == masm.differenceBetween(pic.shapeGuard, inlineShapeLabel)); - pic.labels.getprop.inlineValueOffset = masm.differenceBetween(pic.storeBack, inlineValueLoadLabel); - JS_ASSERT(pic.labels.getprop.inlineValueOffset == masm.differenceBetween(pic.storeBack, inlineValueLoadLabel)); + pic.labels.getprop.inlineValueOffset = masm.differenceBetween(pic.fastPathRejoin, inlineValueLoadLabel); + JS_ASSERT(pic.labels.getprop.inlineValueOffset == masm.differenceBetween(pic.fastPathRejoin, inlineValueLoadLabel)); JS_ASSERT(masm.differenceBetween(inlineShapeLabel, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP); #endif @@ -2925,6 +3024,7 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom) JS_ASSERT(top->isTypeKnown()); JS_ASSERT(top->getKnownType() == JSVAL_TYPE_OBJECT); + pic.pc = PC; pic.fastPathStart = masm.label(); pic.hasTypeCheck = false; pic.typeReg = Registers::ReturnReg; @@ -2950,7 +3050,7 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom) stubcc.leave(); passPICAddress(pic); - pic.callReturn = stubcc.call(ic::CallProp); + pic.slowPathCall = stubcc.call(ic::CallProp); /* Load dslots. */ #if defined JS_NUNBOX32 @@ -2974,14 +3074,14 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom) masm.loadValueAsComponents(slot, shapeReg, objReg); #endif - pic.storeBack = masm.label(); + pic.fastPathRejoin = masm.label(); pic.objReg = objReg; /* * 1) Dup the |this| object. * 2) Push the property value onto the stack. * 3) Move the value below the dup'd |this|, uncopying it. This could - * generate code, thus the storeBack label being prior. This is safe + * generate code, thus the fastPathRejoin label being prior. This is safe * as a stack transition, because JSOP_CALLPROP has JOF_TMPSLOT. It is * also safe for correctness, because if we know the LHS is an object, it * is the resulting vp[1]. @@ -2996,20 +3096,20 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom) */ RETURN_IF_OOM(false); #if defined JS_NUNBOX32 - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDslotsLoad) == GETPROP_DSLOTS_LOAD); - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgTypeLoad) == GETPROP_TYPE_LOAD); - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDataLoad) == GETPROP_DATA_LOAD); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDslotsLoad) == GETPROP_DSLOTS_LOAD); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgTypeLoad) == GETPROP_TYPE_LOAD); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDataLoad) == GETPROP_DATA_LOAD); JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineShapeLabel) == GETPROP_INLINE_SHAPE_OFFSET); JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP); #elif defined JS_PUNBOX64 - pic.labels.getprop.dslotsLoadOffset = masm.differenceBetween(pic.storeBack, dslotsLoadLabel); - JS_ASSERT(pic.labels.getprop.dslotsLoadOffset == masm.differenceBetween(pic.storeBack, dslotsLoadLabel)); + pic.labels.getprop.dslotsLoadOffset = masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel); + JS_ASSERT(pic.labels.getprop.dslotsLoadOffset == masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel)); pic.labels.getprop.inlineShapeOffset = masm.differenceBetween(pic.shapeGuard, inlineShapeLabel); JS_ASSERT(pic.labels.getprop.inlineShapeOffset == masm.differenceBetween(pic.shapeGuard, inlineShapeLabel)); - pic.labels.getprop.inlineValueOffset = masm.differenceBetween(pic.storeBack, inlineValueLoadLabel); - JS_ASSERT(pic.labels.getprop.inlineValueOffset == masm.differenceBetween(pic.storeBack, inlineValueLoadLabel)); + pic.labels.getprop.inlineValueOffset = masm.differenceBetween(pic.fastPathRejoin, inlineValueLoadLabel); + JS_ASSERT(pic.labels.getprop.inlineValueOffset == masm.differenceBetween(pic.fastPathRejoin, inlineValueLoadLabel)); JS_ASSERT(masm.differenceBetween(inlineShapeLabel, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP); #endif @@ -3110,7 +3210,7 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache) stubcc.leave(); passPICAddress(pic); - pic.callReturn = stubcc.call(ic::SetProp); + pic.slowPathCall = stubcc.call(ic::SetProp); } /* Load dslots. */ @@ -3129,7 +3229,7 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache) masm.storeValue(vr, slot); #endif DBGLABEL(dbgAfterValueStore); - pic.storeBack = masm.label(); + pic.fastPathRejoin = masm.label(); frame.freeReg(objReg); frame.freeReg(shapeReg); @@ -3146,26 +3246,26 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache) RETURN_IF_OOM(false); #if defined JS_PUNBOX64 - pic.labels.setprop.dslotsLoadOffset = masm.differenceBetween(pic.storeBack, dslotsLoadLabel); + pic.labels.setprop.dslotsLoadOffset = masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel); pic.labels.setprop.inlineShapeOffset = masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel); JS_ASSERT(masm.differenceBetween(inlineShapeOffsetLabel, dbgInlineShapeJump) == SETPROP_INLINE_SHAPE_JUMP); - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgAfterValueStore) == SETPROP_INLINE_STORE_VALUE); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgAfterValueStore) == SETPROP_INLINE_STORE_VALUE); #elif defined JS_NUNBOX32 JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel) == SETPROP_INLINE_SHAPE_OFFSET); JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineShapeJump) == SETPROP_INLINE_SHAPE_JUMP); - if (vr.isConstant) { + if (vr.isConstant()) { /* Constants are offset inside the opcode by 4. */ - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgInlineStoreType)-4 == SETPROP_INLINE_STORE_CONST_TYPE); - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgAfterValueStore)-4 == SETPROP_INLINE_STORE_CONST_DATA); - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDslots) == SETPROP_DSLOTS_BEFORE_CONSTANT); - } else if (vr.u.s.isTypeKnown) { - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgInlineStoreType)-4 == SETPROP_INLINE_STORE_KTYPE_TYPE); - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgAfterValueStore) == SETPROP_INLINE_STORE_KTYPE_DATA); - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDslots) == SETPROP_DSLOTS_BEFORE_KTYPE); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgInlineStoreType)-4 == SETPROP_INLINE_STORE_CONST_TYPE); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgAfterValueStore)-4 == SETPROP_INLINE_STORE_CONST_DATA); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDslots) == SETPROP_DSLOTS_BEFORE_CONSTANT); + } else if (vr.isTypeKnown()) { + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgInlineStoreType)-4 == SETPROP_INLINE_STORE_KTYPE_TYPE); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgAfterValueStore) == SETPROP_INLINE_STORE_KTYPE_DATA); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDslots) == SETPROP_DSLOTS_BEFORE_KTYPE); } else { - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgInlineStoreType) == SETPROP_INLINE_STORE_DYN_TYPE); - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgAfterValueStore) == SETPROP_INLINE_STORE_DYN_DATA); - JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDslots) == SETPROP_DSLOTS_BEFORE_DYNAMIC); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgInlineStoreType) == SETPROP_INLINE_STORE_DYN_TYPE); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgAfterValueStore) == SETPROP_INLINE_STORE_DYN_DATA); + JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDslots) == SETPROP_DSLOTS_BEFORE_DYNAMIC); } #endif @@ -3192,10 +3292,10 @@ mjit::Compiler::jsop_name(JSAtom *atom) pic.slowPathStart = stubcc.linkExit(j, Uses(0)); stubcc.leave(); passPICAddress(pic); - pic.callReturn = stubcc.call(ic::Name); + pic.slowPathCall = stubcc.call(ic::Name); } - pic.storeBack = masm.label(); + pic.fastPathRejoin = masm.label(); frame.pushRegs(pic.shapeReg, pic.objReg); JS_ASSERT(masm.differenceBetween(pic.fastPathStart, dbgJumpOffset) == SCOPENAME_JUMP_OFFSET); @@ -3234,10 +3334,10 @@ mjit::Compiler::jsop_xname(JSAtom *atom) pic.slowPathStart = stubcc.linkExit(j, Uses(1)); stubcc.leave(); passPICAddress(pic); - pic.callReturn = stubcc.call(ic::XName); + pic.slowPathCall = stubcc.call(ic::XName); } - pic.storeBack = masm.label(); + pic.fastPathRejoin = masm.label(); frame.pop(); frame.pushRegs(pic.shapeReg, pic.objReg); @@ -3254,6 +3354,12 @@ mjit::Compiler::jsop_bindname(uint32 index, bool usePropCache) { PICGenInfo pic(ic::PICInfo::BIND, usePropCache); + // This code does not check the frame flags to see if scopeChain has been + // set. Rather, it relies on the up-front analysis statically determining + // whether BINDNAME can be used, which reifies the scope chain at the + // prologue. + JS_ASSERT(analysis->usesScopeChain()); + pic.shapeReg = frame.allocReg(); pic.objReg = frame.allocReg(); pic.typeReg = Registers::ReturnReg; @@ -3277,10 +3383,10 @@ mjit::Compiler::jsop_bindname(uint32 index, bool usePropCache) pic.slowPathStart = stubcc.linkExit(j, Uses(0)); stubcc.leave(); passPICAddress(pic); - pic.callReturn = stubcc.call(ic::BindName); + pic.slowPathCall = stubcc.call(ic::BindName); } - pic.storeBack = masm.label(); + pic.fastPathRejoin = masm.label(); frame.pushTypedPayload(JSVAL_TYPE_OBJECT, pic.objReg); frame.freeReg(pic.shapeReg); @@ -3359,9 +3465,19 @@ mjit::Compiler::jsop_bindname(uint32 index, bool usePropCache) #endif void -mjit::Compiler::jsop_getarg(uint32 index) +mjit::Compiler::jsop_getarg(uint32 slot) { - frame.push(Address(JSFrameReg, JSStackFrame::offsetOfFormalArg(fun, index))); + frame.push(Address(JSFrameReg, JSStackFrame::offsetOfFormalArg(fun, slot))); +} + +void +mjit::Compiler::jsop_setarg(uint32 slot, bool popped) +{ + FrameEntry *top = frame.peek(-1); + RegisterID reg = frame.allocReg(); + Address address = Address(JSFrameReg, JSStackFrame::offsetOfFormalArg(fun, slot)); + frame.storeTo(top, address, popped); + frame.freeReg(reg); } void @@ -3388,7 +3504,7 @@ mjit::Compiler::jsop_gnameinc(JSOp op, VoidStubAtom stub, uint32 index) { #if defined JS_MONOIC jsbytecode *next = &PC[JSOP_GNAMEINC_LENGTH]; - bool pop = (JSOp(*next) == JSOP_POP) && !analysis[next].nincoming; + bool pop = (JSOp(*next) == JSOP_POP) && !analysis->jumpTarget(next); int amt = (op == JSOP_GNAMEINC || op == JSOP_INCGNAME) ? -1 : 1; if (pop || (op == JSOP_INCGNAME || op == JSOP_DECGNAME)) { @@ -3477,7 +3593,7 @@ mjit::Compiler::jsop_nameinc(JSOp op, VoidStubAtom stub, uint32 index) JSAtom *atom = script->getAtom(index); #if defined JS_POLYIC jsbytecode *next = &PC[JSOP_NAMEINC_LENGTH]; - bool pop = (JSOp(*next) == JSOP_POP) && !analysis[next].nincoming; + bool pop = (JSOp(*next) == JSOP_POP) && !analysis->jumpTarget(next); int amt = (op == JSOP_NAMEINC || op == JSOP_INCNAME) ? -1 : 1; if (pop || (op == JSOP_INCNAME || op == JSOP_DECNAME)) { @@ -3570,7 +3686,7 @@ mjit::Compiler::jsop_propinc(JSOp op, VoidStubAtom stub, uint32 index) FrameEntry *objFe = frame.peek(-1); if (!objFe->isTypeKnown() || objFe->getKnownType() == JSVAL_TYPE_OBJECT) { jsbytecode *next = &PC[JSOP_PROPINC_LENGTH]; - bool pop = (JSOp(*next) == JSOP_POP) && !analysis[next].nincoming; + bool pop = (JSOp(*next) == JSOP_POP) && !analysis->jumpTarget(next); int amt = (op == JSOP_PROPINC || op == JSOP_INCPROP) ? -1 : 1; if (pop || (op == JSOP_INCPROP || op == JSOP_DECPROP)) { @@ -3778,8 +3894,7 @@ mjit::Compiler::iterNext() frame.unpinReg(reg); /* Test clasp */ - masm.loadPtr(Address(reg, offsetof(JSObject, clasp)), T1); - Jump notFast = masm.branchPtr(Assembler::NotEqual, T1, ImmPtr(&js_IteratorClass)); + Jump notFast = masm.testObjClass(Assembler::NotEqual, reg, &js_IteratorClass); stubcc.linkExit(notFast, Uses(1)); /* Get private from iter obj. */ @@ -3833,8 +3948,7 @@ mjit::Compiler::iterMore() frame.unpinReg(reg); /* Test clasp */ - masm.loadPtr(Address(reg, offsetof(JSObject, clasp)), T1); - Jump notFast = masm.branchPtr(Assembler::NotEqual, T1, ImmPtr(&js_IteratorClass)); + Jump notFast = masm.testObjClass(Assembler::NotEqual, reg, &js_IteratorClass); stubcc.linkExitForBranch(notFast); /* Get private from iter obj. */ @@ -3879,8 +3993,7 @@ mjit::Compiler::iterEnd() frame.unpinReg(reg); /* Test clasp */ - masm.loadPtr(Address(reg, offsetof(JSObject, clasp)), T1); - Jump notIterator = masm.branchPtr(Assembler::NotEqual, T1, ImmPtr(&js_IteratorClass)); + Jump notIterator = masm.testObjClass(Assembler::NotEqual, reg, &js_IteratorClass); stubcc.linkExit(notIterator, Uses(1)); /* Get private from iter obj. :FIXME: X64 */ @@ -4291,6 +4404,14 @@ mjit::Compiler::jsop_instanceof() return true; } +void +mjit::Compiler::jsop_eval() +{ + JaegerSpew(JSpew_Insns, " --- SCRIPTED CALL --- \n"); + inlineCallHelper(GET_ARGC(PC), false); + JaegerSpew(JSpew_Insns, " --- END SCRIPTED CALL --- \n"); +} + /* * Note: This function emits tracer hooks into the OOL path. This means if * it is used in the middle of an in-progress slow path, the stream will be @@ -4368,7 +4489,7 @@ mjit::Compiler::enterBlock(JSObject *obj) // VMFrame::fp to the correct fp for the entry point. We need to copy // that value here to FpReg so that FpReg also has the correct sp. // Otherwise, we would simply be using a stale FpReg value. - if (analysis[PC].exceptionEntry) + if (analysis->getCode(PC).exceptionEntry) restoreFrameRegs(masm); uint32 oldFrameDepth = frame.frameDepth(); diff --git a/js/src/methodjit/Compiler.h b/js/src/methodjit/Compiler.h index eced73f2f976..4483e4f81856 100644 --- a/js/src/methodjit/Compiler.h +++ b/js/src/methodjit/Compiler.h @@ -40,9 +40,9 @@ #if !defined jsjaeger_compiler_h__ && defined JS_METHODJIT #define jsjaeger_compiler_h__ +#include "jsanalyze.h" #include "jscntxt.h" #include "jstl.h" -#include "BytecodeAnalyzer.h" #include "MethodJIT.h" #include "CodeGenIncludes.h" #include "BaseCompiler.h" @@ -161,45 +161,49 @@ class Compiler : public BaseCompiler }; #if defined JS_POLYIC - struct PICGenInfo { + struct BaseICInfo { + Label fastPathStart; + Label fastPathRejoin; + Label slowPathStart; + Call slowPathCall; + DataLabelPtr paramAddr; + }; + + struct PICGenInfo : public BaseICInfo { PICGenInfo(ic::PICInfo::Kind kind, bool usePropCache) : kind(kind), usePropCache(usePropCache) { } ic::PICInfo::Kind kind; - Label fastPathStart; - Label storeBack; Label typeCheck; - Label slowPathStart; - DataLabelPtr addrLabel; RegisterID shapeReg; RegisterID objReg; RegisterID idReg; RegisterID typeReg; bool usePropCache; Label shapeGuard; + jsbytecode *pc; JSAtom *atom; StateRemat objRemat; StateRemat idRemat; - Call callReturn; bool hasTypeCheck; ValueRemat vr; # if defined JS_CPU_X64 ic::PICLabels labels; # endif - void copySimpleMembersTo(ic::PICInfo &pi) const { - pi.kind = kind; - pi.shapeReg = shapeReg; - pi.objReg = objReg; - pi.atom = atom; - pi.usePropCache = usePropCache; - if (kind == ic::PICInfo::SET) { - pi.u.vr = vr; - } else if (kind != ic::PICInfo::NAME) { - pi.u.get.idReg = idReg; - pi.u.get.typeReg = typeReg; - pi.u.get.hasTypeCheck = hasTypeCheck; - pi.u.get.objRemat = objRemat.offset; + void copySimpleMembersTo(ic::PICInfo &ic) const { + ic.kind = kind; + ic.shapeReg = shapeReg; + ic.objReg = objReg; + ic.atom = atom; + ic.usePropCache = usePropCache; + if (ic.isSet()) { + ic.u.vr = vr; + } else if (ic.isGet()) { + ic.u.get.idReg = idReg; + ic.u.get.typeReg = typeReg; + ic.u.get.hasTypeCheck = hasTypeCheck; + ic.setObjRemat(objRemat); } } @@ -232,7 +236,7 @@ class Compiler : public BaseCompiler JSObject *globalObj; JSFunction *fun; bool isConstructing; - BytecodeAnalyzer analysis; + analyze::Script *analysis; Label *jumpMap; jsbytecode *PC; Assembler masm; @@ -307,7 +311,8 @@ class Compiler : public BaseCompiler void jsop_setglobal(uint32 index); void jsop_getglobal(uint32 index); void jsop_getprop_slow(JSAtom *atom, bool usePropCache = true); - void jsop_getarg(uint32 index); + void jsop_getarg(uint32 slot); + void jsop_setarg(uint32 slot, bool popped); void jsop_this(); void emitReturn(FrameEntry *fe); void emitFinalReturn(Assembler &masm); @@ -344,6 +349,7 @@ class Compiler : public BaseCompiler bool jsop_xname(JSAtom *atom); void enterBlock(JSObject *obj); void leaveBlock(); + void jsop_eval(); /* Fast arithmetic. */ void jsop_binary(JSOp op, VoidStub stub); diff --git a/js/src/methodjit/FastArithmetic.cpp b/js/src/methodjit/FastArithmetic.cpp index bb76b29d5397..500748b43dd4 100644 --- a/js/src/methodjit/FastArithmetic.cpp +++ b/js/src/methodjit/FastArithmetic.cpp @@ -1050,7 +1050,7 @@ mjit::Compiler::jsop_equality_int_string(JSOp op, BoolStub stub, jsbytecode *tar Jump fast; MaybeJump firstStubJump; - if (lhsInt || rhsInt || (!lhs->isTypeKnown() && !rhs->isTypeKnown())) { + if ((!lhs->isTypeKnown() || lhsInt) && (!rhs->isTypeKnown() || rhsInt)) { if (!lhsInt) { Jump lhsFail = masm.testInt32(Assembler::NotEqual, lvr.typeReg()); stubcc.linkExitDirect(lhsFail, stubEntry); @@ -1102,13 +1102,17 @@ mjit::Compiler::jsop_equality_int_string(JSOp op, BoolStub stub, jsbytecode *tar JS_ASSERT(!lhs->isType(JSVAL_TYPE_STRING) && !rhs->isType(JSVAL_TYPE_STRING)); /* Test the types. */ - if (!lhsInt) { - Jump lhsFail = frame.testInt32(Assembler::NotEqual, lhs); - stubcc.linkExit(lhsFail, Uses(2)); - } - if (!rhsInt) { - Jump rhsFail = frame.testInt32(Assembler::NotEqual, rhs); - stubcc.linkExit(rhsFail, Uses(2)); + if ((lhs->isTypeKnown() && !lhsInt) || (rhs->isTypeKnown() && !rhsInt)) { + stubcc.linkExit(masm.jump(), Uses(2)); + } else { + if (!lhsInt) { + Jump lhsFail = frame.testInt32(Assembler::NotEqual, lhs); + stubcc.linkExit(lhsFail, Uses(2)); + } + if (!rhsInt) { + Jump rhsFail = frame.testInt32(Assembler::NotEqual, rhs); + stubcc.linkExit(rhsFail, Uses(2)); + } } stubcc.leave(); diff --git a/js/src/methodjit/FastOps.cpp b/js/src/methodjit/FastOps.cpp index b55d68561f68..76cf06f3f24e 100644 --- a/js/src/methodjit/FastOps.cpp +++ b/js/src/methodjit/FastOps.cpp @@ -524,13 +524,21 @@ mjit::Compiler::jsop_bitop(JSOp op) RegisterID rr = frame.tempRegForData(rhs); #endif - if (lhs->isConstant()) { - frame.pinReg(rr); + if (frame.haveSameBacking(lhs, rhs)) { + // It's okay to allocReg(). If |rr| is evicted, it won't result in + // a load, and |rr == reg| is fine since this is (x << x). reg = frame.allocReg(); - masm.move(Imm32(lhs->getValue().toInt32()), reg); - frame.unpinReg(rr); + if (rr != reg) + masm.move(rr, reg); } else { - reg = frame.copyDataIntoReg(lhs); + frame.pinReg(rr); + if (lhs->isConstant()) { + reg = frame.allocReg(); + masm.move(Imm32(lhs->getValue().toInt32()), reg); + } else { + reg = frame.copyDataIntoReg(lhs); + } + frame.unpinReg(rr); } if (op == JSOP_LSH) { @@ -574,7 +582,7 @@ mjit::Compiler::jsop_globalinc(JSOp op, uint32 index) bool popped = false; PC += JSOP_GLOBALINC_LENGTH; - if (JSOp(*PC) == JSOP_POP && !analysis[PC].nincoming) { + if (JSOp(*PC) == JSOP_POP && !analysis->jumpTarget(PC)) { popped = true; PC += JSOP_POP_LENGTH; } @@ -1212,9 +1220,7 @@ mjit::Compiler::jsop_setelem() /* obj.isDenseArray() */ RegisterID objReg = frame.copyDataIntoReg(obj); - Jump guardDense = masm.branchPtr(Assembler::NotEqual, - Address(objReg, offsetof(JSObject, clasp)), - ImmPtr(&js_ArrayClass)); + Jump guardDense = masm.testObjClass(Assembler::NotEqual, objReg, &js_ArrayClass); stubcc.linkExit(guardDense, Uses(3)); /* guard within capacity */ @@ -1359,54 +1365,18 @@ mjit::Compiler::jsop_getelem_dense(FrameEntry *obj, FrameEntry *id, RegisterID o MaybeRegisterID &idReg, RegisterID tmpReg) { /* Note: idReg is only valid if id is not a constant. */ - Jump guardDense = masm.branchPtr(Assembler::NotEqual, - Address(objReg, offsetof(JSObject, clasp)), - ImmPtr(&js_ArrayClass)); + Jump guardDense = masm.testObjClass(Assembler::NotEqual, objReg, &js_ArrayClass); stubcc.linkExit(guardDense, Uses(2)); - /* Guard within capacity. */ - Jump inRange; - Address capacity(objReg, offsetof(JSObject, capacity)); - if (id->isConstant()) { - inRange = masm.branch32(Assembler::LessThanOrEqual, capacity, - Imm32(id->getValue().toInt32())); - } else { - inRange = masm.branch32(Assembler::AboveOrEqual, idReg.reg(), capacity); - } - stubcc.linkExit(inRange, Uses(2)); + Int32Key key = idReg.isSet() + ? Int32Key::FromRegister(idReg.reg()) + : Int32Key::FromConstant(id->getValue().toInt32()); - /* load dslots */ - masm.loadPtr(Address(objReg, offsetof(JSObject, slots)), objReg); + Assembler::FastArrayLoadFails fails = + masm.fastArrayLoad(objReg, key, tmpReg, objReg); - /* guard within capacity */ - if (id->isConstant()) { - /* guard not a hole */ - Address slot(objReg, id->getValue().toInt32() * sizeof(Value)); -#if defined JS_NUNBOX32 - masm.loadTypeTag(slot, tmpReg); - Jump notHole = masm.branchPtr(Assembler::Equal, tmpReg, ImmType(JSVAL_TYPE_MAGIC)); - masm.loadPayload(slot, objReg); -#elif defined JS_PUNBOX64 - masm.loadValueAsComponents(slot, tmpReg, objReg); - Jump notHole = masm.branchPtr(Assembler::Equal, tmpReg, ImmType(JSVAL_TYPE_MAGIC)); -#endif - stubcc.linkExit(notHole, Uses(2)); - } else { - /* guard not a hole */ - BaseIndex slot(objReg, idReg.reg(), Assembler::JSVAL_SCALE); -#if defined JS_NUNBOX32 - masm.loadTypeTag(slot, tmpReg); - Jump notHole = masm.branchPtr(Assembler::Equal, tmpReg, ImmType(JSVAL_TYPE_MAGIC)); - masm.loadPayload(slot, objReg); -#elif defined JS_PUNBOX64 - masm.loadValueAsComponents(slot, tmpReg, objReg); - Jump notHole = masm.branchPtr(Assembler::Equal, tmpReg, ImmType(JSVAL_TYPE_MAGIC)); -#endif - stubcc.linkExit(notHole, Uses(2)); - } - /* Postcondition: type must be in tmpReg, data must be in objReg. */ - - /* Note: linkExits will be hooked up to a leave() after this method completes. */ + stubcc.linkExit(fails.rangeCheck, Uses(2)); + stubcc.linkExit(fails.holeCheck, Uses(2)); } bool diff --git a/js/src/methodjit/FrameState-inl.h b/js/src/methodjit/FrameState-inl.h index 666aeb231482..884eae716f75 100644 --- a/js/src/methodjit/FrameState-inl.h +++ b/js/src/methodjit/FrameState-inl.h @@ -932,16 +932,12 @@ FrameState::dataRematInfo(const FrameEntry *fe) const { if (fe->isCopy()) fe = fe->copyOf(); - StateRemat remat; - if (fe->data.inRegister()) { - remat.reg = fe->data.reg(); - remat.inReg = true; - } else { - JS_ASSERT(fe->data.synced()); - remat.offset = addressOf(fe).offset; - remat.inReg = false; - } - return remat; + + if (fe->data.inRegister()) + return StateRemat::FromRegister(fe->data.reg()); + + JS_ASSERT(fe->data.synced()); + return StateRemat::FromAddress(addressOf(fe)); } inline void diff --git a/js/src/methodjit/FrameState.cpp b/js/src/methodjit/FrameState.cpp index c80614133409..4ade98dd62fb 100644 --- a/js/src/methodjit/FrameState.cpp +++ b/js/src/methodjit/FrameState.cpp @@ -326,7 +326,7 @@ FrameState::storeTo(FrameEntry *fe, Address address, bool popped) #endif } -void FrameState::loadTo(FrameEntry *fe, RegisterID typeReg, RegisterID dataReg, RegisterID tempReg) +void FrameState::loadForReturn(FrameEntry *fe, RegisterID typeReg, RegisterID dataReg, RegisterID tempReg) { JS_ASSERT(dataReg != typeReg && dataReg != tempReg && typeReg != tempReg); @@ -338,25 +338,51 @@ void FrameState::loadTo(FrameEntry *fe, RegisterID typeReg, RegisterID dataReg, if (fe->isCopy()) fe = fe->copyOf(); + MaybeRegisterID maybeType = maybePinType(fe); + MaybeRegisterID maybeData = maybePinData(fe); + if (fe->isTypeKnown()) { - RegisterID data = tempRegForData(fe); - if (data != dataReg) - masm.move(data, dataReg); + // If the data is in memory, or in the wrong reg, load/move it. + if (!maybeData.isSet()) + masm.loadPayload(addressOf(fe), dataReg); + else if (maybeData.reg() != dataReg) + masm.move(maybeData.reg(), dataReg); masm.move(ImmType(fe->getKnownType()), typeReg); return; } -#ifdef JS_PUNBOX64 - // If the value is synced, and requires at least one load, we can do - // better on x64. + // If both halves of the value are in memory, make this easier and load + // both pieces into their respective registers. if (fe->type.inMemory() && fe->data.inMemory()) { masm.loadValueAsComponents(addressOf(fe), typeReg, dataReg); return; } -#endif - RegisterID data = tempRegForData(fe); - RegisterID type = tempRegForType(fe); + // Now, we should be guaranteed that at least one part is in a register. + JS_ASSERT(maybeType.isSet() || maybeData.isSet()); + + // Make sure we have two registers while making sure not clobber either half. + // Here we are allowed to mess up the FrameState invariants, because this + // is specialized code for a path that is about to discard the entire frame. + if (!maybeType.isSet()) { + JS_ASSERT(maybeData.isSet()); + if (maybeData.reg() != typeReg) + maybeType = typeReg; + else + maybeType = tempReg; + masm.loadTypeTag(addressOf(fe), maybeType.reg()); + } else if (!maybeData.isSet()) { + JS_ASSERT(maybeType.isSet()); + if (maybeType.reg() != dataReg) + maybeData = dataReg; + else + maybeData = tempReg; + masm.loadPayload(addressOf(fe), maybeData.reg()); + } + + RegisterID type = maybeType.reg(); + RegisterID data = maybeData.reg(); + if (data == typeReg && type == dataReg) { masm.move(type, tempReg); masm.move(data, dataReg); @@ -1305,32 +1331,39 @@ FrameState::shift(int32 n) void FrameState::pinEntry(FrameEntry *fe, ValueRemat &vr) { + if (fe->isConstant()) { + vr = ValueRemat::FromConstant(fe->getValue()); + } else { + // Pin the type register so it can't spill. + MaybeRegisterID maybePinnedType = maybePinType(fe); + + // Get and pin the data register. + RegisterID dataReg = tempRegForData(fe); + pinReg(dataReg); + + if (fe->isTypeKnown()) { + vr = ValueRemat::FromKnownType(fe->getKnownType(), dataReg); + } else { + // The type might not be loaded yet, so unpin for simplicity. + maybeUnpinReg(maybePinnedType); + + vr = ValueRemat::FromRegisters(tempRegForType(fe), dataReg); + pinReg(vr.typeReg()); + } + } + + // Set these bits last, since allocation could have caused a sync. vr.isDataSynced = fe->data.synced(); vr.isTypeSynced = fe->type.synced(); - if (fe->isConstant()) { - vr.isConstant = true; - vr.u.v = Jsvalify(fe->getValue()); - } else { - vr.isConstant = false; - vr.u.s.isTypeKnown = fe->isTypeKnown(); - if (vr.u.s.isTypeKnown) { - vr.u.s.type.knownType = fe->getKnownType(); - } else { - vr.u.s.type.reg = tempRegForType(fe); - pinReg(vr.u.s.type.reg); - } - vr.u.s.data = tempRegForData(fe); - pinReg(vr.u.s.data); - } } void FrameState::unpinEntry(const ValueRemat &vr) { - if (!vr.isConstant) { - if (!vr.u.s.isTypeKnown) - unpinReg(vr.u.s.type.reg); - unpinReg(vr.u.s.data); + if (!vr.isConstant()) { + if (!vr.isTypeKnown()) + unpinReg(vr.typeReg()); + unpinReg(vr.dataReg()); } } @@ -1341,17 +1374,17 @@ FrameState::ensureValueSynced(Assembler &masm, FrameEntry *fe, const ValueRemat if (!vr.isDataSynced || !vr.isTypeSynced) masm.storeValue(vr, addressOf(fe)); #elif defined JS_NUNBOX32 - if (vr.isConstant) { + if (vr.isConstant()) { if (!vr.isDataSynced || !vr.isTypeSynced) - masm.storeValue(Valueify(vr.u.v), addressOf(fe)); + masm.storeValue(vr.value(), addressOf(fe)); } else { if (!vr.isDataSynced) - masm.storePayload(vr.u.s.data, addressOf(fe)); + masm.storePayload(vr.dataReg(), addressOf(fe)); if (!vr.isTypeSynced) { - if (vr.u.s.isTypeKnown) - masm.storeTypeTag(ImmType(vr.u.s.type.knownType), addressOf(fe)); + if (vr.isTypeKnown()) + masm.storeTypeTag(ImmType(vr.knownType()), addressOf(fe)); else - masm.storeTypeTag(vr.u.s.type.reg, addressOf(fe)); + masm.storeTypeTag(vr.typeReg(), addressOf(fe)); } } #endif @@ -1593,3 +1626,32 @@ FrameState::allocForBinary(FrameEntry *lhs, FrameEntry *rhs, JSOp op, BinaryAllo unpinReg(backingRight->data.reg()); } +MaybeRegisterID +FrameState::maybePinData(FrameEntry *fe) +{ + fe = fe->isCopy() ? fe->copyOf() : fe; + if (fe->data.inRegister()) { + pinReg(fe->data.reg()); + return fe->data.reg(); + } + return MaybeRegisterID(); +} + +MaybeRegisterID +FrameState::maybePinType(FrameEntry *fe) +{ + fe = fe->isCopy() ? fe->copyOf() : fe; + if (fe->type.inRegister()) { + pinReg(fe->type.reg()); + return fe->type.reg(); + } + return MaybeRegisterID(); +} + +void +FrameState::maybeUnpinReg(MaybeRegisterID reg) +{ + if (reg.isSet()) + unpinReg(reg.reg()); +} + diff --git a/js/src/methodjit/FrameState.h b/js/src/methodjit/FrameState.h index b6859f4d3d90..546c51c3987f 100644 --- a/js/src/methodjit/FrameState.h +++ b/js/src/methodjit/FrameState.h @@ -50,15 +50,6 @@ namespace js { namespace mjit { -struct StateRemat { - typedef JSC::MacroAssembler::RegisterID RegisterID; - union { - RegisterID reg : 31; - uint32 offset : 31; - }; - bool inReg : 1; -}; - struct Uses { explicit Uses(uint32 nuses) : nuses(nuses) @@ -73,38 +64,6 @@ struct Changes { uint32 nchanges; }; -class MaybeRegisterID { - typedef JSC::MacroAssembler::RegisterID RegisterID; - - public: - MaybeRegisterID() - : reg_(Registers::ReturnReg), set(false) - { } - - MaybeRegisterID(RegisterID reg) - : reg_(reg), set(true) - { } - - inline RegisterID reg() const { JS_ASSERT(set); return reg_; } - inline void setReg(const RegisterID r) { reg_ = r; set = true; } - inline bool isSet() const { return set; } - - MaybeRegisterID & operator =(const MaybeRegisterID &other) { - set = other.set; - reg_ = other.reg_; - return *this; - } - - MaybeRegisterID & operator =(RegisterID r) { - setReg(r); - return *this; - } - - private: - RegisterID reg_; - bool set; -}; - /* * The FrameState keeps track of values on the frame during compilation. * The compiler can query FrameState for information about arguments, locals, @@ -585,7 +544,7 @@ class FrameState * Fully stores a FrameEntry into two arbitrary registers. tempReg may be * used as a temporary. */ - void loadTo(FrameEntry *fe, RegisterID typeReg, RegisterID dataReg, RegisterID tempReg); + void loadForReturn(FrameEntry *fe, RegisterID typeReg, RegisterID dataReg, RegisterID tempReg); /* * Stores the top stack slot back to a slot. @@ -720,6 +679,11 @@ class FrameState */ inline void unpinKilledReg(RegisterID reg); + /* Pins a data or type register if one exists. */ + MaybeRegisterID maybePinData(FrameEntry *fe); + MaybeRegisterID maybePinType(FrameEntry *fe); + void maybeUnpinReg(MaybeRegisterID reg); + /* * Dups the top item on the stack. */ diff --git a/js/src/methodjit/InvokeHelpers.cpp b/js/src/methodjit/InvokeHelpers.cpp index e7a92f2557e6..7adac76021a2 100644 --- a/js/src/methodjit/InvokeHelpers.cpp +++ b/js/src/methodjit/InvokeHelpers.cpp @@ -56,6 +56,7 @@ #include "jstracer.h" #include "jspropertycache.h" #include "methodjit/MonoIC.h" +#include "jsanalyze.h" #include "jsinterpinlines.h" #include "jspropertycacheinlines.h" @@ -941,7 +942,16 @@ RunTracer(VMFrame &f) bool blacklist; uintN inlineCallCount = 0; - tpa = MonitorTracePoint(f.cx, inlineCallCount, blacklist); + void **traceData; + uintN *traceEpoch; +#if JS_MONOIC + traceData = &tic.traceData; + traceEpoch = &tic.traceEpoch; +#else + traceData = NULL; + traceEpoch = NULL; +#endif + tpa = MonitorTracePoint(f.cx, inlineCallCount, &blacklist, traceData, traceEpoch); JS_ASSERT(!TRACE_RECORDER(cx)); #if JS_MONOIC diff --git a/js/src/methodjit/MachineRegs.h b/js/src/methodjit/MachineRegs.h index 2fe1b6dfa5d8..9d0b2fcde45d 100644 --- a/js/src/methodjit/MachineRegs.h +++ b/js/src/methodjit/MachineRegs.h @@ -51,13 +51,20 @@ struct Registers { typedef JSC::MacroAssembler::RegisterID RegisterID; -// TODO: Eliminate scratch register (requires rewriting register allocation mechanism) + // Homed and scratch registers for working with Values on x64. #if defined(JS_CPU_X64) static const RegisterID TypeMaskReg = JSC::X86Registers::r13; static const RegisterID PayloadMaskReg = JSC::X86Registers::r14; static const RegisterID ValueReg = JSC::X86Registers::r15; #endif + // Register that homes the current JSStackFrame. +#if defined(JS_CPU_X86) || defined(JS_CPU_X64) + static const RegisterID JSFrameReg = JSC::X86Registers::ebx; +#elif defined(JS_CPU_ARM) + static const RegisterID JSFrameReg = JSC::ARMRegisters::r11; +#endif + #if defined(JS_CPU_X86) || defined(JS_CPU_X64) static const RegisterID ReturnReg = JSC::X86Registers::eax; # if defined(JS_CPU_X86) || defined(_MSC_VER) @@ -356,6 +363,8 @@ struct FPRegisters { uint32 freeFPMask; }; +static const JSC::MacroAssembler::RegisterID JSFrameReg = Registers::JSFrameReg; + } /* namespace mjit */ } /* namespace js */ diff --git a/js/src/methodjit/MethodJIT.cpp b/js/src/methodjit/MethodJIT.cpp index 412161d26b28..64e6ffe984ab 100644 --- a/js/src/methodjit/MethodJIT.cpp +++ b/js/src/methodjit/MethodJIT.cpp @@ -861,3 +861,56 @@ mjit::ProfileStubCall(VMFrame &f) } #endif +#ifdef JS_POLYIC +static int +PICPCComparator(const void *key, const void *entry) +{ + const jsbytecode *pc = (const jsbytecode *)key; + const ic::PICInfo *pic = (const ic::PICInfo *)entry; + + if (ic::PICInfo::CALL != pic->kind) + return ic::PICInfo::CALL - pic->kind; + + /* + * We can't just return |pc - pic->pc| because the pointers may be + * far apart and an int (or even a ptrdiff_t) may not be large + * enough to hold the difference. C says that pointer subtraction + * is only guaranteed to work for two pointers into the same array. + */ + if (pc < pic->pc) + return -1; + else if (pc == pic->pc) + return 0; + else + return 1; +} + +uintN +mjit::GetCallTargetCount(JSScript *script, jsbytecode *pc) +{ + ic::PICInfo *pic; + + if (mjit::JITScript *jit = script->getJIT(false)) { + pic = (ic::PICInfo *)bsearch(pc, jit->pics, jit->nPICs, sizeof(jit->pics[0]), + PICPCComparator); + if (pic) + return pic->stubsGenerated + 1; /* Add 1 for the inline path. */ + } + + if (mjit::JITScript *jit = script->getJIT(true)) { + pic = (ic::PICInfo *)bsearch(pc, jit->pics, + jit->nPICs, sizeof(jit->pics[0]), + PICPCComparator); + if (pic) + return pic->stubsGenerated + 1; /* Add 1 for the inline path. */ + } + + return 1; +} +#else +uintN +mjit::GetCallTargetCount(JSScript *script, jsbytecode *pc) +{ + return 1; +} +#endif diff --git a/js/src/methodjit/MethodJIT.h b/js/src/methodjit/MethodJIT.h index f80c6e976c10..e5332942a09d 100644 --- a/js/src/methodjit/MethodJIT.h +++ b/js/src/methodjit/MethodJIT.h @@ -281,6 +281,9 @@ struct CallSite void EnableTraceHint(JSScript *script, jsbytecode *pc, uint16_t index); +uintN +GetCallTargetCount(JSScript *script, jsbytecode *pc); + } /* namespace mjit */ } /* namespace js */ diff --git a/js/src/methodjit/MonoIC.cpp b/js/src/methodjit/MonoIC.cpp index 8c9b09c696a4..8b3fa7bf6083 100644 --- a/js/src/methodjit/MonoIC.cpp +++ b/js/src/methodjit/MonoIC.cpp @@ -86,20 +86,17 @@ ic::GetGlobalName(VMFrame &f, ic::MICInfo *ic) JS_ASSERT(ic->kind == ic::MICInfo::GET); - JS_LOCK_OBJ(f.cx, obj); const Shape *shape = obj->nativeLookup(id); if (!shape || !shape->hasDefaultGetterOrIsMethod() || !shape->hasSlot()) { - JS_UNLOCK_OBJ(f.cx, obj); if (shape) PatchGetFallback(f, ic); stubs::GetGlobalName(f); return; } uint32 slot = shape->slot; - JS_UNLOCK_OBJ(f.cx, obj); ic->u.name.touched = true; @@ -164,21 +161,18 @@ ic::SetGlobalName(VMFrame &f, ic::MICInfo *ic) JS_ASSERT(ic->kind == ic::MICInfo::SET); - JS_LOCK_OBJ(f.cx, obj); const Shape *shape = obj->nativeLookup(id); if (!shape || !shape->hasDefaultGetterOrIsMethod() || !shape->writable() || !shape->hasSlot()) { - JS_UNLOCK_OBJ(f.cx, obj); if (shape) PatchSetFallback(f, ic); GetStubForSetGlobalName(f)(f, atom); return; } uint32 slot = shape->slot; - JS_UNLOCK_OBJ(f.cx, obj); ic->u.name.touched = true; @@ -270,15 +264,15 @@ class EqualityCompiler : public BaseCompiler void generateStringPath(Assembler &masm) { - ValueRemat &lvr = ic.lvr; - ValueRemat &rvr = ic.rvr; + const ValueRemat &lvr = ic.lvr; + const ValueRemat &rvr = ic.rvr; - if (!lvr.isConstant && !lvr.isType(JSVAL_TYPE_STRING)) { + if (!lvr.isConstant() && !lvr.isType(JSVAL_TYPE_STRING)) { Jump lhsFail = masm.testString(Assembler::NotEqual, lvr.typeReg()); linkToStub(lhsFail); } - if (!rvr.isConstant && !rvr.isType(JSVAL_TYPE_STRING)) { + if (!rvr.isConstant() && !rvr.isType(JSVAL_TYPE_STRING)) { Jump rhsFail = masm.testString(Assembler::NotEqual, rvr.typeReg()); linkToStub(rhsFail); } @@ -293,15 +287,15 @@ class EqualityCompiler : public BaseCompiler Jump lhsNotAtomized = masm.branch32(Assembler::NotEqual, tmp, atomizedFlags); linkToStub(lhsNotAtomized); - if (!rvr.isConstant) { + if (!rvr.isConstant()) { masm.load32(Address(rvr.dataReg(), offsetof(JSString, mLengthAndFlags)), tmp); masm.and32(Imm32(JSString::TYPE_FLAGS_MASK), tmp); Jump rhsNotAtomized = masm.branch32(Assembler::NotEqual, tmp, atomizedFlags); linkToStub(rhsNotAtomized); } - if (rvr.isConstant) { - JSString *str = Valueify(rvr.u.v).toString(); + if (rvr.isConstant()) { + JSString *str = rvr.value().toString(); JS_ASSERT(str->isAtomized()); Jump test = masm.branchPtr(ic.cond, lvr.dataReg(), ImmPtr(str)); linkTrue(test); @@ -319,12 +313,12 @@ class EqualityCompiler : public BaseCompiler ValueRemat &lvr = ic.lvr; ValueRemat &rvr = ic.rvr; - if (!lvr.isConstant && !lvr.isType(JSVAL_TYPE_OBJECT)) { + if (!lvr.isConstant() && !lvr.isType(JSVAL_TYPE_OBJECT)) { Jump lhsFail = masm.testObject(Assembler::NotEqual, lvr.typeReg()); linkToStub(lhsFail); } - if (!rvr.isConstant && !rvr.isType(JSVAL_TYPE_OBJECT)) { + if (!rvr.isConstant() && !rvr.isType(JSVAL_TYPE_OBJECT)) { Jump rhsFail = masm.testObject(Assembler::NotEqual, rvr.typeReg()); linkToStub(rhsFail); } @@ -335,8 +329,8 @@ class EqualityCompiler : public BaseCompiler Imm32(JSObject::HAS_EQUALITY)); linkToStub(lhsHasEq); - if (rvr.isConstant) { - JSObject *obj = &Valueify(rvr.u.v).toObject(); + if (rvr.isConstant()) { + JSObject *obj = &rvr.value().toObject(); Jump test = masm.branchPtr(ic.cond, lvr.dataReg(), ImmPtr(obj)); linkTrue(test); } else { @@ -585,9 +579,7 @@ class CallCompiler : public BaseCompiler RegisterID t0 = tempRegs.takeAnyReg(); /* Guard that it's actually a function object. */ - Jump claspGuard = masm.branchPtr(Assembler::NotEqual, - Address(ic.funObjReg, offsetof(JSObject, clasp)), - ImmPtr(&js_FunctionClass)); + Jump claspGuard = masm.testObjClass(Assembler::NotEqual, ic.funObjReg, &js_FunctionClass); /* Guard that it's the same function. */ JSFunction *fun = obj->getFunctionPrivate(); diff --git a/js/src/methodjit/MonoIC.h b/js/src/methodjit/MonoIC.h index f2e287a19711..2f930799f524 100644 --- a/js/src/methodjit/MonoIC.h +++ b/js/src/methodjit/MonoIC.h @@ -108,6 +108,10 @@ struct TraceICInfo { #ifdef DEBUG jsbytecode *jumpTargetPC; #endif + + /* This data is used by the tracing JIT. */ + void *traceData; + uintN traceEpoch; bool hasSlowTraceHint : 1; }; diff --git a/js/src/methodjit/NunboxAssembler.h b/js/src/methodjit/NunboxAssembler.h index e4fceea43c94..6715b388688d 100644 --- a/js/src/methodjit/NunboxAssembler.h +++ b/js/src/methodjit/NunboxAssembler.h @@ -41,7 +41,7 @@ #if !defined jsjaeger_assembler_h__ && defined JS_METHODJIT && defined JS_NUNBOX32 #define jsjaeger_assembler_h__ -#include "methodjit/BaseAssembler.h" +#include "assembler/assembler/MacroAssembler.h" #include "methodjit/RematInfo.h" namespace js { @@ -69,7 +69,7 @@ struct ImmPayload : JSC::MacroAssembler::Imm32 { } }; -class Assembler : public BaseAssembler +class NunboxAssembler : public JSC::MacroAssembler { static const uint32 PAYLOAD_OFFSET = 0; static const uint32 TAG_OFFSET = 4; @@ -139,6 +139,14 @@ class Assembler : public BaseAssembler store32(imm, payloadOf(address)); } + bool addressUsesRegister(BaseIndex address, RegisterID reg) { + return (address.base == reg) || (address.index == reg); + } + + bool addressUsesRegister(Address address, RegisterID reg) { + return address.base == reg; + } + /* Loads type first, then payload, returning label after type load. */ template Label loadValueAsComponents(T address, RegisterID type, RegisterID payload) { @@ -185,15 +193,15 @@ class Assembler : public BaseAssembler template Label storeValue(const ValueRemat &vr, T address) { - if (vr.isConstant) { - return storeValue(Valueify(vr.u.v), address); + if (vr.isConstant()) { + return storeValue(vr.value(), address); } else { - if (vr.u.s.isTypeKnown) - storeTypeTag(ImmType(vr.u.s.type.knownType), address); + if (vr.isTypeKnown()) + storeTypeTag(ImmType(vr.knownType()), address); else - storeTypeTag(vr.u.s.type.reg, address); + storeTypeTag(vr.typeReg(), address); Label l = label(); - storePayload(vr.u.s.data, address); + storePayload(vr.dataReg(), address); return l; } } @@ -207,93 +215,103 @@ class Assembler : public BaseAssembler loadPtr(priv, to); } - Jump testNull(Assembler::Condition cond, RegisterID reg) { + Jump testNull(Condition cond, RegisterID reg) { return branch32(cond, reg, ImmTag(JSVAL_TAG_NULL)); } - Jump testNull(Assembler::Condition cond, Address address) { + Jump testNull(Condition cond, Address address) { return branch32(cond, tagOf(address), ImmTag(JSVAL_TAG_NULL)); } - Jump testUndefined(Assembler::Condition cond, RegisterID reg) { + Jump testUndefined(Condition cond, RegisterID reg) { return branch32(cond, reg, ImmTag(JSVAL_TAG_UNDEFINED)); } - Jump testUndefined(Assembler::Condition cond, Address address) { + Jump testUndefined(Condition cond, Address address) { return branch32(cond, tagOf(address), ImmTag(JSVAL_TAG_UNDEFINED)); } - Jump testInt32(Assembler::Condition cond, RegisterID reg) { + Jump testInt32(Condition cond, RegisterID reg) { return branch32(cond, reg, ImmTag(JSVAL_TAG_INT32)); } - Jump testInt32(Assembler::Condition cond, Address address) { + Jump testInt32(Condition cond, Address address) { return branch32(cond, tagOf(address), ImmTag(JSVAL_TAG_INT32)); } - Jump testNumber(Assembler::Condition cond, RegisterID reg) { - cond = (cond == Assembler::Equal) ? Assembler::BelowOrEqual : Assembler::Above; + Jump testNumber(Condition cond, RegisterID reg) { + cond = (cond == Equal) ? BelowOrEqual : Above; return branch32(cond, reg, ImmTag(JSVAL_TAG_INT32)); } - Jump testNumber(Assembler::Condition cond, Address address) { - cond = (cond == Assembler::Equal) ? Assembler::BelowOrEqual : Assembler::Above; + Jump testNumber(Condition cond, Address address) { + cond = (cond == Equal) ? BelowOrEqual : Above; return branch32(cond, tagOf(address), ImmTag(JSVAL_TAG_INT32)); } - Jump testPrimitive(Assembler::Condition cond, RegisterID reg) { - cond = (cond == Assembler::NotEqual) ? Assembler::AboveOrEqual : Assembler::Below; + Jump testPrimitive(Condition cond, RegisterID reg) { + cond = (cond == NotEqual) ? AboveOrEqual : Below; return branch32(cond, reg, ImmTag(JSVAL_TAG_OBJECT)); } - Jump testPrimitive(Assembler::Condition cond, Address address) { - cond = (cond == Assembler::NotEqual) ? Assembler::AboveOrEqual : Assembler::Below; + Jump testPrimitive(Condition cond, Address address) { + cond = (cond == NotEqual) ? AboveOrEqual : Below; return branch32(cond, tagOf(address), ImmTag(JSVAL_TAG_OBJECT)); } - Jump testObject(Assembler::Condition cond, RegisterID reg) { + Jump testObject(Condition cond, RegisterID reg) { return branch32(cond, reg, ImmTag(JSVAL_TAG_OBJECT)); } - Jump testObject(Assembler::Condition cond, Address address) { + Jump testObject(Condition cond, Address address) { return branch32(cond, tagOf(address), ImmTag(JSVAL_TAG_OBJECT)); } - Jump testDouble(Assembler::Condition cond, RegisterID reg) { - Assembler::Condition opcond; - if (cond == Assembler::Equal) - opcond = Assembler::Below; + Jump testDouble(Condition cond, RegisterID reg) { + Condition opcond; + if (cond == Equal) + opcond = Below; else - opcond = Assembler::AboveOrEqual; + opcond = AboveOrEqual; return branch32(opcond, reg, ImmTag(JSVAL_TAG_CLEAR)); } - Jump testDouble(Assembler::Condition cond, Address address) { - Assembler::Condition opcond; - if (cond == Assembler::Equal) - opcond = Assembler::Below; + Jump testDouble(Condition cond, Address address) { + Condition opcond; + if (cond == Equal) + opcond = Below; else - opcond = Assembler::AboveOrEqual; + opcond = AboveOrEqual; return branch32(opcond, tagOf(address), ImmTag(JSVAL_TAG_CLEAR)); } - Jump testBoolean(Assembler::Condition cond, RegisterID reg) { + Jump testBoolean(Condition cond, RegisterID reg) { return branch32(cond, reg, ImmTag(JSVAL_TAG_BOOLEAN)); } - Jump testBoolean(Assembler::Condition cond, Address address) { + Jump testBoolean(Condition cond, Address address) { return branch32(cond, tagOf(address), ImmTag(JSVAL_TAG_BOOLEAN)); } - Jump testString(Assembler::Condition cond, RegisterID reg) { + Jump testString(Condition cond, RegisterID reg) { return branch32(cond, reg, ImmTag(JSVAL_TAG_STRING)); } - Jump testString(Assembler::Condition cond, Address address) { + Jump testString(Condition cond, Address address) { return branch32(cond, tagOf(address), ImmTag(JSVAL_TAG_STRING)); } + + template + Jump fastArrayLoadSlot(T address, RegisterID typeReg, RegisterID dataReg) { + loadTypeTag(address, typeReg); + Jump notHole = branch32(Equal, typeReg, ImmType(JSVAL_TYPE_MAGIC)); + loadPayload(address, dataReg); + return notHole; + } }; +typedef NunboxAssembler ValueAssembler; + } /* namespace mjit */ } /* namespace js */ diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index d2c8ed7b1e78..d0084df29270 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -121,9 +121,7 @@ class PICStubCompiler : public BaseCompiler JITCode jitCode(pic.slowPathStart.executableAddress(), INLINE_PATH_LENGTH); CodeBlock codeBlock(jitCode); RepatchBuffer repatcher(&codeBlock); - ReturnAddressPtr retPtr(pic.slowPathStart.callAtOffset(pic.callReturn).executableAddress()); - MacroAssemblerCodePtr target(stub); - repatcher.relinkCallerToTrampoline(retPtr, target); + repatcher.relink(pic.slowPathCall, FunctionPtr(stub)); return true; } @@ -163,9 +161,9 @@ class SetPropCompiler : public PICStubCompiler static int32 dslotsLoadOffset(ic::PICInfo &pic) { #if defined JS_NUNBOX32 - if (pic.u.vr.isConstant) + if (pic.u.vr.isConstant()) return SETPROP_DSLOTS_BEFORE_CONSTANT; - if (pic.u.vr.u.s.isTypeKnown) + if (pic.u.vr.isTypeKnown()) return SETPROP_DSLOTS_BEFORE_KTYPE; return SETPROP_DSLOTS_BEFORE_DYNAMIC; #elif defined JS_PUNBOX64 @@ -175,9 +173,9 @@ class SetPropCompiler : public PICStubCompiler #if defined JS_NUNBOX32 inline int32 inlineTypeOffset() { - if (pic.u.vr.isConstant) + if (pic.u.vr.isConstant()) return SETPROP_INLINE_STORE_CONST_TYPE; - if (pic.u.vr.u.s.isTypeKnown) + if (pic.u.vr.isTypeKnown()) return SETPROP_INLINE_STORE_KTYPE_TYPE; return SETPROP_INLINE_STORE_DYN_TYPE; } @@ -185,9 +183,9 @@ class SetPropCompiler : public PICStubCompiler #if defined JS_NUNBOX32 inline int32 inlineDataOffset() { - if (pic.u.vr.isConstant) + if (pic.u.vr.isConstant()) return SETPROP_INLINE_STORE_CONST_DATA; - if (pic.u.vr.u.s.isTypeKnown) + if (pic.u.vr.isTypeKnown()) return SETPROP_INLINE_STORE_KTYPE_DATA; return SETPROP_INLINE_STORE_DYN_DATA; } @@ -236,7 +234,7 @@ class SetPropCompiler : public PICStubCompiler static void reset(ic::PICInfo &pic) { RepatchBuffer repatcher(pic.fastPathStart.executableAddress(), INLINE_PATH_LENGTH); - repatcher.repatchLEAToLoadPtr(pic.storeBack.instructionAtOffset(dslotsLoadOffset(pic))); + repatcher.repatchLEAToLoadPtr(pic.fastPathRejoin.instructionAtOffset(dslotsLoadOffset(pic))); repatcher.repatch(pic.fastPathStart.dataLabel32AtOffset( pic.shapeGuard + inlineShapeOffset(pic)), int32(JSObjectMap::INVALID_SHAPE)); @@ -245,9 +243,8 @@ class SetPropCompiler : public PICStubCompiler pic.slowPathStart); RepatchBuffer repatcher2(pic.slowPathStart.executableAddress(), INLINE_PATH_LENGTH); - ReturnAddressPtr retPtr(pic.slowPathStart.callAtOffset(pic.callReturn).executableAddress()); - MacroAssemblerCodePtr target(JS_FUNC_TO_DATA_PTR(void *, ic::SetProp)); - repatcher.relinkCallerToTrampoline(retPtr, target); + FunctionPtr target(JS_FUNC_TO_DATA_PTR(void *, ic::SetProp)); + repatcher.relink(pic.slowPathCall, target); } bool patchInline(const Shape *shape, bool inlineSlot) @@ -260,7 +257,7 @@ class SetPropCompiler : public PICStubCompiler int32 offset; if (inlineSlot) { JSC::CodeLocationInstruction istr; - istr = pic.storeBack.instructionAtOffset(dslotsLoadOffset()); + istr = pic.fastPathRejoin.instructionAtOffset(dslotsLoadOffset()); repatcher.repatchLoadPtrToLEA(istr); // @@ -281,10 +278,10 @@ class SetPropCompiler : public PICStubCompiler uint32 shapeOffs = pic.shapeGuard + inlineShapeOffset(); repatcher.repatch(pic.fastPathStart.dataLabel32AtOffset(shapeOffs), obj->shape()); #if defined JS_NUNBOX32 - repatcher.repatch(pic.storeBack.dataLabel32AtOffset(inlineTypeOffset()), offset + 4); - repatcher.repatch(pic.storeBack.dataLabel32AtOffset(inlineDataOffset()), offset); + repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(inlineTypeOffset()), offset + 4); + repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(inlineDataOffset()), offset); #elif defined JS_PUNBOX64 - repatcher.repatch(pic.storeBack.dataLabel32AtOffset(SETPROP_INLINE_STORE_VALUE), offset); + repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(SETPROP_INLINE_STORE_VALUE), offset); #endif pic.inlinePathPatched = true; @@ -344,16 +341,6 @@ class SetPropCompiler : public PICStubCompiler JS_ASSERT(shape->hasSlot()); pic.shapeRegHasBaseShape = false; -#ifdef JS_THREADSAFE - /* Check that the object isn't shared, so no locking needed. */ - masm.loadPtr(FrameAddress(offsetof(VMFrame, cx)), pic.shapeReg); - Jump sharedObject = masm.branchPtr(Assembler::NotEqual, - Address(pic.objReg, offsetof(JSObject, title.ownercx)), - pic.shapeReg); - if (!slowExits.append(sharedObject)) - return false; -#endif - /* Emit shape guards for the object's prototype chain. */ JSObject *proto = obj->getProto(); RegisterID lastReg = pic.objReg; @@ -374,11 +361,11 @@ class SetPropCompiler : public PICStubCompiler */ JS_ASSERT(shape->isMethod()); JSObject *funobj = &shape->methodObject(); - if (pic.u.vr.isConstant) { - JS_ASSERT(funobj == &Valueify(pic.u.vr.u.v).toObject()); + if (pic.u.vr.isConstant()) { + JS_ASSERT(funobj == &pic.u.vr.value().toObject()); } else { Jump mismatchedFunction = - masm.branchPtr(Assembler::NotEqual, pic.u.vr.u.s.data, ImmPtr(funobj)); + masm.branchPtr(Assembler::NotEqual, pic.u.vr.dataReg(), ImmPtr(funobj)); if (!slowExits.append(mismatchedFunction)) return false; } @@ -496,9 +483,9 @@ class SetPropCompiler : public PICStubCompiler buffer.link(slowExit.get(), pic.slowPathStart); for (Jump *pj = slowExits.begin(); pj != slowExits.end(); ++pj) buffer.link(*pj, pic.slowPathStart); - buffer.link(done, pic.storeBack); + buffer.link(done, pic.fastPathRejoin); if (skipOver.isSet()) - buffer.link(skipOver.get(), pic.storeBack); + buffer.link(skipOver.get(), pic.fastPathRejoin); CodeLocationLabel cs = buffer.finalizeCodeAddendum(); JaegerSpew(JSpew_PICs, "generate setprop stub %p %d %d at %p\n", (void*)&pic, @@ -549,11 +536,6 @@ class SetPropCompiler : public PICStubCompiler if (clasp->ops.setProperty) return disable("ops set property hook"); -#ifdef JS_THREADSAFE - if (!CX_OWNS_OBJECT_TITLE(cx, obj)) - return disable("shared object"); -#endif - jsid id = ATOM_TO_JSID(atom); JSObject *holder; @@ -563,7 +545,6 @@ class SetPropCompiler : public PICStubCompiler /* If the property exists but is on a prototype, treat as addprop. */ if (prop && holder != obj) { - AutoPropertyDropper dropper(cx, holder, prop); const Shape *shape = (const Shape *) prop; if (!holder->isNative()) @@ -656,8 +637,6 @@ class SetPropCompiler : public PICStubCompiler return generateStub(initialShape, shape, true, !obj->hasSlotsArray()); } - AutoPropertyDropper dropper(cx, holder, prop); - const Shape *shape = (const Shape *) prop; if (pic.kind == ic::PICInfo::SETMETHOD && !shape->isMethod()) return disable("set method on non-method shape"); @@ -744,7 +723,7 @@ class GetPropCompiler : public PICStubCompiler static void reset(ic::PICInfo &pic) { RepatchBuffer repatcher(pic.fastPathStart.executableAddress(), INLINE_PATH_LENGTH); - repatcher.repatchLEAToLoadPtr(pic.storeBack.instructionAtOffset(dslotsLoad(pic))); + repatcher.repatchLEAToLoadPtr(pic.fastPathRejoin.instructionAtOffset(dslotsLoad(pic))); repatcher.repatch(pic.fastPathStart.dataLabel32AtOffset( pic.shapeGuard + inlineShapeOffset(pic)), int32(JSObjectMap::INVALID_SHAPE)); @@ -757,7 +736,6 @@ class GetPropCompiler : public PICStubCompiler } RepatchBuffer repatcher2(pic.slowPathStart.executableAddress(), INLINE_PATH_LENGTH); - ReturnAddressPtr retPtr(pic.slowPathStart.callAtOffset(pic.callReturn).executableAddress()); VoidStubPIC stub; switch (pic.kind) { @@ -772,16 +750,15 @@ class GetPropCompiler : public PICStubCompiler return; } - MacroAssemblerCodePtr target(JS_FUNC_TO_DATA_PTR(void *, stub)); - repatcher.relinkCallerToTrampoline(retPtr, target); + FunctionPtr target(JS_FUNC_TO_DATA_PTR(void *, stub)); + repatcher.relink(pic.slowPathCall, target); } bool generateArgsLengthStub() { Assembler masm; - Address clasp(pic.objReg, offsetof(JSObject, clasp)); - Jump notArgs = masm.branchPtr(Assembler::NotEqual, clasp, ImmPtr(obj->getClass())); + Jump notArgs = masm.testObjClass(Assembler::NotEqual, pic.objReg, obj->getClass()); masm.loadPtr(Address(pic.objReg, offsetof(JSObject, slots)), pic.objReg); masm.load32(Address(pic.objReg, JSObject::JSSLOT_ARGS_LENGTH * sizeof(Value)), @@ -799,7 +776,7 @@ class GetPropCompiler : public PICStubCompiler buffer.link(notArgs, pic.slowPathStart); buffer.link(overridden, pic.slowPathStart); - buffer.link(done, pic.storeBack); + buffer.link(done, pic.fastPathRejoin); CodeLocationLabel start = buffer.finalizeCodeAddendum(); JaegerSpew(JSpew_PICs, "generate args length stub at %p\n", @@ -817,10 +794,9 @@ class GetPropCompiler : public PICStubCompiler { Assembler masm; - masm.loadPtr(Address(pic.objReg, offsetof(JSObject, clasp)), pic.shapeReg); - Jump isDense = masm.branchPtr(Assembler::Equal, pic.shapeReg, ImmPtr(&js_ArrayClass)); - Jump notArray = masm.branchPtr(Assembler::NotEqual, pic.shapeReg, - ImmPtr(&js_SlowArrayClass)); + masm.loadObjClass(pic.objReg, pic.shapeReg); + Jump isDense = masm.testClass(Assembler::Equal, pic.shapeReg, &js_ArrayClass); + Jump notArray = masm.testClass(Assembler::NotEqual, pic.shapeReg, &js_SlowArrayClass); isDense.linkTo(masm.label(), &masm); masm.load32(Address(pic.objReg, offsetof(JSObject, privateData)), pic.objReg); @@ -834,7 +810,7 @@ class GetPropCompiler : public PICStubCompiler buffer.link(notArray, pic.slowPathStart); buffer.link(oob, pic.slowPathStart); - buffer.link(done, pic.storeBack); + buffer.link(done, pic.fastPathRejoin); CodeLocationLabel start = buffer.finalizeCodeAddendum(); JaegerSpew(JSpew_PICs, "generate array length stub at %p\n", @@ -863,7 +839,6 @@ class GetPropCompiler : public PICStubCompiler if (!prop) return disable("property not found"); - AutoPropertyDropper dropper(cx, holder, prop); const Shape *shape = (const Shape *)prop; if (holder != obj) return disable("proto walk on String.prototype"); @@ -921,7 +896,7 @@ class GetPropCompiler : public PICStubCompiler buffer.link(notString, pic.slowPathStart.labelAtOffset(pic.u.get.typeCheckOffset)); buffer.link(shapeMismatch, pic.slowPathStart); - buffer.link(done, pic.storeBack); + buffer.link(done, pic.fastPathRejoin); CodeLocationLabel cs = buffer.finalizeCodeAddendum(); JaegerSpew(JSpew_PICs, "generate string call stub at %p\n", @@ -957,7 +932,7 @@ class GetPropCompiler : public PICStubCompiler return false; buffer.link(notString, pic.slowPathStart.labelAtOffset(pic.u.get.typeCheckOffset)); - buffer.link(done, pic.storeBack); + buffer.link(done, pic.fastPathRejoin); CodeLocationLabel start = buffer.finalizeCodeAddendum(); JaegerSpew(JSpew_PICs, "generate string length stub at %p\n", @@ -981,7 +956,7 @@ class GetPropCompiler : public PICStubCompiler int32 offset; if (!holder->hasSlotsArray()) { JSC::CodeLocationInstruction istr; - istr = pic.storeBack.instructionAtOffset(dslotsLoad()); + istr = pic.fastPathRejoin.instructionAtOffset(dslotsLoad()); repatcher.repatchLoadPtrToLEA(istr); // @@ -1002,10 +977,10 @@ class GetPropCompiler : public PICStubCompiler uint32 shapeOffs = pic.shapeGuard + inlineShapeOffset(); repatcher.repatch(pic.fastPathStart.dataLabel32AtOffset(shapeOffs), obj->shape()); #if defined JS_NUNBOX32 - repatcher.repatch(pic.storeBack.dataLabel32AtOffset(GETPROP_TYPE_LOAD), offset + 4); - repatcher.repatch(pic.storeBack.dataLabel32AtOffset(GETPROP_DATA_LOAD), offset); + repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(GETPROP_TYPE_LOAD), offset + 4); + repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(GETPROP_DATA_LOAD), offset); #elif defined JS_PUNBOX64 - repatcher.repatch(pic.storeBack.dataLabel32AtOffset(pic.labels.getprop.inlineValueOffset), offset); + repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(pic.labels.getprop.inlineValueOffset), offset); #endif pic.inlinePathPatched = true; @@ -1020,10 +995,7 @@ class GetPropCompiler : public PICStubCompiler Assembler masm; if (pic.objNeedsRemat()) { - if (pic.objRemat() >= sizeof(JSStackFrame)) - masm.loadPayload(Address(JSFrameReg, pic.objRemat()), pic.objReg); - else - masm.move(RegisterID(pic.objRemat()), pic.objReg); + masm.rematPayload(pic.objRemat(), pic.objReg); pic.u.get.objNeedsRemat = false; } @@ -1032,9 +1004,8 @@ class GetPropCompiler : public PICStubCompiler Jump argsLenGuard; if (obj->isDenseArray()) { start = masm.label(); - shapeGuard = masm.branchPtr(Assembler::NotEqual, - Address(pic.objReg, offsetof(JSObject, clasp)), - ImmPtr(obj->getClass())); + shapeGuard = masm.testObjClass(Assembler::NotEqual, pic.objReg, obj->getClass()); + /* * No need to assert validity of GETPROP_STUB_SHAPE_JUMP in this case: * the IC is disabled after a dense array hit, so no patching can occur. @@ -1120,7 +1091,7 @@ class GetPropCompiler : public PICStubCompiler buffer.link(*pj, pic.slowPathStart); // The final exit jumps to the store-back in the inline stub. - buffer.link(done, pic.storeBack); + buffer.link(done, pic.fastPathRejoin); CodeLocationLabel cs = buffer.finalizeCodeAddendum(); JaegerSpew(JSpew_PICs, "generated %s stub at %p\n", type, cs.executableAddress()); @@ -1182,8 +1153,6 @@ class GetPropCompiler : public PICStubCompiler if (!prop) return disable("lookup failed"); - AutoPropertyDropper dropper(cx, holder, prop); - if (!holder->isNative()) return disable("non-native holder"); @@ -1287,7 +1256,7 @@ class GetElemCompiler : public PICStubCompiler JS_ASSERT(pic.kind == ic::PICInfo::GETELEM); RepatchBuffer repatcher(pic.fastPathStart.executableAddress(), INLINE_PATH_LENGTH); - repatcher.repatchLEAToLoadPtr(pic.storeBack.instructionAtOffset(dslotsLoad(pic))); + repatcher.repatchLEAToLoadPtr(pic.fastPathRejoin.instructionAtOffset(dslotsLoad(pic))); /* Only the shape needs to be patched to fail -- atom jump will never be taken. */ repatcher.repatch(pic.fastPathStart.dataLabel32AtOffset( @@ -1299,10 +1268,9 @@ class GetElemCompiler : public PICStubCompiler pic.slowPathStart); RepatchBuffer repatcher2(pic.slowPathStart.executableAddress(), INLINE_PATH_LENGTH); - ReturnAddressPtr retPtr(pic.slowPathStart.callAtOffset(pic.callReturn).executableAddress()); - MacroAssemblerCodePtr target(JS_FUNC_TO_DATA_PTR(void *, ic::GetElem)); - repatcher.relinkCallerToTrampoline(retPtr, target); + FunctionPtr target(JS_FUNC_TO_DATA_PTR(void *, ic::GetElem)); + repatcher.relink(pic.slowPathCall, target); } bool patchInline(JSObject *holder, const Shape *shape) @@ -1312,7 +1280,7 @@ class GetElemCompiler : public PICStubCompiler int32 offset; if (!holder->hasSlotsArray()) { - JSC::CodeLocationInstruction istr = pic.storeBack.instructionAtOffset(dslotsLoad()); + JSC::CodeLocationInstruction istr = pic.fastPathRejoin.instructionAtOffset(dslotsLoad()); repatcher.repatchLoadPtrToLEA(istr); // @@ -1334,10 +1302,10 @@ class GetElemCompiler : public PICStubCompiler uint32 idOffset = pic.shapeGuard + inlineAtomOffset(); repatcher.repatch(pic.fastPathStart.dataLabelPtrAtOffset(idOffset), id); #if defined JS_NUNBOX32 - repatcher.repatch(pic.storeBack.dataLabel32AtOffset(GETELEM_TYPE_LOAD), offset + 4); - repatcher.repatch(pic.storeBack.dataLabel32AtOffset(GETELEM_DATA_LOAD), offset); + repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(GETELEM_TYPE_LOAD), offset + 4); + repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(GETELEM_DATA_LOAD), offset); #elif defined JS_PUNBOX64 - repatcher.repatch(pic.storeBack.dataLabel32AtOffset(pic.labels.getelem.inlineValueOffset), offset); + repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(pic.labels.getelem.inlineValueOffset), offset); #endif pic.inlinePathPatched = true; @@ -1376,21 +1344,10 @@ class GetElemCompiler : public PICStubCompiler Assembler masm; if (pic.objNeedsRemat()) { - if (pic.objRemat() >= sizeof(JSStackFrame)) - masm.loadPayload(Address(JSFrameReg, pic.objRemat()), pic.objReg); - else - masm.move(RegisterID(pic.objRemat()), pic.objReg); + masm.rematPayload(pic.objRemat(), pic.objReg); pic.u.get.objNeedsRemat = false; } - if (pic.idNeedsRemat()) { - if (pic.idRemat() >= sizeof(JSStackFrame)) - masm.loadPayload(Address(JSFrameReg, pic.idRemat()), pic.u.get.idReg); - else - masm.move(RegisterID(pic.idRemat()), pic.u.get.idReg); - pic.u.get.idNeedsRemat = false; - } - if (pic.shapeNeedsRemat()) { masm.loadShape(pic.objReg, pic.shapeReg); pic.shapeRegHasBaseShape = true; @@ -1473,7 +1430,7 @@ class GetElemCompiler : public PICStubCompiler buffer.link(*pj, pic.slowPathStart); // The final exit jumps to the store-back in the inline stub. - buffer.link(done, pic.storeBack); + buffer.link(done, pic.fastPathRejoin); CodeLocationLabel cs = buffer.finalizeCodeAddendum(); #if DEBUG char *chars = js_DeflateString(cx, id->chars(), id->length()); @@ -1521,8 +1478,6 @@ class GetElemCompiler : public PICStubCompiler if (!prop) return disable("lookup failed"); - AutoPropertyDropper dropper(cx, holder, prop); - if (!obj->isNative()) return disable("non-native obj"); if (!holder->isNative()) @@ -1578,10 +1533,9 @@ class ScopeNameCompiler : public PICStubCompiler pic.slowPathStart); RepatchBuffer repatcher2(pic.slowPathStart.executableAddress(), INLINE_PATH_LENGTH); - ReturnAddressPtr retPtr(pic.slowPathStart.callAtOffset(pic.callReturn).executableAddress()); VoidStubPIC stub = (pic.kind == ic::PICInfo::NAME) ? ic::Name : ic::XName; - MacroAssemblerCodePtr target(JS_FUNC_TO_DATA_PTR(void *, stub)); - repatcher.relinkCallerToTrampoline(retPtr, target); + FunctionPtr target(JS_FUNC_TO_DATA_PTR(void *, stub)); + repatcher.relink(pic.slowPathCall, target); } typedef Vector JumpList; @@ -1676,7 +1630,7 @@ class ScopeNameCompiler : public PICStubCompiler return false; buffer.link(failJump, pic.slowPathStart); - buffer.link(done, pic.storeBack); + buffer.link(done, pic.fastPathRejoin); CodeLocationLabel cs = buffer.finalizeCodeAddendum(); JaegerSpew(JSpew_PICs, "generated %s global stub at %p\n", type, cs.executableAddress()); spew("NAME stub", "global"); @@ -1780,7 +1734,7 @@ class ScopeNameCompiler : public PICStubCompiler return false; buffer.link(failJump, pic.slowPathStart); - buffer.link(done, pic.storeBack); + buffer.link(done, pic.fastPathRejoin); CodeLocationLabel cs = buffer.finalizeCodeAddendum(); JaegerSpew(JSpew_PICs, "generated %s call stub at %p\n", type, cs.executableAddress()); @@ -1850,7 +1804,6 @@ class ScopeNameCompiler : public PICStubCompiler bool retrieve(Value *vp) { if (prop && (!obj->isNative() || !holder->isNative())) { - holder->dropProperty(cx, prop); if (!obj->getProperty(cx, ATOM_TO_JSID(atom), vp)) return false; } else { @@ -1873,7 +1826,6 @@ class ScopeNameCompiler : public PICStubCompiler normalized = js_UnwrapWithObject(cx, obj); NATIVE_GET(cx, normalized, holder, shape, JSGET_METHOD_BARRIER, vp, return false); - JS_UNLOCK_OBJ(cx, holder); } return true; @@ -1916,9 +1868,8 @@ class BindNameCompiler : public PICStubCompiler repatcher.relink(pic.shapeGuard + inlineJumpOffset(pic), pic.slowPathStart); RepatchBuffer repatcher2(pic.slowPathStart.executableAddress(), INLINE_PATH_LENGTH); - ReturnAddressPtr retPtr(pic.slowPathStart.callAtOffset(pic.callReturn).executableAddress()); - MacroAssemblerCodePtr target(JS_FUNC_TO_DATA_PTR(void *, ic::BindName)); - repatcher.relinkCallerToTrampoline(retPtr, target); + FunctionPtr target(JS_FUNC_TO_DATA_PTR(void *, ic::BindName)); + repatcher2.relink(pic.slowPathCall, target); } bool generateStub(JSObject *obj) @@ -1967,7 +1918,7 @@ class BindNameCompiler : public PICStubCompiler return false; buffer.link(failJump, pic.slowPathStart); - buffer.link(done, pic.storeBack); + buffer.link(done, pic.fastPathRejoin); CodeLocationLabel cs = buffer.finalizeCodeAddendum(); JaegerSpew(JSpew_PICs, "generated %s stub at %p\n", type, cs.executableAddress()); @@ -2214,8 +2165,7 @@ ic::CallProp(VMFrame &f, ic::PICInfo *pic) rval.setObject(entry->vword.toFunObj()); } else if (entry->vword.isSlot()) { uint32 slot = entry->vword.toSlot(); - JS_ASSERT(obj2->containsSlot(slot)); - rval = obj2->lockedGetSlot(slot); + rval = obj2->nativeGetSlot(slot); } else { JS_ASSERT(entry->vword.isShape()); const Shape *shape = entry->vword.toShape(); diff --git a/js/src/methodjit/PolyIC.h b/js/src/methodjit/PolyIC.h index 77fdd5af99c7..774a771047d7 100644 --- a/js/src/methodjit/PolyIC.h +++ b/js/src/methodjit/PolyIC.h @@ -187,7 +187,57 @@ union PICLabels { }; #endif -struct PICInfo { +struct BaseIC { + // Address of inline fast-path. + JSC::CodeLocationLabel fastPathStart; + + // Address to rejoin to the fast-path. + JSC::CodeLocationLabel fastPathRejoin; + + // Start of the slow path. + JSC::CodeLocationLabel slowPathStart; + + // Slow path stub call. + JSC::CodeLocationCall slowPathCall; + + // Address of the start of the last generated stub, if any. + JSC::CodeLocationLabel lastStubStart; + + typedef Vector ExecPoolVector; + + // ExecutablePools that IC stubs were generated into. + ExecPoolVector execPools; + + // Return the start address of the last path in this PIC, which is the + // inline path if no stubs have been generated yet. + JSC::CodeLocationLabel lastPathStart() { + return stubsGenerated > 0 ? lastStubStart : fastPathStart; + } + + // Whether or not the callsite has been hit at least once. + bool hit : 1; + + // Number of stubs generated. + uint32 stubsGenerated : 5; + + // Release ExecutablePools referred to by this PIC. + void releasePools() { + for (JSC::ExecutablePool **pExecPool = execPools.begin(); + pExecPool != execPools.end(); + ++pExecPool) { + (*pExecPool)->release(); + } + } + + void reset() { + hit = false; + stubsGenerated = 0; + releasePools(); + execPools.clear(); + } +}; + +struct PICInfo : public BaseIC { typedef JSC::MacroAssembler::RegisterID RegisterID; // Operation this is a PIC for. @@ -207,7 +257,6 @@ struct PICInfo { }; union { - // This struct comes out to 93 bits with GCC. struct { RegisterID typeReg : 5; // reg used for checking type bool hasTypeCheck : 1; // type check and reg are present @@ -216,11 +265,9 @@ struct PICInfo { int32 typeCheckOffset; // Remat info for the object reg. - uint32 objRemat : 20; + int32 objRemat : MIN_STATE_REMAT_BITS; bool objNeedsRemat : 1; RegisterID idReg : 5; // only used in GETELEM PICs. - uint32 idRemat : 20; - bool idNeedsRemat : 1; } get; ValueRemat vr; } u; @@ -240,25 +287,18 @@ struct PICInfo { bool usePropCache : 1; // State flags. - bool hit : 1; // this PIC has been executed bool inlinePathPatched : 1; // inline path has been patched RegisterID shapeReg : 5; // also the out type reg RegisterID objReg : 5; // also the out data reg - // Number of stubs generated. - uint32 stubsGenerated : 5; - // Offset from start of fast path to initial shape guard. uint32 shapeGuard; - // Return address of slow path call, as an offset from slowPathStart. - uint32 callReturn; - - inline bool isSet() { + inline bool isSet() const { return kind == SET || kind == SETMETHOD; } - inline bool isGet() { + inline bool isGet() const { return kind == GET || kind == CALL || kind == GETELEM; } inline RegisterID typeReg() { @@ -269,22 +309,14 @@ struct PICInfo { JS_ASSERT(isGet()); return u.get.hasTypeCheck; } - inline uint32 objRemat() { + inline const StateRemat objRemat() const { JS_ASSERT(isGet()); - return u.get.objRemat; - } - inline uint32 idRemat() { - JS_ASSERT(isGet()); - return u.get.idRemat; + return StateRemat::FromInt32(u.get.objRemat); } inline bool objNeedsRemat() { JS_ASSERT(isGet()); return u.get.objNeedsRemat; } - inline bool idNeedsRemat() { - JS_ASSERT(isGet()); - return u.get.idNeedsRemat; - } inline bool shapeNeedsRemat() { return !shapeRegHasBaseShape; } @@ -293,64 +325,36 @@ struct PICInfo { return !hasTypeCheck(); } + inline void setObjRemat(const StateRemat &sr) { + JS_ASSERT(isGet()); + u.get.objRemat = sr.toInt32(); + JS_ASSERT(u.get.objRemat == sr.toInt32()); + } + #if defined JS_CPU_X64 // Required labels for platform-specific patching. PICLabels labels; #endif + // Where in the script did we generate this PIC? + jsbytecode *pc; + // Index into the script's atom table. JSAtom *atom; - // Address of inline fast-path. - JSC::CodeLocationLabel fastPathStart; - - // Address of store back at the end of the inline fast-path. - JSC::CodeLocationLabel storeBack; - - // Offset from callReturn to the start of the slow case. - JSC::CodeLocationLabel slowPathStart; - - // Address of the start of the last generated stub, if any. - JSC::CodeLocationLabel lastStubStart; - - typedef Vector ExecPoolVector; - - // ExecutablePools that PIC stubs were generated into. - ExecPoolVector execPools; - - // Return the start address of the last path in this PIC, which is the - // inline path if no stubs have been generated yet. - JSC::CodeLocationLabel lastPathStart() { - return stubsGenerated > 0 ? lastStubStart : fastPathStart; - } - bool shouldGenerate() { return stubsGenerated < MAX_PIC_STUBS || !inlinePathPatched; } - // Release ExecutablePools referred to by this PIC. - void releasePools() { - for (JSC::ExecutablePool **pExecPool = execPools.begin(); - pExecPool != execPools.end(); - ++pExecPool) - { - (*pExecPool)->release(); - } - } - // Reset the data members to the state of a fresh PIC before any patching // or stub generation was done. void reset() { - hit = false; inlinePathPatched = false; - if (kind == GET || kind == CALL || kind == GETELEM) { + if (kind == GET || kind == CALL || kind == GETELEM) u.get.objNeedsRemat = false; - } secondShapeGuard = 0; shapeRegHasBaseShape = true; - stubsGenerated = 0; - releasePools(); - execPools.clear(); + BaseIC::reset(); } }; diff --git a/js/src/methodjit/PunboxAssembler.h b/js/src/methodjit/PunboxAssembler.h index 77bb9f157013..eabe3d9f3ff4 100644 --- a/js/src/methodjit/PunboxAssembler.h +++ b/js/src/methodjit/PunboxAssembler.h @@ -40,7 +40,7 @@ #if !defined jsjaeger_assembler64_h__ && defined JS_METHODJIT && defined JS_PUNBOX64 #define jsjaeger_assembler64_h__ -#include "methodjit/BaseAssembler.h" +#include "assembler/assembler/MacroAssembler.h" #include "methodjit/MachineRegs.h" #include "methodjit/RematInfo.h" @@ -76,7 +76,7 @@ struct ImmPayload : Imm64 { } }; -class Assembler : public BaseAssembler +class PunboxAssembler : public JSC::MacroAssembler { static const uint32 PAYLOAD_OFFSET = 0; @@ -206,12 +206,12 @@ class Assembler : public BaseAssembler template void storeValue(const ValueRemat &vr, T address) { - if (vr.isConstant) - storeValue(Valueify(vr.u.v), address); - else if (vr.u.s.isTypeKnown) - storeValueFromComponents(ImmType(vr.u.s.type.knownType), vr.u.s.data, address); + if (vr.isConstant()) + storeValue(vr.value(), address); + else if (vr.isTypeKnown()) + storeValueFromComponents(ImmType(vr.knownType()), vr.dataReg(), address); else - storeValueFromComponents(vr.u.s.type.reg, vr.u.s.data, address); + storeValueFromComponents(vr.typeReg(), vr.dataReg(), address); } void loadPrivate(Address privAddr, RegisterID to) { @@ -224,94 +224,102 @@ class Assembler : public BaseAssembler loadPtr(priv, to); } - Jump testNull(Assembler::Condition cond, RegisterID reg) { + Jump testNull(Condition cond, RegisterID reg) { return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_NULL)); } - Jump testNull(Assembler::Condition cond, Address address) { + Jump testNull(Condition cond, Address address) { loadValue(address, Registers::ValueReg); return testNull(cond, Registers::ValueReg); } - Jump testUndefined(Assembler::Condition cond, RegisterID reg) { + Jump testUndefined(Condition cond, RegisterID reg) { return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_UNDEFINED)); } - Jump testUndefined(Assembler::Condition cond, Address address) { + Jump testUndefined(Condition cond, Address address) { loadValue(address, Registers::ValueReg); return testUndefined(cond, Registers::ValueReg); } - Jump testInt32(Assembler::Condition cond, RegisterID reg) { + Jump testInt32(Condition cond, RegisterID reg) { return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_INT32)); } - Jump testInt32(Assembler::Condition cond, Address address) { + Jump testInt32(Condition cond, Address address) { loadTypeTag(address, Registers::ValueReg); return testInt32(cond, Registers::ValueReg); } - Jump testNumber(Assembler::Condition cond, RegisterID reg) { - cond = (cond == Assembler::Equal) ? Assembler::Below : Assembler::AboveOrEqual; + Jump testNumber(Condition cond, RegisterID reg) { + cond = (cond == Equal) ? Below : AboveOrEqual; return branchPtr(cond, reg, ImmTag(JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET)); } - Jump testNumber(Assembler::Condition cond, Address address) { + Jump testNumber(Condition cond, Address address) { loadValue(address, Registers::ValueReg); return testNumber(cond, Registers::ValueReg); } - Jump testPrimitive(Assembler::Condition cond, RegisterID reg) { - cond = (cond == Assembler::Equal) ? Assembler::Below : Assembler::AboveOrEqual; + Jump testPrimitive(Condition cond, RegisterID reg) { + cond = (cond == Equal) ? Below : AboveOrEqual; return branchPtr(cond, reg, ImmTag(JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET)); } - Jump testPrimitive(Assembler::Condition cond, Address address) { + Jump testPrimitive(Condition cond, Address address) { loadValue(address, Registers::ValueReg); return testPrimitive(cond, Registers::ValueReg); } - Jump testObject(Assembler::Condition cond, RegisterID reg) { - cond = (cond == Assembler::Equal) ? Assembler::AboveOrEqual : Assembler::Below; + Jump testObject(Condition cond, RegisterID reg) { + cond = (cond == Equal) ? AboveOrEqual : Below; return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_OBJECT)); } - Jump testObject(Assembler::Condition cond, Address address) { + Jump testObject(Condition cond, Address address) { loadValue(address, Registers::ValueReg); return testObject(cond, Registers::ValueReg); } - Jump testDouble(Assembler::Condition cond, RegisterID reg) { - cond = (cond == Assembler::Equal) ? Assembler::BelowOrEqual : Assembler::Above; + Jump testDouble(Condition cond, RegisterID reg) { + cond = (cond == Equal) ? BelowOrEqual : Above; return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_MAX_DOUBLE)); } - Jump testDouble(Assembler::Condition cond, Address address) { + Jump testDouble(Condition cond, Address address) { loadValue(address, Registers::ValueReg); return testDouble(cond, Registers::ValueReg); } - Jump testBoolean(Assembler::Condition cond, RegisterID reg) { + Jump testBoolean(Condition cond, RegisterID reg) { return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_BOOLEAN)); } - Jump testBoolean(Assembler::Condition cond, Address address) { + Jump testBoolean(Condition cond, Address address) { loadTypeTag(address, Registers::ValueReg); return testBoolean(cond, Registers::ValueReg); } - Jump testString(Assembler::Condition cond, RegisterID reg) { + Jump testString(Condition cond, RegisterID reg) { return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_STRING)); } - Jump testString(Assembler::Condition cond, Address address) { + Jump testString(Condition cond, Address address) { loadTypeTag(address, Registers::ValueReg); return testString(cond, Registers::ValueReg); } + + template + Jump fastArrayLoadSlot(T address, RegisterID typeReg, RegisterID dataReg) { + loadValueAsComponents(address, typeReg, dataReg); + return branchPtr(Equal, typeReg, ImmType(JSVAL_TYPE_MAGIC)); + } }; +typedef PunboxAssembler ValueAssembler; + } /* namespace mjit */ } /* namespace js */ diff --git a/js/src/methodjit/RematInfo.h b/js/src/methodjit/RematInfo.h index 99bc3d2d2b62..c651637f927b 100644 --- a/js/src/methodjit/RematInfo.h +++ b/js/src/methodjit/RematInfo.h @@ -41,39 +41,157 @@ #define jsjaeger_remat_h__ #include "jscntxt.h" +#include "MachineRegs.h" #include "assembler/assembler/MacroAssembler.h" +namespace js { +namespace mjit { + +// Lightweight, union-able components of FrameEntry. +struct StateRemat { + typedef JSC::MacroAssembler::RegisterID RegisterID; + typedef JSC::MacroAssembler::Address Address; + + static const int32 CONSTANT = -int(UINT16_LIMIT * sizeof(Value)); + + // This union encodes the fastest rematerialization of a non-constant + // value. The |offset| field can be used to recover information + // without this struct's helpers: + // 1) A value in (CONSTANT, 0) is an argument slot. + // 2) A value in [0, fp) is a register ID. + // 3) A value in [fp, inf) is a local slot. + union { + RegisterID reg_; + int32 offset_; + }; + + static StateRemat FromInt32(int32 i32) { + StateRemat sr; + sr.offset_ = i32; + return sr; + } + static StateRemat FromRegister(RegisterID reg) { + StateRemat sr; + sr.reg_ = reg; + JS_ASSERT(sr.inRegister()); + return sr; + } + static StateRemat FromAddress(Address address) { + JS_ASSERT(address.base == JSFrameReg); + StateRemat sr; + sr.offset_ = address.offset; + JS_ASSERT(sr.inMemory()); + return sr; + } + + // Minimum number of bits needed to compactly store the int32 + // representation in a struct or union. This prevents bloating the IC + // structs by an extra 8 bytes in some cases. 16 bits are needed to encode + // the largest local: + // ((UINT16_LIMIT - 1) * sizeof(Value) + sizeof(JSStackFrame), + // And an extra bit for the sign on arguments. +#define MIN_STATE_REMAT_BITS 17 + + bool isConstant() const { return offset_ == CONSTANT; } + bool inRegister() const { return offset_ >= 0 && + offset_ <= int32(JSC::MacroAssembler::TotalRegisters); } + bool inMemory() const { return offset_ >= int32(sizeof(JSStackFrame)); } + + int32 toInt32() const { return offset_; } + Address address() const { + JS_ASSERT(inMemory()); + return Address(JSFrameReg, offset_); + } + RegisterID reg() const { + JS_ASSERT(inRegister()); + return reg_; + } +}; + /* Lightweight version of FrameEntry. */ struct ValueRemat { typedef JSC::MacroAssembler::RegisterID RegisterID; union { struct { union { - RegisterID reg; - JSValueType knownType; + int32 typeRemat_; + JSValueType knownType_; } type; - RegisterID data : 5; - bool isTypeKnown : 1; + int32 dataRemat_ : MIN_STATE_REMAT_BITS; + bool isTypeKnown_ : 1; } s; - jsval v; + jsval v_; } u; - bool isConstant : 1; - bool isDataSynced : 1; - bool isTypeSynced : 1; + bool isConstant_ : 1; + bool isDataSynced : 1; + bool isTypeSynced : 1; - RegisterID dataReg() { - JS_ASSERT(!isConstant); - return u.s.data; + static ValueRemat FromConstant(const Value &v) { + ValueRemat vr; + vr.isConstant_ = true; + vr.u.v_ = Jsvalify(v); + return vr; + } + static ValueRemat FromKnownType(JSValueType type, RegisterID dataReg) { + ValueRemat vr; + vr.isConstant_ = false; + vr.u.s.type.knownType_ = type; + vr.u.s.isTypeKnown_ = true; + vr.u.s.dataRemat_ = StateRemat::FromRegister(dataReg).toInt32(); + + // Assert bitfields are okay. + JS_ASSERT(vr.dataReg() == dataReg); + return vr; + } + static ValueRemat FromRegisters(RegisterID typeReg, RegisterID dataReg) { + ValueRemat vr; + vr.isConstant_ = false; + vr.u.s.isTypeKnown_ = false; + vr.u.s.type.typeRemat_ = StateRemat::FromRegister(typeReg).toInt32(); + vr.u.s.dataRemat_ = StateRemat::FromRegister(dataReg).toInt32(); + + // Assert bitfields are okay. + JS_ASSERT(vr.dataReg() == dataReg); + JS_ASSERT(vr.typeReg() == typeReg); + return vr; } - RegisterID typeReg() { - JS_ASSERT(!isConstant && !u.s.isTypeKnown); - return u.s.type.reg; + RegisterID dataReg() const { + JS_ASSERT(!isConstant()); + return dataRemat().reg(); + } + RegisterID typeReg() const { + JS_ASSERT(!isTypeKnown()); + return typeRemat().reg(); } + bool isConstant() const { return isConstant_; } + bool isTypeKnown() const { return isConstant() || u.s.isTypeKnown_; } + + StateRemat dataRemat() const { + JS_ASSERT(!isConstant()); + return StateRemat::FromInt32(u.s.dataRemat_); + } + StateRemat typeRemat() const { + JS_ASSERT(!isTypeKnown()); + return StateRemat::FromInt32(u.s.type.typeRemat_); + } + Value value() const { + JS_ASSERT(isConstant()); + return Valueify(u.v_); + } + JSValueType knownType() const { + JS_ASSERT(isTypeKnown()); + if (isConstant()) { + const Value v = value(); + if (v.isDouble()) + return JSVAL_TYPE_DOUBLE; + return v.extractNonDoubleType(); + } + return u.s.type.knownType_; + } bool isType(JSValueType type_) const { - JS_ASSERT(!isConstant); - return u.s.isTypeKnown && u.s.type.knownType == type_; + return isTypeKnown() && knownType() == type_; } }; @@ -159,5 +277,8 @@ struct RematInfo { SyncState sync_; }; +} /* namespace mjit */ +} /* namespace js */ + #endif diff --git a/js/src/methodjit/StubCalls-inl.h b/js/src/methodjit/StubCalls-inl.h index 2b2844a2ea9f..00d217a38d03 100644 --- a/js/src/methodjit/StubCalls-inl.h +++ b/js/src/methodjit/StubCalls-inl.h @@ -76,7 +76,7 @@ ReportAtomNotDefined(JSContext *cx, JSAtom *atom) (shape)->slot != SHAPE_INVALID_SLOT && \ !(obj)->brandedOrHasMethodBarrier()) { \ /* Fast path for, e.g., plain Object instance properties. */ \ - (obj)->lockedSetSlot((shape)->slot, *vp); \ + (obj)->nativeSetSlot((shape)->slot, *vp); \ } else { \ if (!js_NativeSet(cx, obj, shape, false, vp)) \ THROW(); \ @@ -90,7 +90,7 @@ ReportAtomNotDefined(JSContext *cx, JSAtom *atom) JS_ASSERT((shape)->slot != SHAPE_INVALID_SLOT || \ !shape->hasDefaultSetter()); \ if (((shape)->slot != SHAPE_INVALID_SLOT)) \ - *(vp) = (pobj)->lockedGetSlot((shape)->slot); \ + *(vp) = (pobj)->nativeGetSlot((shape)->slot); \ else \ (vp)->setUndefined(); \ } else { \ diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index 36e9dffc1691..80d34e39ca45 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -194,15 +194,7 @@ stubs::SetName(VMFrame &f, JSAtom *origAtom) JS_ASSERT(obj->isExtensible()); if (obj->nativeEmpty()) { - /* - * We check that cx owns obj here and will continue to own - * it after ensureClassReservedSlotsForEmptyObject returns - * so we can continue to skip JS_UNLOCK_OBJ calls. - */ - JS_ASSERT(CX_OWNS_OBJECT_TITLE(cx, obj)); - bool ok = obj->ensureClassReservedSlotsForEmptyObject(cx); - JS_ASSERT(CX_OWNS_OBJECT_TITLE(cx, obj)); - if (!ok) + if (!obj->ensureClassReservedSlotsForEmptyObject(cx)) THROW(); } @@ -238,7 +230,7 @@ stubs::SetName(VMFrame &f, JSAtom *origAtom) * new property, not updating an existing slot's value that * might contain a method of a branded shape. */ - obj->lockedSetSlot(slot, rval); + obj->setSlot(slot, rval); /* * Purge the property cache of the id we may have just @@ -357,9 +349,8 @@ NameOp(VMFrame &f, JSObject *obj, bool callname = false) f.regs.sp[-1].setObject(entry->vword.toFunObj()); } else if (entry->vword.isSlot()) { uintN slot = entry->vword.toSlot(); - JS_ASSERT(obj2->containsSlot(slot)); f.regs.sp++; - f.regs.sp[-1] = obj2->lockedGetSlot(slot); + f.regs.sp[-1] = obj2->nativeGetSlot(slot); } else { JS_ASSERT(entry->vword.isShape()); shape = entry->vword.toShape(); @@ -406,7 +397,6 @@ NameOp(VMFrame &f, JSObject *obj, bool callname = false) /* Take the slow path if prop was not found in a native object. */ if (!obj->isNative() || !obj2->isNative()) { - obj2->dropProperty(cx, prop); if (!obj->getProperty(cx, id, &rval)) return NULL; } else { @@ -415,7 +405,6 @@ NameOp(VMFrame &f, JSObject *obj, bool callname = false) if (normalized->getClass() == &js_WithClass && !shape->hasDefaultGetter()) normalized = js_UnwrapWithObject(cx, normalized); NATIVE_GET(cx, normalized, obj2, shape, JSGET_METHOD_BARRIER, &rval, return NULL); - JS_UNLOCK_OBJ(cx, obj2); } f.regs.sp++; @@ -455,57 +444,6 @@ stubs::GetGlobalName(VMFrame &f) THROW(); } -static inline bool -IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval) -{ - if (iterobj->getClass() == &js_IteratorClass) { - NativeIterator *ni = (NativeIterator *) iterobj->getPrivate(); - JS_ASSERT(ni->props_cursor < ni->props_end); - if (ni->isKeyIter()) { - jsid id = *ni->currentKey(); - if (JSID_IS_ATOM(id)) { - rval->setString(JSID_TO_STRING(id)); - ni->incKeyCursor(); - return true; - } - /* Take the slow path if we have to stringify a numeric property name. */ - } else { - *rval = *ni->currentValue(); - ni->incValueCursor(); - return true; - } - } - return js_IteratorNext(cx, iterobj, rval); -} - -template -void JS_FASTCALL -stubs::ForName(VMFrame &f, JSAtom *atom) -{ - JSContext *cx = f.cx; - JSFrameRegs ®s = f.regs; - - JS_ASSERT(regs.sp - 1 >= f.fp()->base()); - jsid id = ATOM_TO_JSID(atom); - JSObject *obj, *obj2; - JSProperty *prop; - if (!js_FindProperty(cx, id, &obj, &obj2, &prop)) - THROW(); - if (prop) - obj2->dropProperty(cx, prop); - { - AutoValueRooter tvr(cx); - JS_ASSERT(regs.sp[-1].isObject()); - if (!IteratorNext(cx, ®s.sp[-1].toObject(), tvr.addr())) - THROW(); - if (!obj->setProperty(cx, id, tvr.addr(), strict)) - THROW(); - } -} - -template void JS_FASTCALL stubs::ForName(VMFrame &f, JSAtom *atom); -template void JS_FASTCALL stubs::ForName(VMFrame &f, JSAtom *atom); - void JS_FASTCALL stubs::GetElem(VMFrame &f) { @@ -975,7 +913,6 @@ stubs::DefFun(VMFrame &f, JSFunction *fun) if (oldAttrs & JSPROP_PERMANENT) doSet = true; } - pobj->dropProperty(cx, prop); } Value rval = ObjectValue(*obj); @@ -1759,8 +1696,7 @@ NameIncDec(VMFrame &f, JSObject *obj, JSAtom *origAtom) if (!atom) { if (obj == obj2 && entry->vword.isSlot()) { uint32 slot = entry->vword.toSlot(); - JS_ASSERT(obj->containsSlot(slot)); - Value &rref = obj->getSlotRef(slot); + Value &rref = obj->nativeGetSlotRef(slot); int32_t tmp; if (JS_LIKELY(rref.isInt32() && CanIncDecWithoutOverflow(tmp = rref.toInt32()))) { int32_t inc = tmp + N; @@ -1781,7 +1717,6 @@ NameIncDec(VMFrame &f, JSObject *obj, JSAtom *origAtom) ReportAtomNotDefined(cx, atom); return false; } - obj2->dropProperty(cx, prop); return ObjIncOp(f, obj, id); } @@ -2042,8 +1977,7 @@ InlineGetProp(VMFrame &f) rval.setObject(entry->vword.toFunObj()); } else if (entry->vword.isSlot()) { uint32 slot = entry->vword.toSlot(); - JS_ASSERT(obj2->containsSlot(slot)); - rval = obj2->lockedGetSlot(slot); + rval = obj2->nativeGetSlot(slot); } else { JS_ASSERT(entry->vword.isShape()); const Shape *shape = entry->vword.toShape(); @@ -2134,8 +2068,7 @@ stubs::CallProp(VMFrame &f, JSAtom *origAtom) rval.setObject(entry->vword.toFunObj()); } else if (entry->vword.isSlot()) { uint32 slot = entry->vword.toSlot(); - JS_ASSERT(obj2->containsSlot(slot)); - rval = obj2->lockedGetSlot(slot); + rval = obj2->nativeGetSlot(slot); } else { JS_ASSERT(entry->vword.isShape()); const Shape *shape = entry->vword.toShape(); @@ -2249,8 +2182,7 @@ InitPropOrMethod(VMFrame &f, JSAtom *atom, JSOp op) */ PropertyCacheEntry *entry; const Shape *shape; - if (CX_OWNS_OBJECT_TITLE(cx, obj) && - JS_PROPERTY_CACHE(cx).testForInit(rt, regs.pc, obj, &shape, &entry) && + if (JS_PROPERTY_CACHE(cx).testForInit(rt, regs.pc, obj, &shape, &entry) && shape->hasDefaultSetter() && shape->previous() == obj->lastProperty()) { @@ -2277,7 +2209,7 @@ InitPropOrMethod(VMFrame &f, JSAtom *atom, JSOp op) * property, not updating an existing slot's value that might * contain a method of a branded shape. */ - obj->lockedSetSlot(slot, rval); + obj->nativeSetSlot(slot, rval); } else { PCMETER(JS_PROPERTY_CACHE(cx).inipcmisses++); @@ -2684,7 +2616,6 @@ stubs::DelName(VMFrame &f, JSAtom *atom) f.regs.sp++; f.regs.sp[-1] = BooleanValue(true); if (prop) { - obj2->dropProperty(f.cx, prop); if (!obj->deleteProperty(f.cx, id, &f.regs.sp[-1], false)) THROW(); } @@ -2761,8 +2692,6 @@ stubs::DefVar(VMFrame &f, JSAtom *atom) JS_ASSERT(prop); obj2 = obj; } - - obj2->dropProperty(cx, prop); } JSBool JS_FASTCALL @@ -2786,11 +2715,7 @@ stubs::In(VMFrame &f) if (!obj->lookupProperty(cx, id, &obj2, &prop)) THROWV(JS_FALSE); - JSBool cond = !!prop; - if (prop) - obj2->dropProperty(cx, prop); - - return cond; + return !!prop; } template void JS_FASTCALL stubs::DelElem(VMFrame &f); diff --git a/js/src/methodjit/StubCalls.h b/js/src/methodjit/StubCalls.h index c460f62fd0d9..33897544dd62 100644 --- a/js/src/methodjit/StubCalls.h +++ b/js/src/methodjit/StubCalls.h @@ -207,7 +207,6 @@ void JS_FASTCALL Iter(VMFrame &f, uint32 flags); void JS_FASTCALL IterNext(VMFrame &f); JSBool JS_FASTCALL IterMore(VMFrame &f); void JS_FASTCALL EndIter(VMFrame &f); -template void JS_FASTCALL ForName(VMFrame &f, JSAtom *atom); JSBool JS_FASTCALL ValueToBoolean(VMFrame &f); JSString * JS_FASTCALL TypeOf(VMFrame &f); diff --git a/js/src/metrics/jint/treesearch.py b/js/src/metrics/jint/treesearch.py index 632717c3fea0..afe373d1fdd1 100644 --- a/js/src/metrics/jint/treesearch.py +++ b/js/src/metrics/jint/treesearch.py @@ -387,7 +387,7 @@ if __name__ == '__main__': lib_dir = os.path.join(script_dir, 'lib') # The [TESTS] optional arguments are paths of test files relative - # to the trace-test/tests directory. + # to the jit-test/tests directory. from optparse import OptionParser op = OptionParser(usage='%prog [options] JS_SHELL test') diff --git a/js/src/nanojit-import-rev b/js/src/nanojit-import-rev index 0b800b57c309..9baa2af4d0dc 100644 --- a/js/src/nanojit-import-rev +++ b/js/src/nanojit-import-rev @@ -1 +1 @@ -8409c49a72dc223ca0622bc18b396e81f8d45608 +a52df753119f0b9c3b6b9a3e6b8efc664b164dec diff --git a/js/src/nanojit/LIR.cpp b/js/src/nanojit/LIR.cpp index 78776fb534fd..e1a111eb120e 100644 --- a/js/src/nanojit/LIR.cpp +++ b/js/src/nanojit/LIR.cpp @@ -2052,6 +2052,7 @@ namespace nanojit CSE_ACC_MULTIPLE( EMB_NUM_USED_ACCS + 1), storesSinceLastLoad(ACCSET_NONE), alloc(alloc), + knownCmpValues(alloc), suspended(false) { @@ -2153,6 +2154,8 @@ namespace nanojit // Note that this clears the CONST and MULTIPLE load tables as well. for (CseAcc a = 0; a < CSE_NUM_USED_ACCS; a++) clearL(a); + + knownCmpValues.clear(); } inline uint32_t CseFilter::hashImmI(int32_t a) { @@ -2556,6 +2559,15 @@ namespace nanojit if (!ins) { ins = out->ins2(op, a, b); addNL(LIns2, ins, k); + } else if (ins->isCmp()) { + if (knownCmpValues.containsKey(ins)) { + // We've seen this comparison before, and it was previously + // used in a guard, so we know what its value must be at this + // point. Replace it with a constant. + NanoAssert(ins->isCmp()); + bool cmpValue = knownCmpValues.get(ins); + return insImmI(cmpValue ? 1 : 0); + } } NanoAssert(ins->isop(op) && ins->oprnd1() == a && ins->oprnd2() == b); return ins; @@ -2670,6 +2682,13 @@ namespace nanojit ins = out->insGuard(op, c, gr); addNL(LIns1, ins, k); } + // After this guard, we know that 'c's result was true (if + // op==LIR_xf) or false (if op==LIR_xt), else we would have + // exited. Record this fact in case 'c' occurs again. + if (!suspended) { + bool c_value = (op == LIR_xt ? false : true); + knownCmpValues.put(c, c_value); + } } else { ins = out->insGuard(op, c, gr); } @@ -2756,7 +2775,7 @@ namespace nanojit case LIR_negi: if (lim > 0) - return sub(Interval(0, 0), of(ins->oprnd2(), lim-1)); + return sub(Interval(0, 0), of(ins->oprnd1(), lim-1)); goto overflow; case LIR_muli: diff --git a/js/src/nanojit/LIR.h b/js/src/nanojit/LIR.h index d80f5a7da0d3..7eaf1a798e3a 100644 --- a/js/src/nanojit/LIR.h +++ b/js/src/nanojit/LIR.h @@ -1986,6 +1986,12 @@ namespace nanojit Allocator& alloc; + // After a conditional guard such as "xf cmp", we know that 'cmp' must + // be true, else we would have side-exited. So if we see 'cmp' again + // we can treat it like a constant. This table records such + // comparisons. + HashMap knownCmpValues; + // If true, we will not add new instructions to the CSE tables, but we // will continue to CSE instructions that match existing table // entries. Load instructions will still be removed if aliasing diff --git a/js/src/nanojit/NativeSparc.cpp b/js/src/nanojit/NativeSparc.cpp index ecc3c3268218..2e99e727cdef 100644 --- a/js/src/nanojit/NativeSparc.cpp +++ b/js/src/nanojit/NativeSparc.cpp @@ -22,7 +22,8 @@ * * Contributor(s): * Adobe AS3 Team - * leon.sha@sun.com + * leon.sha@oracle.com + * ginn.chen@oracle.com * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -69,6 +70,453 @@ namespace nanojit #define BIT_ROUND_UP(v,q) ( (((uintptr_t)v)+(q)-1) & ~((q)-1) ) #define TODO(x) do{ verbose_only(outputf(#x);) NanoAssertMsgf(false, "%s", #x); } while(0) + inline void Assembler::CALL(const CallInfo* ci) { + int32_t offset = (ci->_address) - ((int32_t)_nIns) + 4; + int32_t i = 0x40000000 | ((offset >> 2) & 0x3FFFFFFF); + IMM32(i); + asm_output("call %s",(ci->_name)); + } + + inline void Assembler::IntegerOperation + (Register rs1, Register rs2, Register rd, int32_t op3, const char *opcode) { + Format_3_1(2, rd, op3, rs1, 0, rs2); + asm_output("%s %s, %s, %s", opcode, gpn(rs1), gpn(rs2), gpn(rd)); + } + + inline void Assembler::IntegerOperationI + (Register rs1, int32_t simm13, Register rd, int32_t op3, const char *opcode) { + Format_3_1I(2, rd, op3, rs1, simm13); + asm_output("%s %s, %d, %s", opcode, gpn(rs1), simm13, gpn(rd)); + } + + inline void Assembler::ADD(Register rs1, Register rs2, Register rd) { + IntegerOperation(rs1, rs2, rd, 0, "add"); + } + inline void Assembler::ADDCC(Register rs1, Register rs2, Register rd) { + IntegerOperation(rs1, rs2, rd, 0x10, "addcc"); + } + inline void Assembler::AND(Register rs1, Register rs2, Register rd) { + IntegerOperation(rs1, rs2, rd, 0x1, "and"); + } + inline void Assembler::ANDCC(Register rs1, Register rs2, Register rd) { + IntegerOperation(rs1, rs2, rd, 0x11, "andcc"); + } + inline void Assembler::OR(Register rs1, Register rs2, Register rd) { + IntegerOperation(rs1, rs2, rd, 0x2, "or"); + } + inline void Assembler::ORI(Register rs1, int32_t simm13, Register rd) { + IntegerOperationI(rs1, simm13, rd, 0x2, "or"); + } + inline void Assembler::ORN(Register rs1, Register rs2, Register rd) { + IntegerOperation(rs1, rs2, rd, 0x6, "orn"); + } + inline void Assembler::SMULCC(Register rs1, Register rs2, Register rd) { + IntegerOperation(rs1, rs2, rd, 0x1b, "smulcc"); + } + inline void Assembler::SUB(Register rs1, Register rs2, Register rd) { + IntegerOperation(rs1, rs2, rd, 0x4, "sub"); + }; + inline void Assembler::SUBCC(Register rs1, Register rs2, Register rd) { + IntegerOperation(rs1, rs2, rd, 0x14, "subcc"); + }; + inline void Assembler::SUBI(Register rs1, int32_t simm13, Register rd) { + IntegerOperationI(rs1, simm13, rd, 0x4, "sub"); + } + inline void Assembler::XOR(Register rs1, Register rs2, Register rd) { + IntegerOperation(rs1, rs2, rd, 0x3, "xor"); + }; + + inline void Assembler::Bicc(int32_t a, int32_t dsp22, int32_t cond, const char *opcode) { + Format_2_2(a, cond, 0x2, dsp22); + asm_output("%s 0x%x", opcode, _nIns + dsp22 - 1); + } + + inline void Assembler::BA (int32_t a, int32_t dsp22) { Bicc(a, dsp22, 0x8, "ba"); } + inline void Assembler::BE (int32_t a, int32_t dsp22) { Bicc(a, dsp22, 0x1, "be"); } + inline void Assembler::BNE (int32_t a, int32_t dsp22) { Bicc(a, dsp22, 0x9, "bne"); } + inline void Assembler::BG (int32_t a, int32_t dsp22) { Bicc(a, dsp22, 0xa, "bg"); } + inline void Assembler::BGU (int32_t a, int32_t dsp22) { Bicc(a, dsp22, 0xc, "bgu"); } + inline void Assembler::BGE (int32_t a, int32_t dsp22) { Bicc(a, dsp22, 0xb, "bge"); } + inline void Assembler::BL (int32_t a, int32_t dsp22) { Bicc(a, dsp22, 0x3, "bl"); } + inline void Assembler::BLE (int32_t a, int32_t dsp22) { Bicc(a, dsp22, 0x2, "ble"); } + inline void Assembler::BLEU(int32_t a, int32_t dsp22) { Bicc(a, dsp22, 0x4, "bleu"); } + inline void Assembler::BCC (int32_t a, int32_t dsp22) { Bicc(a, dsp22, 0xd, "bcc"); } + inline void Assembler::BCS (int32_t a, int32_t dsp22) { Bicc(a, dsp22, 0x5, "bcs"); } + inline void Assembler::BVC (int32_t a, int32_t dsp22) { Bicc(a, dsp22, 0xf, "bvc"); } + inline void Assembler::BVS (int32_t a, int32_t dsp22) { Bicc(a, dsp22, 0x7, "bvs"); } + + inline void Assembler::FABSS(Register rs2, Register rd) { + Format_3_8(2, rd, 0x34, G0, 0x9, rs2); + asm_output("fabs %s, %s", gpn(rs2), gpn(rd)); + } + + inline void Assembler::FADDD(Register rs1, Register rs2, Register rd) { + Format_3_8(2, rd, 0x34, rs1, 0x42, rs2); + asm_output("faddd %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); + } + + inline void Assembler::FBfcc(int32_t a, int32_t dsp22, int32_t cond, const char *opcode) { + Format_2_2(a, cond, 0x6, dsp22); + asm_output("%s 0x%x", opcode, _nIns + dsp22 - 1); + } + + inline void Assembler::FBE (int32_t a, int32_t dsp22) { FBfcc(a, dsp22, 0x9, "fbe"); } + inline void Assembler::FBNE (int32_t a, int32_t dsp22) { FBfcc(a, dsp22, 0x1, "fbne"); } + inline void Assembler::FBUE (int32_t a, int32_t dsp22) { FBfcc(a, dsp22, 0xa, "fbue"); } + inline void Assembler::FBG (int32_t a, int32_t dsp22) { FBfcc(a, dsp22, 0x6, "fbg"); } + inline void Assembler::FBUG (int32_t a, int32_t dsp22) { FBfcc(a, dsp22, 0x5, "fbug"); } + inline void Assembler::FBGE (int32_t a, int32_t dsp22) { FBfcc(a, dsp22, 0xb, "fbge"); } + inline void Assembler::FBUGE(int32_t a, int32_t dsp22) { FBfcc(a, dsp22, 0xc, "fbuge"); } + inline void Assembler::FBL (int32_t a, int32_t dsp22) { FBfcc(a, dsp22, 0x4, "fbl"); } + inline void Assembler::FBUL (int32_t a, int32_t dsp22) { FBfcc(a, dsp22, 0x3, "fbul"); } + inline void Assembler::FBLE (int32_t a, int32_t dsp22) { FBfcc(a, dsp22, 0xd, "fble"); } + inline void Assembler::FBULE(int32_t a, int32_t dsp22) { FBfcc(a, dsp22, 0xe, "fbule"); } + + inline void Assembler::FCMPD(Register rs1, Register rs2) { + Format_3_9(2, 0, 0, 0x35, rs1, 0x52, rs2); + asm_output("fcmpd %s, %s", gpn(rs1), gpn(rs2)); + } + + inline void Assembler::FloatOperation + (Register rs1, Register rs2, Register rd, int32_t opf, const char *opcode) { + Format_3_8(2, rd, 0x34, rs1, opf, rs2); + if (rs1 != G0) { + asm_output("%s %s, %s, %s", opcode, gpn(rs1), gpn(rs2), gpn(rd)); + } else { + asm_output("%s %s, %s", opcode, gpn(rs2), gpn(rd)); + } + } + + inline void Assembler::FSUBD(Register rs1, Register rs2, Register rd) { + FloatOperation(rs1, rs2, rd, 0x46, "fsubd"); + } + inline void Assembler::FMULD(Register rs1, Register rs2, Register rd) { + FloatOperation(rs1, rs2, rd, 0x4a, "fsubd"); + } + inline void Assembler::FDTOI(Register rs2, Register rd) { + FloatOperation(G0, rs2, rd, 0xd2, "fdtoi"); + } + inline void Assembler::FDIVD(Register rs1, Register rs2, Register rd) { + FloatOperation(rs1, rs2, rd, 0x4e, "fdivd"); + } + inline void Assembler::FMOVD(Register rs2, Register rd) { + FloatOperation(G0, rs2, rd, 0x2, "fmovd"); + } + inline void Assembler::FNEGD(Register rs2, Register rd) { + FloatOperation(G0, rs2, rd, 0x6, "fnegd"); + } + inline void Assembler::FITOD(Register rs2, Register rd) { + FloatOperation(G0, rs2, rd, 0xc8, "fitod"); + } + + inline void Assembler::JMPL(Register rs1, Register rs2, Register rd) { + Format_3_1(2, rd, 0x38, rs1, 0, rs2); + asm_output("jmpl [%s + %s]", gpn(rs1), gpn(rs2)); + } + + inline void Assembler::JMPLI(Register rs1, int32_t simm13, Register rd) { + Format_3_1I(2, rd, 0x38, rs1, simm13); + asm_output("jmpl [%s + 0x%x]", gpn(rs1), simm13); + } + + inline void Assembler::LoadOperation + (Register rs1, Register rs2, Register rd, int32_t op3, const char* opcode) { + Format_3_1(3, rd, op3, rs1, 0, rs2); + asm_output("%s [%s + %s], %s", opcode, gpn(rs1), gpn(rs2), gpn(rd)); + } + + inline void Assembler::LoadOperationI + (Register rs1, int32_t simm13, Register rd, int32_t op3, const char* opcode) { + Format_3_1I(3, rd, op3, rs1, simm13); + asm_output("%s [%s + 0x%x], %s", opcode, gpn(rs1), simm13, gpn(rd)); + } + + inline void Assembler::LDF(Register rs1, Register rs2, Register rd) { + LoadOperation(rs1, rs2, rd, 0x20, "ldf"); + } + inline void Assembler::LDFI(Register rs1, int32_t simm13, Register rd) { + LoadOperationI(rs1, simm13, rd, 0x20, "ldf"); + } + + inline void Assembler::LDDF32(Register rs1, int32_t immI, Register rd) { + if (isIMM13(immI+4)) { + LDFI(rs1, immI+4, REGINC(rd)); + LDFI(rs1, immI, rd); + } else { + LDF(rs1, L0, REGINC(rd)); + SET32(immI+4, L0); + LDF(rs1, L0, rd); + SET32(immI, L0); + } + } + + inline void Assembler::LDUB(Register rs1, Register rs2, Register rd) { + LoadOperation(rs1, rs2, rd, 0x1, "ldub"); + } + inline void Assembler::LDUBI(Register rs1, int32_t simm13, Register rd) { + LoadOperationI(rs1, simm13, rd, 0x1, "ldub"); + } + + inline void Assembler::LDUB32(Register rs1, int32_t immI, Register rd) { + if (isIMM13(immI)) { + LDUBI(rs1, immI, rd); + } else { + LDUB(rs1, L0, rd); + SET32(immI, L0); + } + } + + inline void Assembler::LDUH(Register rs1, Register rs2, Register rd) { + LoadOperation(rs1, rs2, rd, 0x2, "lduh"); + } + inline void Assembler::LDUHI(Register rs1, int32_t simm13, Register rd) { + LoadOperationI(rs1, simm13, rd, 0x2, "lduh"); + } + + inline void Assembler::LDUH32(Register rs1, int32_t immI, Register rd) { + if (isIMM13(immI)) { + LDUHI(rs1, immI, rd); + } else { + LDUH(rs1, L0, rd); + SET32(immI, L0); + } + } + + inline void Assembler::LDSW(Register rs1, Register rs2, Register rd) { + LoadOperation(rs1, rs2, rd, 0x8, "ldsw"); + } + inline void Assembler::LDSWI(Register rs1, int32_t simm13, Register rd) { + LoadOperationI(rs1, simm13, rd, 0x8, "ldsw"); + } + + inline void Assembler::LDSW32(Register rs1, int32_t immI, Register rd) { + if (isIMM13(immI)) { + LDSWI(rs1, immI, rd); + } else { + LDSW(rs1, L0, rd); + SET32(immI, L0); + } + } + + inline void Assembler::MOVcc + (Register rs, int32_t cc2, int32_t cc1, int32_t cc0, Register rd, int32_t cond, const char *opcode) { + Format_4_2(rd, 0x2c, cc2, cond, cc1, cc0, rs); + asm_output("%s %s, %s", opcode, gpn(rs), gpn(rd)); + } + + inline void Assembler::MOVccI + (int32_t simm11, int32_t cc2, int32_t cc1, int32_t cc0, Register rd, int32_t cond, const char *opcode) { + Format_4_2I(rd, 0x2c, cc2, cond, cc1, cc0, simm11); + asm_output("%s 0x%x, %s", opcode, simm11, gpn(rd)); + } + + inline void Assembler::MOVE (Register rs, Register rd) { MOVcc(rs, 1, 0, 0, rd, 0x1, "move"); } + inline void Assembler::MOVNE (Register rs, Register rd) { MOVcc(rs, 1, 0, 0, rd, 0x9, "movne"); } + inline void Assembler::MOVL (Register rs, Register rd) { MOVcc(rs, 1, 0, 0, rd, 0x3, "movl"); } + inline void Assembler::MOVLE (Register rs, Register rd) { MOVcc(rs, 1, 0, 0, rd, 0x2, "movle"); } + inline void Assembler::MOVG (Register rs, Register rd) { MOVcc(rs, 1, 0, 0, rd, 0xa, "movg"); } + inline void Assembler::MOVGE (Register rs, Register rd) { MOVcc(rs, 1, 0, 0, rd, 0xb, "movge"); } + inline void Assembler::MOVLEU(Register rs, Register rd) { MOVcc(rs, 1, 0, 0, rd, 0x4, "movleu"); } + inline void Assembler::MOVGU (Register rs, Register rd) { MOVcc(rs, 1, 0, 0, rd, 0xc, "movgu"); } + inline void Assembler::MOVCC (Register rs, Register rd) { MOVcc(rs, 1, 0, 0, rd, 0xd, "movcc"); } + inline void Assembler::MOVCS (Register rs, Register rd) { MOVcc(rs, 1, 0, 0, rd, 0x5, "movcs"); } + inline void Assembler::MOVVC (Register rs, Register rd) { MOVcc(rs, 1, 0, 0, rd, 0xf, "movvc"); } + inline void Assembler::MOVEI (int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0x1, "move"); } + inline void Assembler::MOVFEI (int32_t simm11, Register rd) { MOVccI(simm11, 0, 0, 0, rd, 0x9, "movfe"); } + inline void Assembler::MOVNEI (int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0x9, "movne"); } + inline void Assembler::MOVLI (int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0x3, "movl"); } + inline void Assembler::MOVFLI (int32_t simm11, Register rd) { MOVccI(simm11, 0, 0, 0, rd, 0x4, "movfl"); } + inline void Assembler::MOVLEI (int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0x2, "movle"); } + inline void Assembler::MOVFLEI(int32_t simm11, Register rd) { MOVccI(simm11, 0, 0, 0, rd, 0xd, "movfle"); } + inline void Assembler::MOVGI (int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0xa, "movg"); } + inline void Assembler::MOVFGI (int32_t simm11, Register rd) { MOVccI(simm11, 0, 0, 0, rd, 0x6, "movfg"); } + inline void Assembler::MOVGEI (int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0xb, "movge"); } + inline void Assembler::MOVFGEI(int32_t simm11, Register rd) { MOVccI(simm11, 0, 0, 0, rd, 0xb, "movfge"); } + inline void Assembler::MOVLEUI(int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0x4, "movleu"); } + inline void Assembler::MOVGUI (int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0xc, "movgu"); } + inline void Assembler::MOVCCI (int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0xd, "movcc"); } + inline void Assembler::MOVCSI (int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0x5, "movcs"); } + inline void Assembler::MOVVSI (int32_t simm11, Register rd) { MOVccI(simm11, 1, 0, 0, rd, 0x7, "movvs"); } + + inline void Assembler::NOP() { + Format_2(0, 0x4, 0); + asm_output("nop"); + } + + inline void Assembler::RDY(Register rd) { + Format_3_1(2, rd, 0x28, G0, 0, G0); + asm_output("rdy %s", gpn(rd)); + } + + inline void Assembler::RESTORE(Register rs1, Register rs2, Register rd) { + Format_3_1(2, rd, 0x3d, rs1, 0, rs2); + asm_output("restore"); + } + + inline void Assembler::SAVE(Register rs1, Register rs2, Register rd) { + IntegerOperation(rs1, rs2, rd, 0x3c, "save"); + } + inline void Assembler::SAVEI(Register rs1, int32_t simm13, Register rd) { + IntegerOperationI(rs1, simm13, rd, 0x3c, "save"); + } + + inline void Assembler::SETHI(int32_t immI, Register rd) { + Format_2A(rd, 0x4, immI >> 10); + asm_output("sethi 0x%x, %s ! 0x%x", immI >> 10, gpn(rd), immI); + } + + inline void Assembler::SET32(int32_t immI, Register rd) { + if (isIMM13(immI)) { + ORI(G0, immI, rd); + } else { + ORI(rd, immI & 0x3FF, rd); + SETHI(immI, rd); + } + } + + inline void Assembler::ShiftOperation + (Register rs1, Register rs2, Register rd, int32_t op3, const char* opcode) { + Format_3_5(2, rd, op3, rs1, 0, rs2); + asm_output("%s %s, %s, %s", opcode, gpn(rs1), gpn(rs2), gpn(rd)); + } + + inline void Assembler::ShiftOperationI + (Register rs1, int32_t shcnt32, Register rd, int32_t op3, const char* opcode) { + Format_3_6(2, rd, op3, rs1, shcnt32); + asm_output("%s %s, %d, %s", opcode, gpn(rs1), shcnt32, gpn(rd)); + } + + inline void Assembler::SLL(Register rs1, Register rs2, Register rd) { + ShiftOperation(rs1, rs2, rd, 0x25, "sll"); + } + inline void Assembler::SRA(Register rs1, Register rs2, Register rd) { + ShiftOperation(rs1, rs2, rd, 0x27, "sra"); + } + inline void Assembler::SRAI(Register rs1, int32_t shcnt32, Register rd) { + ShiftOperationI(rs1, shcnt32, rd, 0x27, "sra"); + } + inline void Assembler::SRL(Register rs1, Register rs2, Register rd) { + ShiftOperation(rs1, rs2, rd, 0x26, "srl"); + } + + inline void Assembler::Store + (Register rd, Register rs1, Register rs2, int32_t op3, const char* opcode) { + Format_3_1(3, rd, op3, rs1, 0, rs2); + asm_output("%s %s, [%s + %s]", opcode, gpn(rd), gpn(rs1), gpn(rs2)); + } + + inline void Assembler::StoreI + (Register rd, int32_t simm13, Register rs1, int32_t op3, const char* opcode) { + Format_3_1I(3, rd, op3, rs1, simm13); + asm_output("%s %s, [%s + 0x%x]", opcode, gpn(rd), gpn(rs1), simm13); + } + + inline void Assembler::STF(Register rd, Register rs1, Register rs2) { + Store(rd, rs1, rs2, 0x24, "stf"); + } + inline void Assembler::STFI(Register rd, int32_t simm13, Register rs1) { + StoreI(rd, simm13, rs1, 0x24, "stf"); + } + + inline void Assembler::STF32(Register rd, int32_t immI, Register rs1) { + if (isIMM13(immI)) { + STFI(rd, immI, rs1); + } else { + STF(rd, L0, rs1); + SET32(immI, L0); + } + } + + inline void Assembler::STDF32(Register rd, int32_t immI, Register rs1) { + if (isIMM13(immI+4)) { + STFI(REGINC(rd), immI+4, rs1);; + STFI(rd, immI, rs1); + } else { + STF(REGINC(rd), L0, rs1); + SET32(immI+4, L0); + STF(rd, L0, rs1); + SET32(immI, L0); + } + } + + inline void Assembler::STW(Register rd, Register rs1, Register rs2) { + Store(rd, rs1, rs2, 0x4, "st"); + } + inline void Assembler::STWI(Register rd, int32_t simm13, Register rs1) { + StoreI(rd, simm13, rs1, 0x4, "st"); + } + + inline void Assembler::STW32(Register rd, int32_t immI, Register rs1) { + if (isIMM13(immI)) { + STWI(rd, immI, rs1); + } else { + STW(rd, L0, rs1); + SET32(immI, L0); + } + } + + inline void Assembler::STB(Register rd, Register rs1, Register rs2) { + Store(rd, rs1, rs2, 0x5, "stb"); + } + inline void Assembler::STBI(Register rd, int32_t simm13, Register rs1) { + StoreI(rd, simm13, rs1, 0x5, "stb"); + } + + inline void Assembler::STB32(Register rd, int32_t immI, Register rs1) { + if (isIMM13(immI)) { + STBI(rd, immI, rs1); + } else { + STB(rd, L0, rs1); + SET32(immI, L0); + } + } + + // general Assemble + inline void Assembler::JMP_long_nocheck(int32_t t) { + NOP(); + JMPL(G0, G2, G0); + ORI(G2, t & 0x3FF, G2); + SETHI(t, G2); + } + + inline void Assembler::JMP_long(int32_t t) { + underrunProtect(16); + JMP_long_nocheck(t); + } + + inline void Assembler::JMP_long_placeholder() { + JMP_long(0); + } + + inline int32_t Assembler::JCC(void *t) { + underrunProtect(32); + int32_t tt = ((intptr_t)t - (intptr_t)_nIns + 8) >> 2; + if( !(isIMM22(tt)) ) { + NOP(); + JMPL(G0, G2, G0); + SET32((intptr_t)t, G2); + NOP(); + BA(0, 5); + tt = 4; + } + NOP(); + return tt; + } + + void Assembler::JMP(void *t) { + if (!t) { + JMP_long_placeholder(); + } else { + int32_t tt = JCC(t); + BA(0, tt); + } + } + + void Assembler::MR(Register rd, Register rs) { + underrunProtect(4); + ORI(rs, 0, rd); + } + void Assembler::nInit(AvmCore* core) { has_cmov = true; @@ -97,7 +545,7 @@ namespace nanojit verbose_only( if (_logc->lcbits & LC_Native) { - outputf(" %p:",_nIns); + outputf(" 0x%x:",_nIns); outputf(" patch entry:"); }) NIns *patchEntry = _nIns; @@ -173,7 +621,7 @@ namespace nanojit NanoAssert(ins->isop(LIR_callv) || ins->isop(LIR_callp) || ins->isop(LIR_calld)); verbose_only(if (_logc->lcbits & LC_Native) - outputf(" %p:", _nIns); + outputf(" 0x%x:", _nIns); ) bool indirect = ci->isIndirect(); if (!indirect) { @@ -182,10 +630,10 @@ namespace nanojit else { argc--; Register r = findSpecificRegFor(ins->arg(argc), I0); - JMPL(G0, I0, 15); + JMPL(G0, I0, O7); } - uint32_t GPRIndex = O0; + Register GPRIndex = O0; uint32_t offset = kLinkageAreaSize; // start of parameters stack postion. for(int i=0; iarg(j), FpRegs); - GPRIndex += 2; - offset += 8; underrunProtect(48); // We might be calling a varargs function. // So, make sure the GPR's are also loaded with // the value, or the stack contains it. - if (GPRIndex-2 <= O5) { - LDSW32(SP, offset-8, (Register)(GPRIndex-2)); + if (REGNUM(GPRIndex) <= REGNUM(O5)) { + LDSW32(SP, offset, GPRIndex); } - if (GPRIndex-1 <= O5) { - LDSW32(SP, offset-4, (Register)(GPRIndex-1)); + GPRIndex = REGINC(GPRIndex); + if (REGNUM(GPRIndex) <= REGNUM(O5)) { + LDSW32(SP, offset+4, GPRIndex); } - STDF32(r, offset-8, SP); + GPRIndex = REGINC(GPRIndex); + STDF32(r, offset, SP); + offset += 8; } else { - if (GPRIndex > O5) { + if (REGNUM(GPRIndex) > REGNUM(O5)) { underrunProtect(12); Register r = findRegFor(ins->arg(j), GpRegs); STW32(r, offset, SP); } else { - Register r = findSpecificRegFor(ins->arg(j), (Register)GPRIndex); + Register r = findSpecificRegFor(ins->arg(j), GPRIndex); } - GPRIndex++; + GPRIndex = REGINC(GPRIndex); offset += 4; } } @@ -225,11 +674,11 @@ namespace nanojit Register Assembler::nRegisterAllocFromSet(RegisterMask set) { // need to implement faster way - int i=0; - while (!(set & rmask((Register)i))) - i ++; - _allocator.free &= ~rmask((Register)i); - return (Register) i; + Register i = G0; + while (!(set & rmask(i))) + i = REGINC(i); + _allocator.free &= ~rmask(i); + return i; } void Assembler::nRegisterResetAll(RegAlloc& a) @@ -598,15 +1047,15 @@ namespace nanojit LOpcode condop = ins->opcode(); NanoAssert(isCmpDOpcode(condop)); if (condop == LIR_eqd) - MOVFEI(1, 0, 0, 0, r); + MOVFEI(1, r); else if (condop == LIR_led) - MOVFLEI(1, 0, 0, 0, r); + MOVFLEI(1, r); else if (condop == LIR_ltd) - MOVFLI(1, 0, 0, 0, r); + MOVFLI(1, r); else if (condop == LIR_ged) - MOVFGEI(1, 0, 0, 0, r); + MOVFGEI(1, r); else // if (condop == LIR_gtd) - MOVFGI(1, 0, 0, 0, r); + MOVFGI(1, r); ORI(G0, 0, r); asm_cmpd(ins); } @@ -619,23 +1068,23 @@ namespace nanojit Register r = deprecated_prepResultReg(ins, AllowableFlagRegs); if (op == LIR_eqi) - MOVEI(1, 1, 0, 0, r); + MOVEI(1, r); else if (op == LIR_lti) - MOVLI(1, 1, 0, 0, r); + MOVLI(1, r); else if (op == LIR_lei) - MOVLEI(1, 1, 0, 0, r); + MOVLEI(1, r); else if (op == LIR_gti) - MOVGI(1, 1, 0, 0, r); + MOVGI(1, r); else if (op == LIR_gei) - MOVGEI(1, 1, 0, 0, r); + MOVGEI(1, r); else if (op == LIR_ltui) - MOVCSI(1, 1, 0, 0, r); + MOVCSI(1, r); else if (op == LIR_leui) - MOVLEUI(1, 1, 0, 0, r); + MOVLEUI(1, r); else if (op == LIR_gtui) - MOVGUI(1, 1, 0, 0, r); + MOVGUI(1, r); else // if (op == LIR_geui) - MOVCCI(1, 1, 0, 0, r); + MOVCCI(1, r); ORI(G0, 0, r); asm_cmp(ins); } @@ -803,15 +1252,15 @@ namespace nanojit if (op == LIR_cmovi) { switch (condval->opcode()) { // note that these are all opposites... - case LIR_eqi: MOVNE (iffalsereg, 1, 0, 0, rr); break; - case LIR_lti: MOVGE (iffalsereg, 1, 0, 0, rr); break; - case LIR_lei: MOVG (iffalsereg, 1, 0, 0, rr); break; - case LIR_gti: MOVLE (iffalsereg, 1, 0, 0, rr); break; - case LIR_gei: MOVL (iffalsereg, 1, 0, 0, rr); break; - case LIR_ltui: MOVCC (iffalsereg, 1, 0, 0, rr); break; - case LIR_leui: MOVGU (iffalsereg, 1, 0, 0, rr); break; - case LIR_gtui: MOVLEU(iffalsereg, 1, 0, 0, rr); break; - case LIR_geui: MOVCS (iffalsereg, 1, 0, 0, rr); break; + case LIR_eqi: MOVNE (iffalsereg, rr); break; + case LIR_lti: MOVGE (iffalsereg, rr); break; + case LIR_lei: MOVG (iffalsereg, rr); break; + case LIR_gti: MOVLE (iffalsereg, rr); break; + case LIR_gei: MOVL (iffalsereg, rr); break; + case LIR_ltui: MOVCC (iffalsereg, rr); break; + case LIR_leui: MOVGU (iffalsereg, rr); break; + case LIR_gtui: MOVLEU(iffalsereg, rr); break; + case LIR_geui: MOVCS (iffalsereg, rr); break; debug_only( default: NanoAssert(0); break; ) } } diff --git a/js/src/nanojit/NativeSparc.h b/js/src/nanojit/NativeSparc.h index 64243b7ef20c..d98f7416daf9 100644 --- a/js/src/nanojit/NativeSparc.h +++ b/js/src/nanojit/NativeSparc.h @@ -22,7 +22,8 @@ * * Contributor(s): * Adobe AS3 Team - * leon.sha@sun.com + * leon.sha@oracle.com + * ginn.chen@oracle.com * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -42,6 +43,8 @@ #ifndef __nanojit_NativeSparc__ #define __nanojit_NativeSparc__ +#include "NativeCommon.h" + #define count_instr() #define count_ret() #define count_push() @@ -86,7 +89,6 @@ namespace nanojit const size_t LARGEST_BRANCH_PATCH = 2 * sizeof(NIns); // These are used as register numbers in various parts of the code - typedef uint32_t Register; static const Register G0 = { 0 }, G1 = { 1 }, @@ -127,51 +129,48 @@ namespace nanojit SP = O6, FP = I6, - F0 = { 0 }, - F1 = { 1 }, - F2 = { 2 }, - F3 = { 3 }, - F4 = { 4 }, - F5 = { 5 }, - F6 = { 6 }, - F7 = { 7 }, - F8 = { 8 }, - F9 = { 9 }, - F10 = { 10 }, - F11 = { 11 }, - F12 = { 12 }, - F13 = { 13 }, - F14 = { 14 }, - F15 = { 15 }, - F16 = { 16 }, - F17 = { 17 }, - F18 = { 18 }, - F19 = { 19 }, - F20 = { 20 }, - F21 = { 21 }, - F22 = { 22 }, - F23 = { 23 }, - F24 = { 24 }, - F25 = { 25 }, - F26 = { 26 }, - F27 = { 27 }, - F28 = { 28 }, - F29 = { 29 }, - F30 = { 30 }, - F31 = { 31 }, + F0 = { 32 }, + F1 = { 33 }, + F2 = { 34 }, + F3 = { 35 }, + F4 = { 36 }, + F5 = { 37 }, + F6 = { 38 }, + F7 = { 39 }, + F8 = { 40 }, + F9 = { 41 }, + F10 = { 42 }, + F11 = { 43 }, + F12 = { 44 }, + F13 = { 45 }, + F14 = { 46 }, + F15 = { 47 }, + F16 = { 48 }, + F17 = { 49 }, + F18 = { 50 }, + F19 = { 51 }, + F20 = { 52 }, + F21 = { 53 }, + F22 = { 54 }, + F23 = { 55 }, + F24 = { 56 }, + F25 = { 57 }, + F26 = { 58 }, + F27 = { 59 }, + F28 = { 60 }, + F29 = { 61 }, + F30 = { 62 }, + F31 = { 63 }, // helpers FRAME_PTR = G4, - deprecated_UnknownReg = { 30 }; // XXX: remove eventually, see bug 538924 + deprecated_UnknownReg = { 64 }; // XXX: remove eventually, see bug 538924 static const uint32_t FirstRegNum = 0; - static const uint32_t LastRegNum = 29; + static const uint32_t LastRegNum = 63; } -#define NJ_USE_UINT32_REGISTER 1 -#include "NativeCommon.h" - namespace nanojit { // We only use 32 registers to be managed. @@ -179,21 +178,21 @@ namespace nanojit // And other unmanaged registers we can use them directly. // The registers that can be used directly are G0-G4, L0, L2, L4, L6 // SP, FP, F8-F12, F24-F28 - typedef int RegisterMask; -#define _rmask_(r) (1<<(r)) - + typedef uint64_t RegisterMask; +#define _rmask_(r) ((RegisterMask)1<<(REGNUM(r))) +#define _reg_(r) (REGNUM(r) & 0x1F) // Assembler::savedRegs[] is not needed for sparc because the // registers are already saved automatically by "save" instruction. static const int NumSavedRegs = 0; - static const RegisterMask SavedRegs = 1<_address) - ((int)_nIns) + 4; \ - int i = 0x40000000 | ((offset >> 2) & 0x3FFFFFFF); \ - IMM32(i); \ - asm_output("call %s",(c->_name)); \ - } while (0) - -#define Format_2_1(rd, op2, imm22) do { \ - int i = rd << 25 | op2 << 22 | (imm22 & 0x3FFFFF); \ - IMM32(i); \ - } while (0) - -#define Format_2_2(a, cond, op2, disp22) \ - Format_2_1((a & 0x1) << 4 | (cond & 0xF), op2, disp22) - -#define Format_2_3(a, cond, op2, cc1, cc0, p, disp19) \ - Format_2_2(a, cond, op2, (cc1 & 0x1) << 21 | (cc0 & 0x1) << 20 | (p & 0x1) << 19 | (disp19 & 0x7FFFF)) - -#define Format_2_4(a, rcond, op2, d16hi, p, rs1, d16lo) \ - Format_2_2(a, (rcond & 0x7), op2, (d16hi & 0x3) << 20 | (p & 0x1) << 19 | rs1 << 14 | (d16lo & 0x3FFF)) - -#define Format_3(op1, rd, op3, bits19) do { \ - int i = op1 << 30 | rd << 25 | op3 << 19 | (bits19 & 0x7FFFF); \ - IMM32(i); \ - } while (0) - -#define Format_3_1(op1, rd, op3, rs1, bit8, rs2) \ - Format_3(op1, rd, op3, rs1 << 14 | (bit8 & 0xFF) << 5 | rs2) - -#define Format_3_1I(op1, rd, op3, rs1, simm13) \ - Format_3(op1, rd, op3, rs1 << 14 | 1 << 13 | (simm13 & 0x1FFF)) - -#define Format_3_2(op1, rd, op3, rs1, rcond, rs2) \ - Format_3(op1, rd, op3, rs1 << 14 | (rcond & 0x3) << 10 | rs2) - -#define Format_3_2I(op1, rd, op3, rs1, rcond, simm10) \ - Format_3(op1, rd, op3, rs1 << 14 | 1 << 13 | (rcond & 0x3) << 10 | (simm10 & 0x1FFF)) - -#define Format_3_3(op1, rd, op3, rs1, cmask, mmask) \ - Format_3(op1, rd, op3, rs1 << 14 | 1 << 13 | (cmask & 0x7) << 5 | (mmask & 0xF)) - -#define Format_3_4(op1, rd, op3, bits19) \ - Format_3(op1, rd, op3, bits19) - -#define Format_3_5(op1, rd, op3, rs1, x, rs2) \ - Format_3(op1, rd, op3, rs1 << 14 | (x & 0x1) << 12 | rs2) - -#define Format_3_6(op1, rd, op3, rs1, shcnt32) \ - Format_3(op1, rd, op3, rs1 << 14 | 1 << 13 | (shcnt32 & 0x3F)) - -#define Format_3_7(op1, rd, op3, rs1, shcnt64) \ - Format_3(op1, rd, op3, rs1 << 14 | 1 << 13 | 1 << 12 | (shcnt64 & 0x7F)) - -#define Format_3_8(op1, rd, op3, rs1, bits9, rs2) \ - Format_3(op1, rd, op3, rs1 << 14 | (bits9 & 0x1FF) << 5 | rs2) - -#define Format_3_9(op1, cc1, cc0, op3, rs1, bits9, rs2) \ - Format_3(op1, (cc1 & 0x1) << 1 | (cc0 & 0x1), op3, rs1 << 14 | (bits9 & 0x1FF) << 5 | rs2) - -#define Format_4_1(rd, op3, rs1, cc1, cc0, rs2) \ - Format_3(2, rd, op3, rs1 << 14 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | rs2) - -#define Format_4_1I(rd, op3, rs1, cc1, cc0, simm11) \ - Format_3(2, rd, op3, rs1 << 14 | (cc1 & 0x1) << 12 | 1 << 13 |(cc0 & 0x1) << 11 | (simm11 & 0x7FF)) - -#define Format_4_2(rd, op3, cc2, cond, cc1, cc0, rs2) \ - Format_3(2, rd, op3, (cc2 & 0x1) << 18 | (cond & 0xF) << 14 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | rs2) - -#define Format_4_2I(rd, op3, cc2, cond, cc1, cc0, simm11) \ - Format_3(2, rd, op3, (cc2 & 0x1) << 18 | (cond & 0xF) << 14 | 1 << 13 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | (simm11 & 0x7FF)) - -#define Format_4_3(rd, op3, rs1, cc1, cc0, swap_trap) \ - Format_3(2, rd, op3, rs1 << 14 | 1 << 13 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | (swap_trap & 0x7F)) - -#define Format_4_4(rd, op3, rs1, rcond, opf_low, rs2) \ - Format_3(2, rd, op3, rs1 << 14 | (rcond & 0x7) << 10 | (opf_low & 0x1F) << 5 | rs2) - -#define Format_4_5(rd, op3, cond, opf_cc, opf_low, rs2) \ - Format_3(2, rd, op3, (cond & 0xF) << 14 | (opf_cc & 0x7) << 11 | (opf_low & 0x3F) << 5 | rs2) - -#define ADDCC(rs1, rs2, rd) \ - do { \ - Format_3_1(2, rd, 0x10, rs1, 0, rs2); \ - asm_output("addcc %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ - } while (0) - -#define ADD(rs1, rs2, rd) \ - do { \ - Format_3_1(2, rd, 0, rs1, 0, rs2); \ - asm_output("add %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ - } while (0) - -#define AND(rs1, rs2, rd) \ - do { \ - Format_3_1(2, rd, 0x1, rs1, 0, rs2); \ - asm_output("and %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ - } while (0) - -#define BA(a, dsp22) \ - do { \ - Format_2_2(a, 0x8, 0x2, dsp22); \ - asm_output("ba %p", _nIns + dsp22 - 1); \ - } while (0) - -#define BE(a, dsp22) \ - do { \ - Format_2_2(a, 0x1, 0x2, dsp22); \ - asm_output("be %p", _nIns + dsp22 - 1); \ - } while (0) - -#define BG(a, dsp22) \ - do { \ - Format_2_2(a, 0xA, 0x2, dsp22); \ - asm_output("bg %p", _nIns + dsp22 - 1); \ - } while (0) - -#define BGU(a, dsp22) \ - do { \ - Format_2_2(a, 0xC, 0x2, dsp22); \ - asm_output("bgu %p", _nIns + dsp22 - 1); \ - } while (0) - -#define BGE(a, dsp22) \ - do { \ - Format_2_2(a, 0xB, 0x2, dsp22); \ - asm_output("bge %p", _nIns + dsp22 - 1); \ - } while (0) - -#define BL(a, dsp22) \ - do { \ - Format_2_2(a, 0x3, 0x2, dsp22); \ - asm_output("bl %p", _nIns + dsp22 - 1); \ - } while (0) - -#define BLE(a, dsp22) \ - do { \ - Format_2_2(a, 0x2, 0x2, dsp22); \ - asm_output("ble %p", _nIns + dsp22 - 1); \ - } while (0) - -#define BLEU(a, dsp22) \ - do { \ - Format_2_2(a, 0x4, 0x2, dsp22); \ - asm_output("bleu %p", _nIns + dsp22 - 1); \ - } while (0) - -#define BCC(a, dsp22) \ - do { \ - Format_2_2(a, 0xd, 0x2, dsp22); \ - asm_output("bcc %p", _nIns + dsp22 - 1); \ - } while (0) - -#define BCS(a, dsp22) \ - do { \ - Format_2_2(a, 0x5, 0x2, dsp22); \ - asm_output("bcs %p", _nIns + dsp22 - 1); \ - } while (0) - -#define BVC(a, dsp22) \ - do { \ - Format_2_2(a, 0xf, 0x2, dsp22); \ - asm_output("bvc %p", _nIns + dsp22 - 1); \ - } while (0) - -#define BVS(a, dsp22) \ - do { \ - Format_2_2(a, 0x7, 0x2, dsp22); \ - asm_output("bvc %p", _nIns + dsp22 - 1); \ - } while (0) - -#define BNE(a, dsp22) \ - do { \ - Format_2_2(a, 0x9, 0x2, dsp22); \ - asm_output("bne %p", _nIns + dsp22 - 1); \ - } while (0) - -#define FABSS(rs2, rd) \ - do { \ - Format_3_8(2, rd, 0x34, 0, 0x9, rs2); \ - asm_output("fabs %s, %s", gpn(rs2+32), gpn(rd+32)); \ - } while (0) - -#define FADDD(rs1, rs2, rd) \ - do { \ - Format_3_8(2, rd, 0x34, rs1, 0x42, rs2); \ - asm_output("faddd %s, %s, %s", gpn(rs1+32), gpn(rs2+32), gpn(rd+32)); \ - } while (0) - -#define FBE(a, dsp22) \ - do { \ - Format_2_2(a, 0x9, 0x6, dsp22); \ - asm_output("fbe %p", _nIns + dsp22 - 1); \ - } while(0) - -#define FBNE(a, dsp22) \ - do { \ - Format_2_2(a, 0x1, 0x6, dsp22); \ - asm_output("fbne %p", _nIns + dsp22 - 1); \ - } while(0) - -#define FBUE(a, dsp22) \ - do { \ - Format_2_2(a, 0xA, 0x6, dsp22); \ - asm_output("fbue %p", _nIns + dsp22 - 1); \ - } while(0) - -#define FBG(a, dsp22) \ - do { \ - Format_2_2(a, 0x6, 0x6, dsp22); \ - asm_output("fng %p", _nIns + dsp22 - 1); \ - } while(0) - -#define FBUG(a, dsp22) \ - do { \ - Format_2_2(a, 0x5, 0x6, dsp22); \ - asm_output("fbug %p", _nIns + dsp22 - 1); \ - } while(0) - -#define FBGE(a, dsp22) \ - do { \ - Format_2_2(a, 0xB, 0x6, dsp22); \ - asm_output("fbge %p", _nIns + dsp22 - 1); \ - } while(0) - -#define FBUGE(a, dsp22) \ - do { \ - Format_2_2(a, 0xC, 0x6, dsp22); \ - asm_output("fbuge %p", _nIns + dsp22 - 1); \ - } while(0) - -#define FBL(a, dsp22) \ - do { \ - Format_2_2(a, 0x4, 0x6, dsp22); \ - asm_output("fbl %p", _nIns + dsp22 - 1); \ - } while(0) - -#define FBUL(a, dsp22) \ - do { \ - Format_2_2(a, 0x3, 0x6, dsp22); \ - asm_output("fbl %p", _nIns + dsp22 - 1); \ - } while(0) - -#define FBLE(a, dsp22) \ - do { \ - Format_2_2(a, 0xD, 0x6, dsp22); \ - asm_output("fble %p", _nIns + dsp22 - 1); \ - } while(0) - -#define FBULE(a, dsp22) \ - do { \ - Format_2_2(a, 0xE, 0x6, dsp22); \ - asm_output("fbule %p", _nIns + dsp22 - 1); \ - } while(0) - -#define FCMPD(rs1, rs2) \ - do { \ - Format_3_9(2, 0, 0, 0x35, rs1, 0x52, rs2); \ - asm_output("fcmpd %s, %s", gpn(rs1+32), gpn(rs2+32)); \ - } while (0) - -#define FSUBD(rs1, rs2, rd) \ - do { \ - Format_3_8(2, rd, 0x34, rs1, 0x46, rs2); \ - asm_output("fsubd %s, %s, %s", gpn(rs1+32), gpn(rs2+32), gpn(rd+32)); \ - } while (0) - -#define FMULD(rs1, rs2, rd) \ - do { \ - Format_3_8(2, rd, 0x34, rs1, 0x4a, rs2); \ - asm_output("fmuld %s, %s, %s", gpn(rs1+32), gpn(rs2+32), gpn(rd+32)); \ - } while (0) - -#define FDTOI(rs2, rd) \ - do { \ - Format_3_8(2, rd, 0x34, 0, 0xd2, rs2); \ - asm_output("fdtoi %s, %s", gpn(rs2+32), gpn(rd+32)); \ - } while (0) - -#define FDIVD(rs1, rs2, rd) \ - do { \ - Format_3_8(2, rd, 0x34, rs1, 0x4e, rs2); \ - asm_output("fdivd %s, %s, %s", gpn(rs1+32), gpn(rs2+32), gpn(rd+32)); \ - } while (0) - -#define FMOVD(rs2, rd) \ - do { \ - Format_3_8(2, rd, 0x34, 0, 0x2, rs2); \ - asm_output("fmovd %s, %s", gpn(rs2+32), gpn(rd+32)); \ - } while (0) - -#define FNEGD(rs2, rd) \ - do { \ - Format_3_8(2, rd, 0x34, 0, 0x6, rs2); \ - asm_output("fnegd %s, %s", gpn(rs2+32), gpn(rd+32)); \ - } while (0) - -#define FITOD(rs2, rd) \ - do { \ - Format_3_8(2, rd, 0x34, 0, 0xc8, rs2); \ - asm_output("fitod %s, %s", gpn(rs2+32), gpn(rd+32)); \ - } while (0) - -#define JMPL(rs1, rs2, rd) \ - do { \ - Format_3_1(2, rd, 0x38, rs1, 0, rs2); \ - asm_output("jmpl [%s + %s]", gpn(rs1), gpn(rs2)); \ - } while (0) - -#define JMPLI(rs1, simm13, rd) \ - do { \ - Format_3_1I(2, rd, 0x38, rs1, simm13); \ - asm_output("jmpl [%s + %d]", gpn(rs1), simm13); \ - } while (0) - -#define LDF(rs1, rs2, rd) \ - do { \ - Format_3_1(3, rd, 0x20, rs1, 0, rs2); \ - asm_output("ld [%s + %s], %s", gpn(rs1), gpn(rs2), gpn(rd+32)); \ - } while (0) - -#define LDFI(rs1, simm13, rd) \ - do { \ - Format_3_1I(3, rd, 0x20, rs1, simm13); \ - asm_output("ld [%s + %d], %s", gpn(rs1), simm13, gpn(rd+32)); \ - } while (0) - -#define LDUB(rs1, rs2, rd) \ - do { \ - Format_3_1(3, rd, 0x1, rs1, 0, rs2); \ - asm_output("ld [%s + %s], %s", gpn(rs1), gpn(rs2), gpn(rd)); \ - } while (0) - -#define LDUBI(rs1, simm13, rd) \ - do { \ - Format_3_1I(3, rd, 0x1, rs1, simm13); \ - asm_output("ld [%s + %d], %s", gpn(rs1), simm13, gpn(rd)); \ - } while (0) - -#define LDUH(rs1, rs2, rd) \ - do { \ - Format_3_1(3, rd, 0x2, rs1, 0, rs2); \ - asm_output("ld [%s + %s], %s", gpn(rs1), gpn(rs2), gpn(rd)); \ - } while (0) - -#define LDUHI(rs1, simm13, rd) \ - do { \ - Format_3_1I(3, rd, 0x2, rs1, simm13); \ - asm_output("ld [%s + %d], %s", gpn(rs1), simm13, gpn(rd)); \ - } while (0) - -#define LDSW(rs1, rs2, rd) \ - do { \ - Format_3_1(3, rd, 0x8, rs1, 0, rs2); \ - asm_output("ld [%s + %s], %s", gpn(rs1), gpn(rs2), gpn(rd)); \ - } while (0) - -#define LDSWI(rs1, simm13, rd) \ - do { \ - Format_3_1I(3, rd, 0x8, rs1, simm13); \ - asm_output("ld [%s + %d], %s", gpn(rs1), simm13, gpn(rd)); \ - } while (0) - -#define MOVE(rs, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2(rd, 0x2c, cc2, 1, cc1, cc0, rs); \ - asm_output("move %s, %s", gpn(rs), gpn(rd)); \ - } while (0) - -#define MOVNE(rs, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2(rd, 0x2c, cc2, 9, cc1, cc0, rs); \ - asm_output("movne %s, %s", gpn(rs), gpn(rd)); \ - } while (0) - -#define MOVL(rs, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2(rd, 0x2c, cc2, 3, cc1, cc0, rs); \ - asm_output("movl %s, %s", gpn(rs), gpn(rd)); \ - } while (0) - -#define MOVLE(rs, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2(rd, 0x2c, cc2, 2, cc1, cc0, rs); \ - asm_output("movle %s, %s", gpn(rs), gpn(rd)); \ - } while (0) - -#define MOVG(rs, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2(rd, 0x2c, cc2, 0xa, cc1, cc0, rs); \ - asm_output("movg %s, %s", gpn(rs), gpn(rd)); \ - } while (0) - -#define MOVGE(rs, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2(rd, 0x2c, cc2, 0xb, cc1, cc0, rs); \ - asm_output("movge %s, %s", gpn(rs), gpn(rd)); \ - } while (0) - -#define MOVCS(rs, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2(rd, 0x2c, cc2, 5, cc1, cc0, rs); \ - asm_output("movcs %s, %s", gpn(rs), gpn(rd)); \ - } while (0) - -#define MOVLEU(rs, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2(rd, 0x2c, cc2, 4, cc1, cc0, rs); \ - asm_output("movleu %s, %s", gpn(rs), gpn(rd)); \ - } while (0) - -#define MOVGU(rs, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2(rd, 0x2c, cc2, 0xc, cc1, cc0, rs); \ - asm_output("movgu %s, %s", gpn(rs), gpn(rd)); \ - } while (0) - -#define MOVCC(rs, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2(rd, 0x2c, cc2, 0xd, cc1, cc0, rs); \ - asm_output("movcc %s, %s", gpn(rs), gpn(rd)); \ - } while (0) - -#define MOVVC(rs, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2(rd, 0x2c, cc2, 0xf, cc1, cc0, rs); \ - asm_output("movvc %s, %s", gpn(rs), gpn(rd)); \ - } while (0) - -#define MOVEI(simm11, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2I(rd, 0x2c, cc2, 1, cc1, cc0, simm11); \ - asm_output("move %d, %s", simm11, gpn(rd)); \ - } while (0) - -#define MOVFEI(simm11, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2I(rd, 0x2c, cc2, 9, cc1, cc0, simm11); \ - asm_output("move %d, %s", simm11, gpn(rd)); \ - } while (0) - -#define MOVNEI(simm11, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2I(rd, 0x2c, cc2, 9, cc1, cc0, simm11); \ - asm_output("move %d, %s", simm11, gpn(rd)); \ - } while (0) - -#define MOVLI(simm11, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2I(rd, 0x2c, cc2, 3, cc1, cc0, simm11); \ - asm_output("move %d, %s", simm11, gpn(rd)); \ - } while (0) - -#define MOVFLI(simm11, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2I(rd, 0x2c, cc2, 4, cc1, cc0, simm11); \ - asm_output("move %d, %s", simm11, gpn(rd)); \ - } while (0) - -#define MOVLEI(simm11, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2I(rd, 0x2c, cc2, 2, cc1, cc0, simm11); \ - asm_output("movle %d, %s", simm11, gpn(rd)); \ - } while (0) - -#define MOVFLEI(simm11, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2I(rd, 0x2c, cc2, 0xd, cc1, cc0, simm11); \ - asm_output("movle %d, %s", simm11, gpn(rd)); \ - } while (0) - -#define MOVGI(simm11, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2I(rd, 0x2c, cc2, 0xa, cc1, cc0, simm11); \ - asm_output("movg %d, %s", simm11, gpn(rd)); \ - } while (0) - -#define MOVFGI(simm11, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2I(rd, 0x2c, cc2, 6, cc1, cc0, simm11); \ - asm_output("movg %d, %s", simm11, gpn(rd)); \ - } while (0) - -#define MOVGEI(simm11, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2I(rd, 0x2c, cc2, 0xb, cc1, cc0, simm11); \ - asm_output("movge %d, %s", simm11, gpn(rd)); \ - } while (0) - -#define MOVFGEI(simm11, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2I(rd, 0x2c, cc2, 0xb, cc1, cc0, simm11); \ - asm_output("movge %d, %s", simm11, gpn(rd)); \ - } while (0) - -#define MOVLEUI(simm11, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2I(rd, 0x2c, cc2, 4, cc1, cc0, simm11); \ - asm_output("movleu %d, %s", simm11, gpn(rd)); \ - } while (0) - -#define MOVGUI(simm11, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2I(rd, 0x2c, cc2, 0xc, cc1, cc0, simm11); \ - asm_output("movgu %d, %s", simm11, gpn(rd)); \ - } while (0) - -#define MOVCCI(simm11, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2I(rd, 0x2c, cc2, 0xd, cc1, cc0, simm11); \ - asm_output("movcc %d, %s", simm11, gpn(rd)); \ - } while (0) - -#define MOVCSI(simm11, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2I(rd, 0x2c, cc2, 0x5, cc1, cc0, simm11); \ - asm_output("movcs %d, %s", simm11, gpn(rd)); \ - } while (0) - -#define MOVVSI(simm11, cc2, cc1, cc0, rd) \ - do { \ - Format_4_2I(rd, 0x2c, cc2, 7, cc1, cc0, simm11); \ - asm_output("movvs %d, %s", simm11, gpn(rd)); \ - } while (0) - -#define SMULCC(rs1, rs2, rd) \ - do { \ - Format_3_1(2, rd, 0x1b, rs1, 0, rs2); \ - asm_output("smulcc %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ - } while (0) - -#define NOP() \ - do { \ - Format_2_1(0, 0x4, 0); \ - asm_output("nop"); \ - } while (0) - -#define ORI(rs1, simm13, rd) \ - do { \ - Format_3_1I(2, rd, 0x2, rs1, simm13); \ - asm_output("or %s, %d, %s", gpn(rs1), simm13, gpn(rd)); \ - } while (0) - -#define OR(rs1, rs2, rd) \ - do { \ - Format_3_1(2, rd, 0x2, rs1, 0, rs2); \ - asm_output("or %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ - } while (0) - -#define ORN(rs1, rs2, rd) \ - do { \ - Format_3_1(2, rd, 0x6, rs1, 0, rs2); \ - asm_output("orn %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ - } while (0) - -#define ANDCC(rs1, rs2, rd) \ - do { \ - Format_3_1(2, rd, 0x11, rs1, 0, rs2); \ - asm_output("andcc %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ - } while (0) - -#define RDY(rd) \ - do { \ - Format_3_1(2, rd, 0x28, 0, 0, 0); \ - asm_output("rdy %s", gpn(rd)); \ - } while (0) - -#define RESTORE(rs1, rs2, rd) \ - do { \ - Format_3_1(2, rd, 0x3D, rs1, 0, rs2); \ - asm_output("restore"); \ - } while (0) - -#define SAVEI(rs1, simm13, rd) \ - do { \ - Format_3_1I(2, rd, 0x3C, rs1, simm13); \ - asm_output("save %s, %d, %s", gpn(rs1), simm13, gpn(rd)); \ - } while (0) - -#define SAVE(rs1, rs2, rd) \ - do { \ - Format_3_1(2, rd, 0x3C, rs1, 0, rs2); \ - asm_output("save %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ - } while (0) - -#define SETHI(imm22, rd) \ - do { \ - Format_2_1(rd, 0x4, (imm22 >> 10)); \ - asm_output("sethi %p, %s", imm22, gpn(rd)); \ - } while (0) - -#define SLL(rs1, rs2, rd) \ - do { \ - Format_3_5(2, rd, 0x25, rs1, 0, rs2); \ - asm_output("sll %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ - } while (0) - -#define SRA(rs1, rs2, rd) \ - do { \ - Format_3_5(2, rd, 0x27, rs1, 0, rs2); \ - asm_output("sra %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ - } while (0) - -#define SRAI(rs1, shcnt32, rd) \ - do { \ - Format_3_6(2, rd, 0x27, rs1, shcnt32); \ - asm_output("sra %s, %d, %s", gpn(rs1), shcnt32, gpn(rd)); \ - } while (0) - -#define SRL(rs1, rs2, rd) \ - do { \ - Format_3_5(2, rd, 0x26, rs1, 0, rs2); \ - asm_output("srl %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ - } while (0) - -#define STF(rd, rs1, rs2) \ - do { \ - Format_3_1(3, rd, 0x24, rs1, 0, rs2); \ - asm_output("st %s, [%s + %s]", gpn(rd+32), gpn(rs1), gpn(rs2)); \ - } while (0) - -#define STFI(rd, simm13, rs1) \ - do { \ - Format_3_1I(3, rd, 0x24, rs1, simm13); \ - asm_output("st %s, [%s + %d]", gpn(rd+32), gpn(rs1), simm13); \ - } while (0) - -#define STW(rd, rs2, rs1) \ - do { \ - Format_3_1(3, rd, 0x4, rs1, 0, rs2); \ - asm_output("st %s, [%s + %s]", gpn(rd), gpn(rs1), gpn(rs2)); \ - } while (0) - -#define STWI(rd, simm13, rs1) \ - do { \ - Format_3_1I(3, rd, 0x4, rs1, simm13); \ - asm_output("st %s, [%s + %d]", gpn(rd), gpn(rs1), simm13); \ - } while (0) - -#define STB(rd, rs2, rs1) \ - do { \ - Format_3_1(3, rd, 0x5, rs1, 0, rs2); \ - asm_output("stb %s, [%s + %s]", gpn(rd), gpn(rs1), gpn(rs2)); \ - } while (0) - -#define STBI(rd, simm13, rs1) \ - do { \ - Format_3_1I(3, rd, 0x5, rs1, simm13); \ - asm_output("stb %s, [%s + %d]", gpn(rd), gpn(rs1), simm13); \ - } while (0) - - -#define SUBCC(rs1, rs2, rd) \ - do { \ - Format_3_1(2, rd, 0x14, rs1, 0, rs2); \ - asm_output("subcc %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ - } while (0) - -#define SUB(rs1, rs2, rd) \ - do { \ - Format_3_1(2, rd, 0x4, rs1, 0, rs2); \ - asm_output("sub %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ - } while (0) - -#define SUBI(rs1, simm13, rd) \ - do { \ - Format_3_1I(2, rd, 0x4, rs1, simm13); \ - asm_output("sub %s, %d, %s", gpn(rs1), simm13, gpn(rd)); \ - } while (0) - -#define XOR(rs1, rs2, rd) \ - do { \ - Format_3_1(2, rd, 0x3, rs1, 0, rs2); \ - asm_output("xor %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd)); \ - } while (0) - - // Returns true if imm below 13-bit unsigned immediate) -#define isIMM13(imm) \ - (imm) <= 4095 && (imm) >= -4096 - -#define isIMM19(imm) \ - (imm) <= 0x3ffff && (imm) >= -0x40000 - -#define isIMM22(imm) \ - (imm) <= 0x1fffff && (imm) >= -0x200000 - -#define SET32(immI, rd) \ - if(isIMM13(immI)) { \ - ORI(G0, immI, rd); \ - } else { \ - ORI(rd, immI & 0x3FF, rd); \ - SETHI(immI, rd); \ - } - -#define STDF32(rd, immI, rs1) \ - if(isIMM13(immI+4)) { \ - STFI(rd+1, immI+4, rs1); \ - STFI(rd, immI, rs1); \ - } else { \ - STF(rd+1, L0, rs1); \ - SET32(immI+4, L0); \ - STF(rd, L0, rs1); \ - SET32(immI, L0); \ - } - -#define STF32(rd, immI, rs1) \ - if(isIMM13(immI+4)) { \ - STFI(rd, immI, rs1); \ - } else { \ - STF(rd, L0, rs1); \ - SET32(immI, L0); \ - } - -#define LDDF32(rs1, immI, rd) \ - if(isIMM13(immI+4)) { \ - LDFI(rs1, immI+4, rd+1); \ - LDFI(rs1, immI, rd); \ - } else { \ - LDF(rs1, L0, rd+1); \ - SET32(immI+4, L0); \ - LDF(rs1, L0, rd); \ - SET32(immI, L0); \ - } - -#define STW32(rd, immI, rs1) \ - if(isIMM13(immI)) { \ - STWI(rd, immI, rs1); \ - } else { \ - STW(rd, L0, rs1); \ - SET32(immI, L0); \ - } - -#define STB32(rd, immI, rs1) \ - if(isIMM13(immI)) { \ - STBI(rd, immI, rs1); \ - } else { \ - STB(rd, L0, rs1); \ - SET32(immI, L0); \ - } - -#define LDUB32(rs1, immI, rd) \ - if(isIMM13(immI)) { \ - LDUBI(rs1, immI, rd); \ - } else { \ - LDUB(rs1, L0, rd); \ - SET32(immI, L0); \ - } - -#define LDUH32(rs1, immI, rd) \ - if(isIMM13(immI)) { \ - LDUHI(rs1, immI, rd); \ - } else { \ - LDUH(rs1, L0, rd); \ - SET32(immI, L0); \ - } - -#define LDSW32(rs1, immI, rd) \ - if(isIMM13(immI)) { \ - LDSWI(rs1, immI, rd); \ - } else { \ - LDSW(rs1, L0, rd); \ - SET32(immI, L0); \ - } - - - // general Assemble -#define JMP_long_nocheck(t) do { NOP(); JMPL(G0, G2, G0); ORI(G2, t & 0x3FF, G2); SETHI(t, G2); } while(0) -#define JMP_long(t) do { underrunProtect(16); JMP_long_nocheck(t); } while(0) -#define JMP_long_placeholder() JMP_long(0) - -#define JCC(t, tt) \ - underrunProtect(32); \ - tt = ((intptr_t)t - (intptr_t)_nIns + 8) >> 2; \ - if( !(isIMM22((int32_t)tt)) ) { \ - NOP(); \ - JMPL(G0, G2, G0); \ - SET32((intptr_t)t, G2); \ - NOP(); \ - BA(0, 5); \ - tt = 4; \ + const static Register argRegs[6], retRegs[1]; \ + bool has_cmov; \ + void nativePageReset(); \ + void nativePageSetup(); \ + void underrunProtect(int bytes); \ + void asm_align_code(); \ + void asm_cmp(LIns *cond); \ + void asm_cmpd(LIns *cond); \ + NIns* asm_branchd(bool, LIns*, NIns*); \ + void IMM32(int32_t i) { \ + --_nIns; \ + *((int32_t*)_nIns) = i; \ + } \ + void CALL(const CallInfo* ci); \ + void Format_2(int32_t x, int32_t op2, int32_t imm22) { \ + int32_t i = x << 25 | op2 << 22 | imm22 & 0x3FFFFF; \ + IMM32(i); \ + } \ + void Format_2A(Register rd, int32_t op2, int32_t imm22) { \ + Format_2(_reg_(rd), op2, imm22); \ + } \ + void Format_2_2(int32_t a, int32_t cond, int32_t op2, int32_t disp22) { \ + Format_2((a & 0x1) << 4 | cond & 0xF, op2, disp22); \ + } \ + void Format_2_3(int32_t a, int32_t cond, int32_t op2, int32_t cc1, int32_t cc0, int32_t p, int32_t disp19) { \ + Format_2_2(a, cond, op2, (cc1 & 0x1) << 21 | (cc0 & 0x1) << 20 | (p & 0x1) << 19 | disp19 & 0x7FFFF); \ + } \ + void Format_2_4(int32_t a, int32_t rcond, int32_t op2, int32_t d16hi, int32_t p, int32_t rs1, int32_t d16lo) { \ + Format_2_2(a, rcond & 0x7, op2, (d16hi & 0x3) << 20 | (p & 0x1) << 19 | rs1 << 14 | d16lo & 0x3FFF); \ + } \ + void Format_3(int32_t op1, int32_t x, int32_t op3, int32_t bits19) { \ + int32_t i = op1 << 30 | x << 25 | op3 << 19 | bits19 & 0x7FFFF; \ + IMM32(i); \ + } \ + void Format_3A(int32_t op1, Register rd, int32_t op3, int32_t bits19) { \ + Format_3(op1, _reg_(rd), op3, bits19); \ + } \ + void Format_3_1(int32_t op1, Register rd, int32_t op3, Register rs1, int32_t bit8, Register rs2) { \ + Format_3A(op1, rd, op3, _reg_(rs1) << 14 | (bit8 & 0xFF) << 5 | _reg_(rs2)); \ + } \ + void Format_3_1I(int32_t op1, Register rd, int32_t op3, Register rs1, int32_t simm13) { \ + Format_3A(op1, rd, op3, _reg_(rs1) << 14 | 1 << 13 | simm13 & 0x1FFF); \ + } \ + void Format_3_2(int32_t op1, Register rd, int32_t op3, Register rs1, int32_t rcond, Register rs2) { \ + Format_3A(op1, rd, op3, _reg_(rs1) << 14 | (rcond & 0x3) << 10 | _reg_(rs2)); \ } \ - NOP() - -#define JMP(t) do { \ - if (!t) { \ - JMP_long_placeholder(); \ - } else { \ - intptr_t tt; \ - JCC(t, tt); \ - BA(0, tt); \ - } \ - } while(0) - -#define MR(d, s) do { underrunProtect(4); ORI(s, 0, d); } while(0) - - } + void Format_3_2I(int32_t op1, Register rd, int32_t op3, Register rs1, int32_t rcond, int32_t simm10) { \ + Format_3A(op1, rd, op3, _reg_(rs1) << 14 | 1 << 13 | (rcond & 0x3) << 10 | simm10 & 0x1FFF); \ + } \ + void Format_3_3(int32_t op1, Register rd, int32_t op3, Register rs1, int32_t cmask, int32_t mmask) { \ + Format_3A(op1, rd, op3, _reg_(rs1) << 14 | 1 << 13 | (cmask & 0x7) << 5 | mmask & 0xF); \ + } \ + void Format_3_4(int32_t op1, Register rd, int32_t op3, int32_t bits19) { \ + Format_3A(op1, rd, op3, bits19); \ + } \ + void Format_3_5(int32_t op1, Register rd, int32_t op3, Register rs1, int32_t x, Register rs2) { \ + Format_3A(op1, rd, op3, _reg_(rs1) << 14 | (x & 0x1) << 12 | _reg_(rs2)); \ + } \ + void Format_3_6(int32_t op1, Register rd, int32_t op3, Register rs1, int32_t shcnt32) { \ + Format_3A(op1, rd, op3, _reg_(rs1) << 14 | 1 << 13 | (shcnt32 & 0x3F)); \ + } \ + void Format_3_7(int32_t op1, Register rd, int32_t op3, Register rs1, int32_t shcnt64) { \ + Format_3A(op1, rd, op3, _reg_(rs1) << 14 | 1 << 13 | 1 << 12 | (shcnt64 & 0x7F)); \ + } \ + void Format_3_8(int32_t op1, Register rd, int32_t op3, Register rs1, int32_t bits9, Register rs2) { \ + Format_3A(op1, rd, op3, _reg_(rs1) << 14 | (bits9 & 0x1FF) << 5 | _reg_(rs2)); \ + } \ + void Format_3_9(int32_t op1, int32_t cc1, int32_t cc0, int32_t op3, Register rs1, int32_t bits9, Register rs2) { \ + Format_3(op1, (cc1 & 0x1) << 1 | (cc0 & 0x1), op3, _reg_(rs1) << 14 | (bits9 & 0x1FF) << 5 | _reg_(rs2)); \ + } \ + void Format_4_1(Register rd, int32_t op3, Register rs1, int32_t cc1, int32_t cc0, Register rs2) { \ + Format_3A(2, rd, op3, _reg_(rs1) << 14 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | _reg_(rs2)); \ + } \ + void Format_4_1I(Register rd, int32_t op3, Register rs1, int32_t cc1, int32_t cc0, int32_t simm11) { \ + Format_3A(2, rd, op3, _reg_(rs1) << 14 | (cc1 & 0x1) << 12 | 1 << 13 |(cc0 & 0x1) << 11 | simm11 & 0x7FF); \ + } \ + void Format_4_2(Register rd, int32_t op3, int32_t cc2, int32_t cond, int32_t cc1, int32_t cc0, Register rs2) { \ + Format_3A(2, rd, op3, (cc2 & 0x1) << 18 | (cond & 0xF) << 14 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | _reg_(rs2)); \ + } \ + void Format_4_2I(Register rd, int32_t op3, int32_t cc2, int32_t cond, int32_t cc1, int32_t cc0, int32_t simm11) { \ + Format_3A(2, rd, op3, (cc2 & 0x1) << 18 | (cond & 0xF) << 14 | 1 << 13 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | (simm11 & 0x7FF)); \ + } \ + void Format_4_3(Register rd, int32_t op3, Register rs1, int32_t cc1, int32_t cc0, int32_t swap_trap) { \ + Format_3A(2, rd, op3, _reg_(rs1) << 14 | 1 << 13 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | swap_trap & 0x7F); \ + } \ + void Format_4_4(Register rd, int32_t op3, Register rs1, int32_t rcond, int32_t opf_low, Register rs2) { \ + Format_3A(2, rd, op3, _reg_(rs1) << 14 | (rcond & 0x7) << 10 | (opf_low & 0x1F) << 5 | _reg_(rs2)); \ + } \ + void Format_4_5(Register rd, int32_t op3, int32_t cond, int32_t opf_cc, int32_t opf_low, Register rs2) { \ + Format_3A(2, rd, op3, (cond & 0xF) << 14 | (opf_cc & 0x7) << 11 | (opf_low & 0x3F) << 5 | _reg_(rs2)); \ + } \ + void IntegerOperation(Register rs1, Register rs2, Register rd, int32_t op3, const char *opcode); \ + void Assembler::IntegerOperationI(Register rs1, int32_t simm13, Register rd, int32_t op3, const char *opcode); \ + void FloatOperation(Register rs1, Register rs2, Register rd, int32_t op3, const char *opcode); \ + void Bicc(int32_t a, int32_t dsp22, int32_t cond, const char *opcode); \ + void FBfcc(int32_t a, int32_t dsp22, int32_t cond, const char *opcode); \ + void LoadOperation(Register rs1, Register rs2, Register rd, int32_t op3, const char* opcode); \ + void LoadOperationI(Register rs1, int32_t simm13, Register rd, int32_t op3, const char* opcode); \ + void MOVcc(Register rs, int32_t cc2, int32_t cc1, int32_t cc0, Register rd, int32_t cond, const char *opcode); \ + void MOVccI(int32_t simm11, int32_t cc2, int32_t cc1, int32_t cc0, Register rd, int32_t cond, const char *opcode); \ + void ShiftOperation(Register rs1, Register rs2, Register rd, int32_t op3, const char* opcode); \ + void ShiftOperationI(Register rs1, int32_t shcnt32, Register rd, int32_t op3, const char* opcode); \ + void Store(Register rd, Register rs1, Register rs2, int32_t op3, const char* opcode); \ + void Assembler::StoreI(Register rd, int32_t simm13, Register rs1, int32_t op3, const char* opcode); \ + void ADD(Register rs1, Register rs2, Register rd); \ + void ADDCC(Register rs1, Register rs2, Register rd); \ + void AND(Register rs1, Register rs2, Register rd); \ + void ANDCC(Register rs1, Register rs2, Register rd); \ + void OR(Register rs1, Register rs2, Register rd); \ + void ORI(Register rs1, int32_t simm13, Register rd); \ + void ORN(Register rs1, Register rs2, Register rd); \ + void SMULCC(Register rs1, Register rs2, Register rd); \ + void SUB(Register rs1, Register rs2, Register rd); \ + void SUBCC(Register rs1, Register rs2, Register rd); \ + void SUBI(Register rs1, int32_t simm13, Register rd); \ + void XOR(Register rs1, Register rs2, Register rd); \ + void BA(int32_t a, int32_t dsp22); \ + void BE(int32_t a, int32_t dsp22); \ + void BNE(int32_t a, int32_t dsp22); \ + void BG(int32_t a, int32_t dsp22); \ + void BGU(int32_t a, int32_t dsp22); \ + void BGE(int32_t a, int32_t dsp22); \ + void BL(int32_t a, int32_t dsp22); \ + void BLE(int32_t a, int32_t dsp22); \ + void BLEU(int32_t a, int32_t dsp22); \ + void BCC(int32_t a, int32_t dsp22); \ + void BCS(int32_t a, int32_t dsp22); \ + void BVC(int32_t a, int32_t dsp22); \ + void BVS(int32_t a, int32_t dsp22); \ + void FABSS(Register rs2, Register rd); \ + void FADDD(Register rs1, Register rs2, Register rd); \ + void FBE(int32_t a, int32_t dsp22); \ + void FBNE(int32_t a, int32_t dsp22); \ + void FBUE(int32_t a, int32_t dsp22); \ + void FBG(int32_t a, int32_t dsp22); \ + void FBUG(int32_t a, int32_t dsp22); \ + void FBGE(int32_t a, int32_t dsp22); \ + void FBUGE(int32_t a, int32_t dsp22); \ + void FBL(int32_t a, int32_t dsp22); \ + void FBUL(int32_t a, int32_t dsp22); \ + void FBLE(int32_t a, int32_t dsp22); \ + void FBULE(int32_t a, int32_t dsp22); \ + void FCMPD(Register rs1, Register rs2); \ + void FSUBD(Register rs1, Register rs2, Register rd); \ + void FMULD(Register rs1, Register rs2, Register rd); \ + void FDTOI(Register rs2, Register rd); \ + void FDIVD(Register rs1, Register rs2, Register rd); \ + void FMOVD(Register rs2, Register rd); \ + void FNEGD(Register rs2, Register rd); \ + void FITOD(Register rs2, Register rd); \ + void JMPL(Register rs1, Register rs2, Register rd); \ + void JMPLI(Register rs1, int32_t simm13, Register rd); \ + void LDF(Register rs1, Register rs2, Register rd); \ + void LDFI(Register rs1, int32_t simm13, Register rd); \ + void LDDF32(Register rs1, int32_t immI, Register rd); \ + void LDUB(Register rs1, Register rs2, Register rd); \ + void LDUBI(Register rs1, int32_t simm13, Register rd); \ + void LDUB32(Register rs1, int32_t immI, Register rd); \ + void LDUH(Register rs1, Register rs2, Register rd); \ + void LDUHI(Register rs1, int32_t simm13, Register rd); \ + void LDUH32(Register rs1, int32_t immI, Register rd); \ + void LDSW(Register rs1, Register rs2, Register rd); \ + void LDSWI(Register rs1, int32_t simm13, Register rd); \ + void LDSW32(Register rs1, int32_t immI, Register rd); \ + void MOVE(Register rs, Register rd); \ + void MOVNE(Register rs, Register rd); \ + void MOVL(Register rs, Register rd); \ + void MOVLE(Register rs, Register rd); \ + void MOVG(Register rs, Register rd); \ + void MOVGE(Register rs, Register rd); \ + void MOVLEU(Register rs, Register rd); \ + void MOVGU(Register rs, Register rd); \ + void MOVCC(Register rs, Register rd); \ + void MOVCS(Register rs, Register rd); \ + void MOVVC(Register rs, Register rd); \ + void MOVEI(int32_t simm11, Register rd); \ + void MOVFEI(int32_t simm11, Register rd); \ + void MOVNEI(int32_t simm11, Register rd); \ + void MOVLI(int32_t simm11, Register rd); \ + void MOVFLI(int32_t simm11, Register rd); \ + void MOVLEI(int32_t simm11, Register rd); \ + void MOVFLEI(int32_t simm11, Register rd); \ + void MOVGI(int32_t simm11, Register rd); \ + void MOVFGI(int32_t simm11, Register rd); \ + void MOVGEI(int32_t simm11, Register rd); \ + void MOVFGEI(int32_t simm11, Register rd); \ + void MOVLEUI(int32_t simm11, Register rd); \ + void MOVGUI(int32_t simm11, Register rd); \ + void MOVCCI(int32_t simm11, Register rd); \ + void MOVCSI(int32_t simm11, Register rd); \ + void MOVVSI(int32_t simm11, Register rd); \ + void NOP(); \ + void RDY(Register rd); \ + void RESTORE(Register rs1, Register rs2, Register rd); \ + void SAVE(Register rs1, Register rs2, Register rd); \ + void SAVEI(Register rs1, int32_t simm13, Register rd); \ + void SETHI(int32_t immI, Register rd); \ + void SET32(int32_t immI, Register rd); \ + void SLL(Register rs1, Register rs2, Register rd); \ + void SRA(Register rs1, Register rs2, Register rd); \ + void SRAI(Register rs1, int32_t shcnt32, Register rd); \ + void SRL(Register rs1, Register rs2, Register rd); \ + void STF(Register rd, Register rs1, Register rs2); \ + void STFI(Register rd, int32_t simm13, Register rs1); \ + void STF32(Register rd, int32_t immI, Register rs1); \ + void STDF32(Register rd, int32_t immI, Register rs1); \ + void STW(Register rd, Register rs1, Register rs2); \ + void STWI(Register rd, int32_t simm13, Register rs1); \ + void STW32(Register rd, int32_t immI, Register rs1); \ + void STB(Register rd, Register rs1, Register rs2); \ + void STBI(Register rd, int32_t simm13, Register rs1); \ + void STB32(Register rd, int32_t immI, Register rs1); \ + bool isIMM13(int32_t imm) { return (imm) <= 0xfff && (imm) >= -0x1000; } \ + bool isIMM19(int32_t imm) { return (imm) <= 0x3ffff && (imm) >= -0x40000; } \ + bool isIMM22(int32_t imm) { return (imm) <= 0x1fffff && (imm) >= -0x200000; } \ + void JMP_long_nocheck(int32_t t); \ + void JMP_long(int32_t t); \ + void JMP_long_placeholder(); \ + int32_t JCC(void *t); \ + void JMP(void *t); \ + void MR(Register rd, Register rs); +} #endif // __nanojit_NativeSparc__ diff --git a/js/src/nanojit/NativeX64.cpp b/js/src/nanojit/NativeX64.cpp index b999359ad995..0ffabc5bf3d7 100644 --- a/js/src/nanojit/NativeX64.cpp +++ b/js/src/nanojit/NativeX64.cpp @@ -294,6 +294,37 @@ namespace nanojit emitprr(op, r, b); } + // disp32 modrm form with 32-bit immediate value + void Assembler::emitrm_imm32(uint64_t op, Register b, int32_t d, int32_t imm) { + NanoAssert(IsGpReg(b)); + NanoAssert((REGNUM(b) & 7) != 4); // using RSP or R12 as base requires SIB + underrunProtect(4+4+8); // room for imm plus disp plus fullsize op + *((int32_t*)(_nIns -= 4)) = imm; + _nvprof("x86-bytes", 4); + emitrm_wide(op, RZero, d, b); + } + + // disp32 modrm form with 16-bit immediate value + // p = prefix -- opcode must have a 66, F2, or F3 prefix + void Assembler::emitprm_imm16(uint64_t op, Register b, int32_t d, int32_t imm) { + NanoAssert(IsGpReg(b)); + NanoAssert((REGNUM(b) & 7) != 4); // using RSP or R12 as base requires SIB + underrunProtect(2+4+8); // room for imm plus disp plus fullsize op + *((int16_t*)(_nIns -= 2)) = (int16_t) imm; + _nvprof("x86-bytes", 2); + emitprm(op, RZero, d, b); + } + + // disp32 modrm form with 8-bit immediate value + void Assembler::emitrm_imm8(uint64_t op, Register b, int32_t d, int32_t imm) { + NanoAssert(IsGpReg(b)); + NanoAssert((REGNUM(b) & 7) != 4); // using RSP or R12 as base requires SIB + underrunProtect(1+4+8); // room for imm plus disp plus fullsize op + *((int8_t*)(_nIns -= 1)) = (int8_t) imm; + _nvprof("x86-bytes", 1); + emitrm_wide(op, RZero, d, b); + } + void Assembler::emitrr_imm(uint64_t op, Register r, Register b, int32_t imm) { NanoAssert(IsGpReg(r) && IsGpReg(b)); underrunProtect(4+8); // room for imm plus fullsize op @@ -590,6 +621,11 @@ namespace nanojit void Assembler::CALLRAX() { emit(X64_callrax); asm_output("call (rax)"); } void Assembler::RET() { emit(X64_ret); asm_output("ret"); } + void Assembler::MOVQMI(R r, I d, I32 imm) { emitrm_imm32(X64_movqmi,r,d,imm); asm_output("movq %d(%s), %d",d,RQ(r),imm); } + void Assembler::MOVLMI(R r, I d, I32 imm) { emitrm_imm32(X64_movlmi,r,d,imm); asm_output("movl %d(%s), %d",d,RQ(r),imm); } + void Assembler::MOVSMI(R r, I d, I32 imm) { emitprm_imm16(X64_movsmi,r,d,imm); asm_output("movs %d(%s), %d",d,RQ(r),imm); } + void Assembler::MOVBMI(R r, I d, I32 imm) { emitrm_imm8(X64_movbmi,r,d,imm); asm_output("movb %d(%s), %d",d,RQ(r),imm); } + void Assembler::MOVQSPR(I d, R r) { emit(X64_movqspr | U64(d) << 56 | U64((REGNUM(r)&7)<<3) << 40 | U64((REGNUM(r)&8)>>1) << 24); asm_output("movq %d(rsp), %s", d, RQ(r)); } // insert r into mod/rm and rex bytes void Assembler::XORPSA(R r, I32 i32) { emitxm_abs(X64_xorpsa, r, i32); asm_output("xorps %s, (0x%x)",RQ(r), i32); } @@ -1647,9 +1683,17 @@ namespace nanojit switch (op) { case LIR_stq: { - Register r, b; - getBaseReg2(GpRegs, value, r, BaseRegs, base, b, d); - MOVQMR(r, d, b); // gpr store + uint64_t c; + if (value->isImmQ() && (c = value->immQ(), isS32(c))) { + uint64_t c = value->immQ(); + Register rb = getBaseReg(base, d, BaseRegs); + // MOVQMI takes a 32-bit integer that gets signed extended to a 64-bit value. + MOVQMI(rb, d, int32_t(c)); + } else { + Register rr, rb; + getBaseReg2(GpRegs, value, rr, BaseRegs, base, rb, d); + MOVQMR(rr, d, rb); // gpr store + } break; } case LIR_std: { @@ -1675,28 +1719,31 @@ namespace nanojit } void Assembler::asm_store32(LOpcode op, LIns *value, int d, LIns *base) { + if (value->isImmI()) { + Register rb = getBaseReg(base, d, BaseRegs); + int c = value->immI(); + switch (op) { + case LIR_sti2c: MOVBMI(rb, d, c); break; + case LIR_sti2s: MOVSMI(rb, d, c); break; + case LIR_sti: MOVLMI(rb, d, c); break; + default: NanoAssert(0); break; + } - // Quirk of x86-64: reg cannot appear to be ah/bh/ch/dh for - // single-byte stores with REX prefix. - const RegisterMask SrcRegs = (op == LIR_sti2c) ? SingleByteStoreRegs : GpRegs; + } else { + // Quirk of x86-64: reg cannot appear to be ah/bh/ch/dh for + // single-byte stores with REX prefix. + const RegisterMask SrcRegs = (op == LIR_sti2c) ? SingleByteStoreRegs : GpRegs; - NanoAssert(value->isI()); - Register b = getBaseReg(base, d, BaseRegs); - Register r = findRegFor(value, SrcRegs & ~rmask(b)); + NanoAssert(value->isI()); + Register b = getBaseReg(base, d, BaseRegs); + Register r = findRegFor(value, SrcRegs & ~rmask(b)); - switch (op) { - case LIR_sti2c: - MOVBMR(r, d, b); - break; - case LIR_sti2s: - MOVSMR(r, d, b); - break; - case LIR_sti: - MOVLMR(r, d, b); - break; - default: - NanoAssertMsg(0, "asm_store32 should never receive this LIR opcode"); - break; + switch (op) { + case LIR_sti2c: MOVBMR(r, d, b); break; + case LIR_sti2s: MOVSMR(r, d, b); break; + case LIR_sti: MOVLMR(r, d, b); break; + default: NanoAssert(0); break; + } } } diff --git a/js/src/nanojit/NativeX64.h b/js/src/nanojit/NativeX64.h index b7fb84acd026..2f5a6b3d1b58 100644 --- a/js/src/nanojit/NativeX64.h +++ b/js/src/nanojit/NativeX64.h @@ -320,6 +320,11 @@ namespace nanojit X64_jmpx = 0xC524ff4000000004LL, // jmp [d32+x*8] X64_jmpxb = 0xC024ff4000000004LL, // jmp [b+x*8] + X64_movqmi = 0x80C7480000000003LL, // 32bit signed extended to 64-bit store imm -> qword ptr[b+disp32] + X64_movlmi = 0x80C7400000000003LL, // 32bit store imm -> dword ptr[b+disp32] + X64_movsmi = 0x80C7406600000004LL, // 16bit store imm -> word ptr[b+disp32] + X64_movbmi = 0x80C6400000000003LL, // 8bit store imm -> byte ptr[b+disp32] + X86_and8r = 0xC022000000000002LL, // and rl,rh X86_sete = 0xC0940F0000000003LL, // no-rex version of X64_sete X86_setnp = 0xC09B0F0000000003LL // no-rex set byte if odd parity (ordered fcmp result) (PF == 0) @@ -390,6 +395,9 @@ namespace nanojit void emitprm(uint64_t op, Register r, int32_t d, Register b);\ void emitrr_imm(uint64_t op, Register r, Register b, int32_t imm);\ void emitr_imm64(uint64_t op, Register r, uint64_t imm);\ + void emitrm_imm32(uint64_t op, Register r, int32_t d, int32_t imm);\ + void emitprm_imm16(uint64_t op, Register r, int32_t d, int32_t imm);\ + void emitrm_imm8(uint64_t op, Register r, int32_t d, int32_t imm);\ void emitrxb_imm(uint64_t op, Register r, Register x, Register b, int32_t imm);\ void emitr_imm(uint64_t op, Register r, int32_t imm) { emitrr_imm(op, RZero, r, imm); }\ void emitr_imm8(uint64_t op, Register b, int32_t imm8);\ @@ -598,6 +606,10 @@ namespace nanojit void X86_AND8R(Register r);\ void X86_SETNP(Register r);\ void X86_SETE(Register r);\ + void MOVQMI(Register base, int disp, int32_t imm32); \ + void MOVLMI(Register base, int disp, int32_t imm32); \ + void MOVSMI(Register base, int disp, int32_t imm16); \ + void MOVBMI(Register base, int disp, int32_t imm8); \ const int LARGEST_UNDERRUN_PROT = 32; // largest value passed to underrunProtect diff --git a/js/src/nanojit/Nativei386.cpp b/js/src/nanojit/Nativei386.cpp index db5fc4d74516..c4677efcef4c 100644 --- a/js/src/nanojit/Nativei386.cpp +++ b/js/src/nanojit/Nativei386.cpp @@ -76,20 +76,18 @@ namespace nanojit // XXX rearrange NanoAssert() expression to workaround apparent gcc 4.3 bug: // XXX "error: logical && with non-zero constant will always evaluate as true" // underrunProtect(6) is necessary for worst-case - inline void Assembler::MODRMs(I32 r, I32 d, R b, I32 l, I32 i) { - NanoAssert(unsigned(i) < 8 && REGNUM(b) < 8 && unsigned(r) < 8); + inline void Assembler::MODRMsib(I32 r, R b, R i, I32 s, I32 d) { + NanoAssert(REGNUM(i) < 8 && REGNUM(b) < 8 && unsigned(r) < 8); if (d == 0 && b != rEBP) { - _nIns -= 2; - _nIns[0] = uint8_t(0 << 6 | r << 3 | 4); - _nIns[1] = uint8_t(l << 6 | i << 3 | REGNUM(b)); + *(--_nIns) = uint8_t(s << 6 | REGNUM(i) << 3 | REGNUM(b)); + *(--_nIns) = uint8_t(0 << 6 | r << 3 | 4); } else if (isS8(d)) { - _nIns -= 3; - _nIns[0] = uint8_t(1 << 6 | r << 3 | 4); - _nIns[1] = uint8_t(l << 6 | i << 3 | REGNUM(b)); - _nIns[2] = uint8_t(d); + *(--_nIns) = uint8_t(d); + *(--_nIns) = uint8_t(s << 6 | REGNUM(i) << 3 | REGNUM(b)); + *(--_nIns) = uint8_t(1 << 6 | r << 3 | 4); } else { IMM32(d); - *(--_nIns) = uint8_t(l << 6 | i << 3 | REGNUM(b)); + *(--_nIns) = uint8_t(s << 6 | REGNUM(i) << 3 | REGNUM(b)); *(--_nIns) = uint8_t(2 << 6 | r << 3 | 4); } } @@ -101,7 +99,7 @@ namespace nanojit IMM32(d); *(--_nIns) = uint8_t(0 << 6 | r << 3 | 5); } else if (b == rESP) { - MODRMs(r, d, b, 0, 4); + MODRMsib(r, b, rESP, 0, d); } else if (d == 0 && b != rEBP) { *(--_nIns) = uint8_t(0 << 6 | r << 3 | REGNUM(b)); } else if (isS8(d)) { @@ -113,24 +111,6 @@ namespace nanojit } } - inline void Assembler::MODRMsib(I32 reg, R base, R index, I32 scale, I32 disp) { - if (disp != 0 || base == rEBP) { - if (isS8(disp)) { - *(--_nIns) = int8_t(disp); - } else { - IMM32(disp); - } - } - *(--_nIns) = uint8_t(scale << 6 | REGNUM(index) << 3 | REGNUM(base)); - if (disp == 0 && base != rEBP) { - *(--_nIns) = uint8_t(reg << 3 | 4); - } else if (isS8(disp)) { - *(--_nIns) = uint8_t(1 << 6 | reg << 3 | 4); - } else { - *(--_nIns) = uint8_t(2 << 6 | reg << 3 | 4); - } - } - inline void Assembler::MODRMdm(I32 r, I32 addr) { NanoAssert(unsigned(r) < 8); IMM32(addr); @@ -230,9 +210,8 @@ namespace nanojit inline void Assembler::ALU2(I32 c, R d, R s) { underrunProtect(3); MODRM(REGNUM(d), REGNUM(s)); - _nIns -= 2; - _nIns[0] = uint8_t(c>>8); - _nIns[1] = uint8_t(c); + *(--_nIns) = uint8_t(c); + *(--_nIns) = uint8_t(c>>8); } inline void Assembler::LAHF() { count_alu(); ALU0(0x9F); asm_output("lahf"); } @@ -242,7 +221,7 @@ namespace nanojit inline void Assembler::XOR(R l, R r) { count_alu(); ALU(0x33, REGNUM(l), r); asm_output("xor %s,%s", gpn(l), gpn(r)); } inline void Assembler::ADD(R l, R r) { count_alu(); ALU(0x03, REGNUM(l), r); asm_output("add %s,%s", gpn(l), gpn(r)); } inline void Assembler::SUB(R l, R r) { count_alu(); ALU(0x2b, REGNUM(l), r); asm_output("sub %s,%s", gpn(l), gpn(r)); } - inline void Assembler::MUL(R l, R r) { count_alu(); ALU2(0x0faf, l, r); asm_output("mul %s,%s", gpn(l), gpn(r)); } + inline void Assembler::IMUL(R l, R r){ count_alu(); ALU2(0x0faf, l, r); asm_output("imul %s,%s", gpn(l), gpn(r)); } inline void Assembler::DIV(R r) { count_alu(); ALU(0xf7, 7, r); asm_output("idiv edx:eax, %s", gpn(r)); } inline void Assembler::NOT(R r) { count_alu(); ALU(0xf7, 2, r); asm_output("not %s", gpn(r)); } inline void Assembler::NEG(R r) { count_alu(); ALU(0xf7, 3, r); asm_output("neg %s", gpn(r)); } @@ -562,9 +541,8 @@ namespace nanojit count_push(); if (isS8(i)) { underrunProtect(2); - _nIns -= 2; - _nIns[0] = 0x6a; - _nIns[1] = uint8_t(i); + *(--_nIns) = uint8_t(i); + *(--_nIns) = 0x6a; asm_output("push %d", i); } else { PUSHi32(i); @@ -606,14 +584,12 @@ namespace nanojit underrunProtect(6); intptr_t tt = (intptr_t)t - (intptr_t)_nIns; if (t && isS8(tt)) { - _nIns -= 2; - _nIns[0] = uint8_t(0x70 | o); - _nIns[1] = uint8_t(tt); + *(--_nIns) = uint8_t(tt); + *(--_nIns) = uint8_t(0x70 | o); } else { IMM32(tt); - _nIns -= 2; - _nIns[0] = JCC32; - _nIns[1] = uint8_t(0x80 | o); + *(--_nIns) = uint8_t(0x80 | o); + *(--_nIns) = JCC32; } asm_output("%-5s %p", n, t); (void) n; @@ -640,10 +616,9 @@ namespace nanojit inline void Assembler::JMP_indexed(Register x, I32 ss, NIns** addr) { underrunProtect(7); IMM32(int32_t(addr)); - _nIns -= 3; - _nIns[0] = uint8_t(0xff); /* jmp */ - _nIns[1] = uint8_t(0 << 6 | 4 << 3 | 4); /* modrm: base=sib + disp32 */ - _nIns[2] = uint8_t(ss << 6 | REGNUM(x) << 3 | 5); /* sib: x< Interrupt long-running execution after seconds, where\n" + " <= 1800.0. Negative values indicate no timeout (default).\n" + " -c Suggest stack chunk size of bytes. Default is 8192.\n" + " Warning: this option is currently ignored.\n" + " -o