diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog index c31f5fc700..134540d3f0 100644 --- a/deps/v8/ChangeLog +++ b/deps/v8/ChangeLog @@ -1,12 +1,53 @@ +2010-09-30: Version 2.4.7 + + Changed the command-line flag --max-new-space-size to be in kB and the + flag --max-old-space-size to be in MB (previously they were in bytes). + + Added Debug::CancelDebugBreak to the debugger API. + + Fixed a bug in getters for negative numeric property names + (https://bugs.webkit.org/show_bug.cgi?id=46689). + + Performance improvements on all platforms. + + +2010-09-27: Version 2.4.6 + + Fixed assertion failure related to copy-on-write arrays (issue 876). + + Fixed build failure of 64-bit V8 on Windows. + + Fixed a bug in RegExp (issue http://crbug.com/52801). + + Improved the profiler's coverage to cover more functions (issue 858). + + Fixed error in shift operators on 64-bit V8 + (issue http://crbug.com/54521). + + +2010-09-22: Version 2.4.5 + + Changed the RegExp benchmark to exercise the regexp engine on different + inputs by scrambling the input strings. + + Fixed a bug in keyed loads on strings. + + Fixed a bug with loading global function prototypes. + + Fixed a bug with profiling RegExp calls (issue http://crbug.com/55999). + + Performance improvements on all platforms. + + 2010-09-15: Version 2.4.4 - Fix bug with hangs on very large sparse arrays. + Fixed bug with hangs on very large sparse arrays. - Try harder to free up memory when running out of space. + Now tries harder to free up memory when running out of space. - Add heap snapshots to JSON format to API. + Added heap snapshots to JSON format to API. - Recalibrate benchmarks. + Recalibrated benchmarks. 2010-09-13: Version 2.4.3 @@ -42,33 +83,33 @@ 2010-09-01: Version 2.4.0 - Fix bug in Object.freeze and Object.seal when Array.prototype or - Object.prototype is changed (issue 842). + Fixed bug in Object.freeze and Object.seal when Array.prototype or + Object.prototype are changed (issue 842). - Update Array.splice to follow Safari and Firefox when called + Updated Array.splice to follow Safari and Firefox when called with zero arguments. - Fix a missing live register when breaking at keyed loads on ARM. + Fixed a missing live register when breaking at keyed loads on ARM. Performance improvements on all platforms. 2010-08-25: Version 2.3.11 - Fix bug in RegExp related to copy-on-write arrays. + Fixed bug in RegExp related to copy-on-write arrays. - Refactoring of tools/test.py script, including the introduction of + Refactored tools/test.py script, including the introduction of VARIANT_FLAGS that allows specification of sets of flags with which all tests should be run. - Fix a bug in the handling of debug breaks in CallIC. + Fixed a bug in the handling of debug breaks in CallIC. Performance improvements on all platforms. 2010-08-23: Version 2.3.10 - Fix bug in bitops on ARM. + Fixed bug in bitops on ARM. Build fixes for unusual compilers. @@ -79,7 +120,7 @@ 2010-08-18: Version 2.3.9 - Fix compilation for ARMv4 on OpenBSD/FreeBSD. + Fixed compilation for ARMv4 on OpenBSD/FreeBSD. Removed specialized handling of GCC 4.4 (issue 830). @@ -120,7 +161,7 @@ Fixed handling of JSObject::elements in CalculateNetworkSize (issue 822). - Allow compiling with strict aliasing enabled on GCC 4.4 (issue 463). + Allowed compiling with strict aliasing enabled on GCC 4.4 (issue 463). 2010-08-09: Version 2.3.6 @@ -130,7 +171,7 @@ Object.seal and Object.freeze return the modified object (issue 809). - Fix building using GCC 4.4.4. + Fixed building using GCC 4.4.4. 2010-08-04: Version 2.3.5 @@ -139,7 +180,7 @@ dot-notation property access now allows keywords. Also allowed non-identifiers after "get" or "set" in an object initialiser. - Randomize the addresses of allocated executable memory on Windows. + Randomized the addresses of allocated executable memory on Windows. 2010-08-02: Version 2.3.4 @@ -251,15 +292,15 @@ 2010-06-30: Version 2.2.21 - Fix bug in externalizing some ASCII strings (Chromium issue 47824). + Fixed bug in externalizing some ASCII strings (Chromium issue 47824). - Update JSON.stringify to floor the space parameter (issue 753). + Updated JSON.stringify to floor the space parameter (issue 753). - Update the Mozilla test expectations to the newest version. + Updated the Mozilla test expectations to the newest version. - Update the ES5 Conformance Test expectations to the latest version. + Updated the ES5 Conformance Test expectations to the latest version. - Update the V8 benchmark suite. + Updated the V8 benchmark suite. Provide actual breakpoints locations in response to setBreakpoint and listBreakpoints requests. @@ -267,13 +308,13 @@ 2010-06-28: Version 2.2.20 - Fix bug with for-in on x64 platform (issue 748). + Fixed bug with for-in on x64 platform (issue 748). - Fix crash bug on x64 platform (issue 756). + Fixed crash bug on x64 platform (issue 756). - Fix bug in Object.getOwnPropertyNames. (chromium issue 41243). + Fixed bug in Object.getOwnPropertyNames. (chromium issue 41243). - Fix a bug on ARM that caused the result of 1 << x to be + Fixed a bug on ARM that caused the result of 1 << x to be miscalculated for some inputs. Performance improvements on all platforms. @@ -281,7 +322,7 @@ 2010-06-23: Version 2.2.19 - Fix bug that causes the build to break when profillingsupport=off + Fixed bug that causes the build to break when profillingsupport=off (issue 738). Added expose-externalize-string flag for testing extensions. @@ -289,7 +330,7 @@ Resolve linker issues with using V8 as a DLL causing a number of problems with unresolved symbols. - Fix build failure for cctests when ENABLE_DEBUGGER_SUPPORT is not + Fixed build failure for cctests when ENABLE_DEBUGGER_SUPPORT is not defined. Performance improvements on all platforms. @@ -300,11 +341,11 @@ Added API functions to retrieve information on indexed properties managed by the embedding layer. Fixes bug 737. - Make ES5 Object.defineProperty support array elements. Fixes bug 619. + Made ES5 Object.defineProperty support array elements. Fixes bug 619. - Add heap profiling to the API. + Added heap profiling to the API. - Remove old named property query from the API. + Removed old named property query from the API. Incremental performance improvements. @@ -330,12 +371,12 @@ 2010-06-07: Version 2.2.15 - Add an API to control the disposal of external string resources. + Added an API to control the disposal of external string resources. - Add missing initialization of a couple of variables which makes + Added missing initialization of a couple of variables which makes some compilers complaint when compiling with -Werror. - Improve performance on all platforms. + Improved performance on all platforms. 2010-06-02: Version 2.2.14 @@ -349,12 +390,12 @@ 2010-05-31: Version 2.2.13 - Implement Object.getOwnPropertyDescriptor for element indices and + Implemented Object.getOwnPropertyDescriptor for element indices and strings (issue 599). - Fix bug for windows 64 bit C calls from generated code. + Fixed bug for windows 64 bit C calls from generated code. - Add new scons flag unalignedaccesses for arm builds. + Added new scons flag unalignedaccesses for arm builds. Performance improvements on all platforms. @@ -369,7 +410,7 @@ 2010-05-21: Version 2.2.11 - Fix crash bug in liveedit on 64 bit. + Fixed crash bug in liveedit on 64 bit. Use 'full compiler' when debugging is active. This should increase the density of possible break points, making single step more fine @@ -379,11 +420,11 @@ Misc. fixes to the Solaris build. - Add new flags --print-cumulative-gc-stat and --trace-gc-nvp. + Added new flags --print-cumulative-gc-stat and --trace-gc-nvp. - Add filtering of CPU profiles by security context. + Added filtering of CPU profiles by security context. - Fix crash bug on ARM when running without VFP2 or VFP3. + Fixed crash bug on ARM when running without VFP2 or VFP3. Incremental performance improvements in all backends. @@ -395,12 +436,12 @@ 2010-05-10: Version 2.2.9 - Allow Object.create to be called with a function (issue 697). + Allowed Object.create to be called with a function (issue 697). Fixed bug with Date.parse returning a non-NaN value when called on a non date string (issue 696). - Allow unaligned memory accesses on ARM targets that support it (by + Allowed unaligned memory accesses on ARM targets that support it (by Subrato K De of CodeAurora ). C++ API for retrieving JavaScript stack trace information. @@ -554,9 +595,9 @@ 2010-02-23: Version 2.1.2 - Fix a crash bug caused by wrong assert. + Fixed a crash bug caused by wrong assert. - Fix a bug with register names on 64-bit V8 (issue 615). + Fixed a bug with register names on 64-bit V8 (issue 615). Performance improvements on all platforms. @@ -592,13 +633,13 @@ Solaris support by Erich Ocean and Ryan Dahl . - Fix a bug that Math.round() returns incorrect results for huge + Fixed a bug that Math.round() returns incorrect results for huge integers. - Fix enumeration order for objects created from some constructor + Fixed enumeration order for objects created from some constructor functions (isue http://crbug.com/3867). - Fix arithmetic on some integer constants (issue 580). + Fixed arithmetic on some integer constants (issue 580). Numerous performance improvements including porting of previous IA-32 optimizations to x64 and ARM architectures. @@ -737,11 +778,11 @@ X64: Convert smis to holding 32 bits of payload. - Introduce v8::Integer::NewFromUnsigned method. + Introduced v8::Integer::NewFromUnsigned method. - Add missing null check in Context::GetCurrent. + Added missing null check in Context::GetCurrent. - Add trim, trimLeft and trimRight methods to String + Added trim, trimLeft and trimRight methods to String Patch by Jan de Mooij Implement ES5 Array.isArray @@ -749,14 +790,15 @@ Skip access checks for hidden properties. - Add String::Concat(Handle left, Handle right) to the V8 API. + Added String::Concat(Handle left, Handle right) to the + V8 API. - Fix GYP-based builds of V8. + Fixed GYP-based builds of V8. 2009-10-07: Version 1.3.15 - Expand the maximum size of the code space to 512MB for 64-bit mode. + Expanded the maximum size of the code space to 512MB for 64-bit mode. Fixed a crash bug happening when starting profiling (issue http://crbug.com/23768). @@ -768,10 +810,10 @@ located on the object or in the prototype chain skipping any interceptors. - Fix the stack limits setting API to work correctly with threads. The + Fixed the stack limits setting API to work correctly with threads. The stack limit now needs to be set to each thread thich is used with V8. - Remove the high-priority flag from IdleNotification() + Removed the high-priority flag from IdleNotification() Ensure V8 is initialized before locking and unlocking threads. @@ -839,7 +881,7 @@ Implemented missing pieces of debugger infrastructure on ARM. The debugger is now fully functional on ARM. - Make 'hidden' the default visibility for gcc. + Made 'hidden' the default visibility for gcc. 2009-09-09: Version 1.3.10 @@ -894,9 +936,9 @@ 2009-08-21: Version 1.3.6 - Add support for forceful termination of JavaScript execution. + Added support for forceful termination of JavaScript execution. - Add low memory notification to the API. The embedding host can signal + Added low memory notification to the API. The embedding host can signal a low memory situation to V8. Changed the handling of global handles (persistent handles in the API @@ -910,9 +952,9 @@ 2009-08-19: Version 1.3.5 - Optimize initialization of some arrays in the builtins. + Optimized initialization of some arrays in the builtins. - Fix mac-nm script to support filenames with spaces. + Fixed mac-nm script to support filenames with spaces. Support for using the V8 profiler when V8 is embedded in a Windows DLL. @@ -925,7 +967,7 @@ Added API for getting object mirrors. - Make sure that SSE3 instructions are used whenever possible even when + Made sure that SSE3 instructions are used whenever possible even when running off a snapshot generated without using SSE3 instructions. Tweaked the handling of the initial size and growth policy of the heap. @@ -947,20 +989,20 @@ 2009-08-12: Version 1.3.3 - Fix issue 417: incorrect %t placeholder expansion. + Fixed issue 417: incorrect %t placeholder expansion. - Add .gitignore file similar to Chromium's one. + Added .gitignore file similar to Chromium's one. - Fix SConstruct file to build with new logging code for Android. + Fixed SConstruct file to build with new logging code for Android. API: added function to find instance of template in prototype chain. Inlined Object::IsInstanceOf. Land change to notify valgrind when we modify code on x86. - Add api call to determine whether a string can be externalized. + Added api call to determine whether a string can be externalized. - Add a write() command to d8. + Added a write() command to d8. 2009-08-05: Version 1.3.2 @@ -1243,7 +1285,7 @@ Added EcmaScript 5 JSON object. - Fix bug in preemption support on ARM. + Fixed bug in preemption support on ARM. 2009-04-23: Version 1.2.0 diff --git a/deps/v8/benchmarks/README.txt b/deps/v8/benchmarks/README.txt index 800b4f5185..6676f37556 100644 --- a/deps/v8/benchmarks/README.txt +++ b/deps/v8/benchmarks/README.txt @@ -70,7 +70,9 @@ Removed dead code from the RayTrace benchmark and fixed a couple of typos in the DeltaBlue implementation. Changed the Splay benchmark to avoid converting the same numeric key to a string over and over again and to avoid inserting and removing the same element repeatedly thus -increasing pressure on the memory subsystem. +increasing pressure on the memory subsystem. Changed the RegExp +benchmark to exercise the regular expression engine on different +input strings. Furthermore, the benchmark runner was changed to run the benchmarks for at least a few times to stabilize the reported numbers on slower diff --git a/deps/v8/benchmarks/regexp.js b/deps/v8/benchmarks/regexp.js index f76086685c..71b9e6362c 100644 --- a/deps/v8/benchmarks/regexp.js +++ b/deps/v8/benchmarks/regexp.js @@ -1,4 +1,4 @@ -// Copyright 2009 the V8 project authors. All rights reserved. +// Copyright 2010 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -25,21 +25,51 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Automatically generated on 2009-01-30. +// Automatically generated on 2009-01-30. Manually updated on 2010-09-17. // This benchmark is generated by loading 50 of the most popular pages // on the web and logging all regexp operations performed. Each // operation is given a weight that is calculated from an estimate of // the popularity of the pages where it occurs and the number of times -// it is executed while loading each page. Finally the literal +// it is executed while loading each page. Furthermore the literal // letters in the data are encoded using ROT13 in a way that does not -// affect how the regexps match their input. +// affect how the regexps match their input. Finally the strings are +// scrambled to exercise the regexp engine on different input strings. -var RegRxp = new BenchmarkSuite('RegExp', 910985, [ - new Benchmark("RegExp", runRegExpBenchmark) + +var RegExp = new BenchmarkSuite('RegExp', 910985, [ + new Benchmark("RegExp", RegExpRun, RegExpSetup, RegExpTearDown) ]); -function runRegExpBenchmark() { +var regExpBenchmark = null; + +function RegExpSetup() { + regExpBenchmark = new RegExpBenchmark(); + RegExpRun(); // run once to get system initialized +} + +function RegExpRun() { + regExpBenchmark.run(); +} + +function RegExpTearDown() { + regExpBenchmark = null; +} + +// Returns an array of n different variants of the input string str. +// The variants are computed by randomly rotating one random +// character. +function computeInputVariants(str, n) { + var variants = [ str ]; + for (var i = 1; i < n; i++) { + var pos = Math.floor(Math.random() * str.length); + var chr = String.fromCharCode((str.charCodeAt(pos) + Math.floor(Math.random() * 128)) % 128); + variants[i] = str.substring(0, pos) + chr + str.substring(pos + 1, str.length); + } + return variants; +} + +function RegExpBenchmark() { var re0 = /^ba/; var re1 = /(((\w+):\/\/)([^\/:]*)(:(\d+))?)?([^#?]*)(\?([^#]*))?(#(.*))?/; var re2 = /^\s*|\s*$/g; @@ -59,77 +89,105 @@ function runRegExpBenchmark() { var re14 = /\s+/g; var re15 = /^\s*(\S*(\s+\S+)*)\s*$/; var re16 = /(-[a-z])/i; + + var s0 = computeInputVariants('pyvpx', 6511); + var s1 = computeInputVariants('uggc://jjj.snprobbx.pbz/ybtva.cuc', 1844); + var s2 = computeInputVariants('QBZPbageby_cynprubyqre', 739); + var s3 = computeInputVariants('uggc://jjj.snprobbx.pbz/', 598); + var s4 = computeInputVariants('uggc://jjj.snprobbx.pbz/fepu.cuc', 454); + var s5 = computeInputVariants('qqqq, ZZZ q, llll', 352); + var s6 = computeInputVariants('vachggrkg QBZPbageby_cynprubyqre', 312); + var s7 = computeInputVariants('/ZlFcnprUbzrcntr/Vaqrk-FvgrUbzr,10000000', 282); + var s8 = computeInputVariants('vachggrkg', 177); + var s9 = computeInputVariants('528.9', 170); + var s10 = computeInputVariants('528', 170); + var s11 = computeInputVariants('VCPhygher=ra-HF', 156); + var s12 = computeInputVariants('CersreerqPhygher=ra-HF', 156); + var s13 = computeInputVariants('xrlcerff', 144); + var s14 = computeInputVariants('521', 139); + var s15 = computeInputVariants(str0, 139); + var s16 = computeInputVariants('qvi .so_zrah', 137); + var s17 = computeInputVariants('qvi.so_zrah', 137); + var s18 = computeInputVariants('uvqqra_ryrz', 117); + var s19 = computeInputVariants('sevraqfgre_naba=nvq%3Qn6ss9p85n868ro9s059pn854735956o3%26ers%3Q%26df%3Q%26vpgl%3QHF', 95); + var s20 = computeInputVariants('uggc://ubzr.zlfcnpr.pbz/vaqrk.psz', 93); + var s21 = computeInputVariants(str1, 92); + var s22 = computeInputVariants('svefg', 85); + var s23 = computeInputVariants('uggc://cebsvyr.zlfcnpr.pbz/vaqrk.psz', 85); + var s24 = computeInputVariants('ynfg', 85); + var s25 = computeInputVariants('qvfcynl', 85); + function runBlock0() { for (var i = 0; i < 6511; i++) { - re0.exec('pyvpx'); + re0.exec(s0[i]); } for (var i = 0; i < 1844; i++) { - re1.exec('uggc://jjj.snprobbx.pbz/ybtva.cuc'); + re1.exec(s1[i]); } for (var i = 0; i < 739; i++) { - 'QBZPbageby_cynprubyqre'.replace(re2, ''); + s2[i].replace(re2, ''); } for (var i = 0; i < 598; i++) { - re1.exec('uggc://jjj.snprobbx.pbz/'); + re1.exec(s3[i]); } for (var i = 0; i < 454; i++) { - re1.exec('uggc://jjj.snprobbx.pbz/fepu.cuc'); + re1.exec(s4[i]); } for (var i = 0; i < 352; i++) { - /qqqq|qqq|qq|q|ZZZZ|ZZZ|ZZ|Z|llll|ll|l|uu|u|UU|U|zz|z|ff|f|gg|g|sss|ss|s|mmm|mm|m/g.exec('qqqq, ZZZ q, llll'); + /qqqq|qqq|qq|q|ZZZZ|ZZZ|ZZ|Z|llll|ll|l|uu|u|UU|U|zz|z|ff|f|gg|g|sss|ss|s|mmm|mm|m/g.exec(s5[i]); } for (var i = 0; i < 312; i++) { - re3.exec('vachggrkg QBZPbageby_cynprubyqre'); + re3.exec(s6[i]); } for (var i = 0; i < 282; i++) { - re4.exec('/ZlFcnprUbzrcntr/Vaqrk-FvgrUbzr,10000000'); + re4.exec(s7[i]); } for (var i = 0; i < 177; i++) { - 'vachggrkg'.replace(re5, ''); + s8[i].replace(re5, ''); } for (var i = 0; i < 170; i++) { - '528.9'.replace(re6, ''); - re7.exec('528'); + s9[i].replace(re6, ''); + re7.exec(s10[i]); } for (var i = 0; i < 156; i++) { - re8.exec('VCPhygher=ra-HF'); - re8.exec('CersreerqPhygher=ra-HF'); + re8.exec(s11[i]); + re8.exec(s12[i]); } for (var i = 0; i < 144; i++) { - re0.exec('xrlcerff'); + re0.exec(s13[i]); } for (var i = 0; i < 139; i++) { - '521'.replace(re6, ''); - re7.exec('521'); + s14[i].replace(re6, ''); + re7.exec(s14[i]); re9.exec(''); - /JroXvg\/(\S+)/.exec(str0); + /JroXvg\/(\S+)/.exec(s15[i]); } for (var i = 0; i < 137; i++) { - 'qvi .so_zrah'.replace(re10, ''); - 'qvi .so_zrah'.replace(/\[/g, ''); - 'qvi.so_zrah'.replace(re11, ''); + s16[i].replace(re10, ''); + s16[i].replace(/\[/g, ''); + s17[i].replace(re11, ''); } for (var i = 0; i < 117; i++) { - 'uvqqra_ryrz'.replace(re2, ''); + s18[i].replace(re2, ''); } for (var i = 0; i < 95; i++) { - /(?:^|;)\s*sevraqfgre_ynat=([^;]*)/.exec('sevraqfgre_naba=nvq%3Qn6ss9p85n868ro9s059pn854735956o3%26ers%3Q%26df%3Q%26vpgl%3QHF'); + /(?:^|;)\s*sevraqfgre_ynat=([^;]*)/.exec(s19[i]); } for (var i = 0; i < 93; i++) { - 'uggc://ubzr.zlfcnpr.pbz/vaqrk.psz'.replace(re12, ''); - re13.exec('uggc://ubzr.zlfcnpr.pbz/vaqrk.psz'); + s20[i].replace(re12, ''); + re13.exec(s20[i]); } for (var i = 0; i < 92; i++) { - str1.replace(/([a-zA-Z]|\s)+/, ''); + s21[i].replace(/([a-zA-Z]|\s)+/, ''); } for (var i = 0; i < 85; i++) { - 'svefg'.replace(re14, ''); - 'svefg'.replace(re15, ''); - 'uggc://cebsvyr.zlfcnpr.pbz/vaqrk.psz'.replace(re12, ''); - 'ynfg'.replace(re14, ''); - 'ynfg'.replace(re15, ''); - re16.exec('qvfcynl'); - re13.exec('uggc://cebsvyr.zlfcnpr.pbz/vaqrk.psz'); + s22[i].replace(re14, ''); + s22[i].replace(re15, ''); + s23[i].replace(re12, ''); + s24[i].replace(re14, ''); + s24[i].replace(re15, ''); + re16.exec(s25[i]); + re13.exec(s23[i]); } } var re17 = /(^|[^\\])\"\\\/Qngr\((-?[0-9]+)\)\\\/\"/g; @@ -145,64 +203,98 @@ function runRegExpBenchmark() { var str7 = ';;jvaqbj.IjPurpxZbhfrCbfvgvbaNQ_VQ=shapgvba(r){vs(!r)ine r=jvaqbj.rirag;ine c=-1;vs(d1)c=d1.EbyybssCnary;ine bo=IjTrgBow("IjCnayNQ_VQ_"+c);vs(bo&&bo.fglyr.ivfvovyvgl=="ivfvoyr"){ine fns=IjFns?8:0;ine pheK=r.pyvragK+IjBOFpe("U")+fns,pheL=r.pyvragL+IjBOFpe("I")+fns;ine y=IjBOEC(NQ_VQ,bo,"Y"),g=IjBOEC(NQ_VQ,bo,"G");ine e=y+d1.Cnaryf[c].Jvqgu,o=g+d1.Cnaryf[c].Urvtug;vs((pheKe)||(pheLo)){vs(jvaqbj.IjBaEbyybssNQ_VQ)IjBaEbyybssNQ_VQ(c);ryfr IjPybfrNq(NQ_VQ,c,gehr,"");}ryfr erghea;}IjPnapryZbhfrYvfgrareNQ_VQ();};;jvaqbj.IjFrgEbyybssCnaryNQ_VQ=shapgvba(c){ine z="zbhfrzbir",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;c=IjTc(NQ_VQ,c);vs(d1&&d1.EbyybssCnary>-1)IjPnapryZbhfrYvfgrareNQ_VQ();vs(d1)d1.EbyybssCnary=c;gel{vs(q.nqqRiragYvfgrare)q.nqqRiragYvfgrare(z,s,snyfr);ryfr vs(q.nggnpuRirag)q.nggnpuRirag("ba"+z,s);}pngpu(r){}};;jvaqbj.IjPnapryZbhfrYvfgrareNQ_VQ=shapgvba(){ine z="zbhfrzbir",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;vs(d1)d1.EbyybssCnary=-1;gel{vs(q.erzbirRiragYvfgrare)q.erzbirRiragYvfgrare(z,s,snyfr);ryfr vs(q.qrgnpuRirag)q.qrgnpuRirag("ba"+z,s);}pngpu(r){}};;d1.IjTc=d2(n,c){ine nq=d1;vs(vfAnA(c)){sbe(ine v=0;v0){vs(nq.FzV.yratgu>0)nq.FzV+="/";nq.FzV+=vh[v];nq.FtZ[nq.FtZ.yratgu]=snyfr;}}};;d1.IjYvzvg0=d2(n,f){ine nq=d1,vh=f.fcyvg("/");sbe(ine v=0;v0){vs(nq.OvC.yratgu>0)nq.OvC+="/";nq.OvC+=vh[v];}}};;d1.IjRVST=d2(n,c){jvaqbj["IjCnayNQ_VQ_"+c+"_Bow"]=IjTrgBow("IjCnayNQ_VQ_"+c+"_Bow");vs(jvaqbj["IjCnayNQ_VQ_"+c+"_Bow"]==ahyy)frgGvzrbhg("IjRVST(NQ_VQ,"+c+")",d1.rvsg);};;d1.IjNavzSHC=d2(n,c){ine nq=d1;vs(c>nq.Cnaryf.yratgu)erghea;ine cna=nq.Cnaryf[c],nn=gehr,on=gehr,yn=gehr,en=gehr,cn=nq.Cnaryf[0],sf=nq.ShF,j=cn.Jvqgu,u=cn.Urvtug;vs(j=="100%"){j=sf;en=snyfr;yn=snyfr;}vs(u=="100%"){u=sf;nn=snyfr;on=snyfr;}vs(cn.YnY=="Y")yn=snyfr;vs(cn.YnY=="E")en=snyfr;vs(cn.GnY=="G")nn=snyfr;vs(cn.GnY=="O")on=snyfr;ine k=0,l=0;fjvgpu(nq.NshP%8){pnfr 0:oernx;pnfr 1:vs(nn)l=-sf;oernx;pnfr 2:k=j-sf;oernx;pnfr 3:vs(en)k=j;oernx;pnfr 4:k=j-sf;l=u-sf;oernx;pnfr 5:k=j-sf;vs(on)l=u;oernx;pnfr 6:l=u-sf;oernx;pnfr 7:vs(yn)k=-sf;l=u-sf;oernx;}vs(nq.NshP++ 0)||(nethzragf.yratgu==3&&bG>0))){pyrneGvzrbhg(cay.UgU);cay.UgU=frgGvzrbhg(cay.UvqrNpgvba,(nethzragf.yratgu==3?bG:cay.UvqrGvzrbhgInyhr));}};;d1.IjErfrgGvzrbhg=d2(n,c,bG){c=IjTc(n,c);IjPnapryGvzrbhg(n,c);riny("IjFgnegGvzrbhg(NQ_VQ,c"+(nethzragf.yratgu==3?",bG":"")+")");};;d1.IjErfrgNyyGvzrbhgf=d2(n){sbe(ine c=0;c'.replace(re55, ''); ''.replace(re55, ''); - str1.replace(/^.*\s+(\S+\s+\S+$)/, ''); + s21[i].replace(/^.*\s+(\S+\s+\S+$)/, ''); 'tzk%2Subzrcntr%2Sfgneg%2Sqr%2S'.replace(re30, ''); 'tzk'.replace(re30, ''); 'uggc://${ubfg}${cngu}/${dz}'.replace(/(\$\{ubfg\})|(\$ubfg\b)/g, ''); @@ -549,61 +671,70 @@ function runRegExpBenchmark() { var re62 = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/; var str34 = '${1}://${2}${3}${4}${5}'; var str35 = ' O=6gnyg0g4znrrn&o=3&f=gc; Q=_lyu=K3bQZGSxnT4lZzD3OS9GNmV3ZGLkAQxRpTyxNmRlZmRmAmNkAQLRqTImqNZjOUEgpTjQnJ5xMKtgoN--; SCF=qy'; + var s83 = computeInputVariants(str27, 11); + var s84 = computeInputVariants(str28, 11); + var s85 = computeInputVariants(str29, 11); + var s86 = computeInputVariants(str30, 11); + var s87 = computeInputVariants(str31, 11); + var s88 = computeInputVariants(str32, 11); + var s89 = computeInputVariants(str33, 11); + var s90 = computeInputVariants(str34, 11); + function runBlock6() { for (var i = 0; i < 11; i++) { - str27.replace(/##yv0##/gi, ''); - str27.replace(re57, ''); - str28.replace(re58, ''); - str29.replace(re59, ''); - str30.replace(/##\/o##/gi, ''); - str30.replace(/##\/v##/gi, ''); - str30.replace(/##\/h##/gi, ''); - str30.replace(/##o##/gi, ''); - str30.replace(/##oe##/gi, ''); - str30.replace(/##v##/gi, ''); - str30.replace(/##h##/gi, ''); - str31.replace(/##n##/gi, ''); - str32.replace(/##\/n##/gi, ''); - str33.replace(/#~#argjbexybtb#~#/g, ''); - / Zbovyr\//.exec(str0); - /##yv1##/gi.exec(str27); - /##yv10##/gi.exec(str28); - /##yv11##/gi.exec(str28); - /##yv12##/gi.exec(str28); - /##yv13##/gi.exec(str28); - /##yv14##/gi.exec(str28); - /##yv15##/gi.exec(str28); - re58.exec(str28); - /##yv17##/gi.exec(str29); - /##yv18##/gi.exec(str29); - re59.exec(str29); - /##yv2##/gi.exec(str27); - /##yv20##/gi.exec(str30); - /##yv21##/gi.exec(str30); - /##yv22##/gi.exec(str30); - /##yv23##/gi.exec(str30); - /##yv3##/gi.exec(str27); - re57.exec(str27); - /##yv5##/gi.exec(str28); - /##yv6##/gi.exec(str28); - /##yv7##/gi.exec(str28); - /##yv8##/gi.exec(str28); - /##yv9##/gi.exec(str28); + s83[i].replace(/##yv0##/gi, ''); + s83[i].replace(re57, ''); + s84[i].replace(re58, ''); + s85[i].replace(re59, ''); + s86[i].replace(/##\/o##/gi, ''); + s86[i].replace(/##\/v##/gi, ''); + s86[i].replace(/##\/h##/gi, ''); + s86[i].replace(/##o##/gi, ''); + s86[i].replace(/##oe##/gi, ''); + s86[i].replace(/##v##/gi, ''); + s86[i].replace(/##h##/gi, ''); + s87[i].replace(/##n##/gi, ''); + s88[i].replace(/##\/n##/gi, ''); + s89[i].replace(/#~#argjbexybtb#~#/g, ''); + / Zbovyr\//.exec(s15[i]); + /##yv1##/gi.exec(s83[i]); + /##yv10##/gi.exec(s84[i]); + /##yv11##/gi.exec(s84[i]); + /##yv12##/gi.exec(s84[i]); + /##yv13##/gi.exec(s84[i]); + /##yv14##/gi.exec(s84[i]); + /##yv15##/gi.exec(s84[i]); + re58.exec(s84[i]); + /##yv17##/gi.exec(s85[i]); + /##yv18##/gi.exec(s85[i]); + re59.exec(s85[i]); + /##yv2##/gi.exec(s83[i]); + /##yv20##/gi.exec(s86[i]); + /##yv21##/gi.exec(s86[i]); + /##yv22##/gi.exec(s86[i]); + /##yv23##/gi.exec(s86[i]); + /##yv3##/gi.exec(s83[i]); + re57.exec(s83[i]); + /##yv5##/gi.exec(s84[i]); + /##yv6##/gi.exec(s84[i]); + /##yv7##/gi.exec(s84[i]); + /##yv8##/gi.exec(s84[i]); + /##yv9##/gi.exec(s84[i]); re8.exec('473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29'); re8.exec('SbeprqRkcvengvba=633669325184628362'); re8.exec('FrffvbaQQS2=473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29'); - /AbxvnA[^\/]*/.exec(str0); + /AbxvnA[^\/]*/.exec(s15[i]); } for (var i = 0; i < 10; i++) { ' bss'.replace(/(?:^|\s+)bss(?:\s+|$)/g, ''); - str34.replace(/(\$\{0\})|(\$0\b)/g, ''); - str34.replace(/(\$\{1\})|(\$1\b)/g, ''); - str34.replace(/(\$\{pbzcyrgr\})|(\$pbzcyrgr\b)/g, ''); - str34.replace(/(\$\{sentzrag\})|(\$sentzrag\b)/g, ''); - str34.replace(/(\$\{ubfgcbeg\})|(\$ubfgcbeg\b)/g, ''); - str34.replace(re56, ''); - str34.replace(/(\$\{cebgbpby\})|(\$cebgbpby\b)/g, ''); - str34.replace(/(\$\{dhrel\})|(\$dhrel\b)/g, ''); + s90[i].replace(/(\$\{0\})|(\$0\b)/g, ''); + s90[i].replace(/(\$\{1\})|(\$1\b)/g, ''); + s90[i].replace(/(\$\{pbzcyrgr\})|(\$pbzcyrgr\b)/g, ''); + s90[i].replace(/(\$\{sentzrag\})|(\$sentzrag\b)/g, ''); + s90[i].replace(/(\$\{ubfgcbeg\})|(\$ubfgcbeg\b)/g, ''); + s90[i].replace(re56, ''); + s90[i].replace(/(\$\{cebgbpby\})|(\$cebgbpby\b)/g, ''); + s90[i].replace(/(\$\{dhrel\})|(\$dhrel\b)/g, ''); 'nqfvmr'.replace(re29, ''); 'nqfvmr'.replace(re30, ''); 'uggc://${2}${3}${4}${5}'.replace(/(\$\{2\})|(\$2\b)/g, ''); @@ -629,7 +760,7 @@ function runRegExpBenchmark() { re9.exec('zrqvgobk'); re9.exec('hsgy'); re9.exec('lhv-h'); - /Fnsnev|Xbadhrebe|XUGZY/gi.exec(str0); + /Fnsnev|Xbadhrebe|XUGZY/gi.exec(s15[i]); re61.exec('uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf'); re62.exec('#Ybtva_rznvy'); } @@ -640,6 +771,9 @@ function runRegExpBenchmark() { var str38 = 'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231364057761&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231364057761&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Ssevraqf.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1667363813.1231364061&tn_fvq=1231364061&tn_uvq=1917563877&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22'; var str39 = 'ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669321699093060&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q'; var str40 = 'ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669321699093060&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R='; + var s91 = computeInputVariants(str36, 9); + var s92 = computeInputVariants(str37, 9); + var s93 = computeInputVariants(str38, 9); function runBlock7() { for (var i = 0; i < 9; i++) { '0'.replace(re40, ''); @@ -660,15 +794,15 @@ function runRegExpBenchmark() { for (var i = 0; i < 8; i++) { 'Pybfr {0}'.replace(re63, ''); 'Bcra {0}'.replace(re63, ''); - str36.split(re32); - str37.split(re32); + s91[i].split(re32); + s92[i].split(re32); 'puvyq p1 svefg gnournqref'.replace(re14, ''); 'puvyq p1 svefg gnournqref'.replace(re15, ''); 'uqy_fcb'.replace(re14, ''); 'uqy_fcb'.replace(re15, ''); 'uvag'.replace(re14, ''); 'uvag'.replace(re15, ''); - str38.replace(re33, ''); + s93[i].replace(re33, ''); 'yvfg'.replace(re14, ''); 'yvfg'.replace(re15, ''); 'at_bhgre'.replace(re30, ''); @@ -697,8 +831,8 @@ function runRegExpBenchmark() { re8.exec('__hgzo=144631658.0.10.1231364074'); re8.exec('__hgzm=144631658.1231364074.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)'); re8.exec('p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7'); - re34.exec(str36); - re34.exec(str37); + re34.exec(s91[i]); + re34.exec(s92[i]); } } var re64 = /\b[a-z]/g; @@ -707,7 +841,7 @@ function runRegExpBenchmark() { var str41 = 'uggc://cebsvyr.zlfcnpr.pbz/Zbqhyrf/Nccyvpngvbaf/Cntrf/Pnainf.nfck'; function runBlock8() { for (var i = 0; i < 7; i++) { - str1.match(/\d+/g); + s21[i].match(/\d+/g); 'nsgre'.replace(re64, ''); 'orsber'.replace(re64, ''); 'obggbz'.replace(re64, ''); @@ -741,9 +875,9 @@ function runRegExpBenchmark() { re19.exec('gno6'); re19.exec('gno7'); re19.exec('gno8'); - /NqborNVE\/([^\s]*)/.exec(str0); - /NccyrJroXvg\/([^ ]*)/.exec(str0); - /XUGZY/gi.exec(str0); + /NqborNVE\/([^\s]*)/.exec(s15[i]); + /NccyrJroXvg\/([^ ]*)/.exec(s15[i]); + /XUGZY/gi.exec(s15[i]); /^(?:obql|ugzy)$/i.exec('YV'); re38.exec('ohggba'); re38.exec('vachg'); @@ -774,14 +908,14 @@ function runRegExpBenchmark() { 'freivpr'.replace(re46, ''); 'freivpr'.replace(re47, ''); 'freivpr'.replace(re48, ''); - /((ZFVR\s+([6-9]|\d\d)\.))/.exec(str0); + /((ZFVR\s+([6-9]|\d\d)\.))/.exec(s15[i]); re66.exec(''); re50.exec('fryrpgrq'); re8.exec('8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn'); re8.exec('SbeprqRkcvengvba=633669340386893867'); re8.exec('VC=74.125.75.17'); re8.exec('FrffvbaQQS2=8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn'); - /Xbadhrebe|Fnsnev|XUGZY/.exec(str0); + /Xbadhrebe|Fnsnev|XUGZY/.exec(s15[i]); re13.exec(str41); re49.exec('unfsbphf'); } @@ -826,12 +960,23 @@ function runRegExpBenchmark() { var str61 = 'uggc://gx2.fgp.f-zfa.pbz/oe/uc/11/ra-hf/pff/v/g.tvs#uggc://gx2.fgo.f-zfa.pbz/v/29/4RQP4969777N048NPS4RRR3PO2S7S.wct'; var str62 = 'uggc://gx2.fgp.f-zfa.pbz/oe/uc/11/ra-hf/pff/v/g.tvs#uggc://gx2.fgo.f-zfa.pbz/v/OQ/63NP9O94NS5OQP1249Q9S1ROP7NS3.wct'; var str63 = 'zbmvyyn/5.0 (jvaqbjf; h; jvaqbjf ag 5.1; ra-hf) nccyrjroxvg/528.9 (xugzy, yvxr trpxb) puebzr/2.0.157.0 fnsnev/528.9'; + var s94 = computeInputVariants(str42, 5); + var s95 = computeInputVariants(str43, 5); + var s96 = computeInputVariants(str44, 5); + var s97 = computeInputVariants(str47, 5); + var s98 = computeInputVariants(str48, 5); + var s99 = computeInputVariants(str49, 5); + var s100 = computeInputVariants(str50, 5); + var s101 = computeInputVariants(str51, 5); + var s102 = computeInputVariants(str52, 5); + var s103 = computeInputVariants(str53, 5); + function runBlock9() { for (var i = 0; i < 5; i++) { - str42.split(re32); - str43.split(re32); + s94[i].split(re32); + s95[i].split(re32); 'svz_zlfcnpr_hfre-ivrj-pbzzragf,svz_zlfcnpr_havgrq-fgngrf'.split(re20); - str44.replace(re33, ''); + s96[i].replace(re33, ''); 'zrah_arj zrah_arj_gbttyr zrah_gbttyr'.replace(re67, ''); 'zrah_byq zrah_byq_gbttyr zrah_gbttyr'.replace(re67, ''); re8.exec('102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98'); @@ -855,12 +1000,12 @@ function runRegExpBenchmark() { ' yvfg2'.replace(re15, ''); ' frneputebhc1'.replace(re14, ''); ' frneputebhc1'.replace(re15, ''); - str47.replace(re68, ''); - str47.replace(re18, ''); + s97[i].replace(re68, ''); + s97[i].replace(re18, ''); ''.replace(/&/g, ''); ''.replace(re35, ''); '(..-{0})(\|(\d+)|)'.replace(re63, ''); - str48.replace(re18, ''); + s98[i].replace(re18, ''); '//vzt.jro.qr/vij/FC/${cngu}/${anzr}/${inyhr}?gf=${abj}'.replace(re56, ''); '//vzt.jro.qr/vij/FC/tzk_uc/${anzr}/${inyhr}?gf=${abj}'.replace(/(\$\{anzr\})|(\$anzr\b)/g, ''); 'Jvaqbjf Yvir Ubgznvy{1}'.replace(re69, ''); @@ -872,8 +1017,8 @@ function runRegExpBenchmark() { 'Zncf'.replace(re15, ''); 'Zbq-Vasb-Vasb-WninFpevcgUvag'.replace(re39, ''); 'Arjf'.replace(re15, ''); - str49.split(re32); - str50.split(re32); + s99[i].split(re32); + s100[i].split(re32); 'Ivqrb'.replace(re15, ''); 'Jro'.replace(re15, ''); 'n'.replace(re39, ''); @@ -907,17 +1052,17 @@ function runRegExpBenchmark() { 'uc_fubccvatobk'.replace(re30, ''); 'ugzy%2Rvq'.replace(re29, ''); 'ugzy%2Rvq'.replace(re30, ''); - str51.replace(re33, ''); + s101[i].replace(re33, ''); 'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/cebgbglcr.wf${4}${5}'.replace(re71, ''); 'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/cebgbglcr.wf${5}'.replace(re72, ''); - str52.replace(re73, ''); + s102[i].replace(re73, ''); 'uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55332979829981?[NDO]&{1}&{2}&[NDR]'.replace(re69, ''); 'vztZFSG'.replace(re14, ''); 'vztZFSG'.replace(re15, ''); 'zfasbbg1 ps'.replace(re14, ''); 'zfasbbg1 ps'.replace(re15, ''); - str53.replace(re14, ''); - str53.replace(re15, ''); + s103[i].replace(re14, ''); + s103[i].replace(re15, ''); 'cnerag puebzr6 fvatyr1 gno fryrpgrq ovaq'.replace(re14, ''); 'cnerag puebzr6 fvatyr1 gno fryrpgrq ovaq'.replace(re15, ''); 'cevznel'.replace(re14, ''); @@ -945,11 +1090,11 @@ function runRegExpBenchmark() { re8.exec('__hgzn=144631658.2770915348920628700.1231367708.1231367708.1231367708.1'); re8.exec('__hgzo=144631658.0.10.1231367708'); re8.exec('__hgzm=144631658.1231367708.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)'); - re34.exec(str49); - re34.exec(str50); - /ZFVR\s+5[.]01/.exec(str0); + re34.exec(s99[i]); + re34.exec(s100[i]); + /ZFVR\s+5[.]01/.exec(s15[i]); /HF(?=;)/i.exec(str56); - re74.exec(str47); + re74.exec(s97[i]); re28.exec('svefg npgvir svefgNpgvir'); re28.exec('ynfg'); /\bp:(..)/i.exec('m:94043|yn:37.4154|yb:-122.0585|p:HF'); @@ -967,15 +1112,15 @@ function runRegExpBenchmark() { re79.exec(str60); re79.exec(str59); /\|p:([a-z]{2})/i.exec('m:94043|yn:37.4154|yb:-122.0585|p:HF|ue:1'); - re80.exec(str47); + re80.exec(s97[i]); re61.exec('cebgbglcr.wf'); - re68.exec(str47); - re81.exec(str47); - re82.exec(str47); - /^Fubpxjnir Synfu (\d)/.exec(str1); - /^Fubpxjnir Synfu (\d+)/.exec(str1); + re68.exec(s97[i]); + re81.exec(s97[i]); + re82.exec(s97[i]); + /^Fubpxjnir Synfu (\d)/.exec(s21[i]); + /^Fubpxjnir Synfu (\d+)/.exec(s21[i]); re83.exec('[bowrpg tybony]'); - re62.exec(str47); + re62.exec(s97[i]); re84.exec(str61); re84.exec(str62); /jroxvg/.exec(str63); @@ -1597,18 +1742,23 @@ function runRegExpBenchmark() { /jvaqbjf/.exec(str63); } } - for (var i = 0; i < 5; i++) { - runBlock0(); - runBlock1(); - runBlock2(); - runBlock3(); - runBlock4(); - runBlock5(); - runBlock6(); - runBlock7(); - runBlock8(); - runBlock9(); - runBlock10(); - runBlock11(); + + function run() { + for (var i = 0; i < 5; i++) { + runBlock0(); + runBlock1(); + runBlock2(); + runBlock3(); + runBlock4(); + runBlock5(); + runBlock6(); + runBlock7(); + runBlock8(); + runBlock9(); + runBlock10(); + runBlock11(); + } } + + this.run = run; } diff --git a/deps/v8/benchmarks/revisions.html b/deps/v8/benchmarks/revisions.html index 1c54f63462..6ff75be1e1 100644 --- a/deps/v8/benchmarks/revisions.html +++ b/deps/v8/benchmarks/revisions.html @@ -26,7 +26,9 @@ the benchmark suite. typos in the DeltaBlue implementation. Changed the Splay benchmark to avoid converting the same numeric key to a string over and over again and to avoid inserting and removing the same element repeatedly thus -increasing pressure on the memory subsystem.

+increasing pressure on the memory subsystem. Changed the RegExp +benchmark to exercise the regular expression engine on different input +strings.

Furthermore, the benchmark runner was changed to run the benchmarks for at least a few times to stabilize the reported numbers on slower diff --git a/deps/v8/benchmarks/run.html b/deps/v8/benchmarks/run.html index 05bfffee02..36d2ad511b 100644 --- a/deps/v8/benchmarks/run.html +++ b/deps/v8/benchmarks/run.html @@ -114,7 +114,7 @@ higher scores means better performance: Bigger is better!

  • RayTrace
    Ray tracer benchmark based on code by Adam Burmister (904 lines).
  • EarleyBoyer
    Classic Scheme benchmarks, translated to JavaScript by Florian Loitsch's Scheme2Js compiler (4684 lines).
  • RegExp
    Regular expression benchmark generated by extracting regular expression operations from 50 of the most popular web pages -(1614 lines). +(1761 lines).
  • Splay
    Data manipulation benchmark that deals with splay trees and exercises the automatic memory management subsystem (394 lines).
  • diff --git a/deps/v8/include/v8-debug.h b/deps/v8/include/v8-debug.h old mode 100644 new mode 100755 index 414fd8622a..4314727adc --- a/deps/v8/include/v8-debug.h +++ b/deps/v8/include/v8-debug.h @@ -253,9 +253,12 @@ class EXPORT Debug { static bool SetDebugEventListener(v8::Handle that, Handle data = Handle()); - // Break execution of JavaScript. + // Schedule a debugger break to happen when JavaScript code is run. static void DebugBreak(); + // Remove scheduled debugger break if it has not happened yet. + static void CancelDebugBreak(); + // Break execution of JavaScript (this method can be invoked from a // non-VM thread) for further client command execution on a VM // thread. Client data is then passed in EventDetails to diff --git a/deps/v8/src/SConscript b/deps/v8/src/SConscript index e2b01aaf98..05ccae4a98 100755 --- a/deps/v8/src/SConscript +++ b/deps/v8/src/SConscript @@ -100,6 +100,7 @@ SOURCES = { serialize.cc snapshot-common.cc spaces.cc + string-search.cc string-stream.cc stub-cache.cc token.cc diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index e09d4c954c..b7d85c68a1 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -134,27 +134,27 @@ void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) { heap_stats.new_space_size = &new_space_size; int new_space_capacity; heap_stats.new_space_capacity = &new_space_capacity; - int old_pointer_space_size; + intptr_t old_pointer_space_size; heap_stats.old_pointer_space_size = &old_pointer_space_size; - int old_pointer_space_capacity; + intptr_t old_pointer_space_capacity; heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity; - int old_data_space_size; + intptr_t old_data_space_size; heap_stats.old_data_space_size = &old_data_space_size; - int old_data_space_capacity; + intptr_t old_data_space_capacity; heap_stats.old_data_space_capacity = &old_data_space_capacity; - int code_space_size; + intptr_t code_space_size; heap_stats.code_space_size = &code_space_size; - int code_space_capacity; + intptr_t code_space_capacity; heap_stats.code_space_capacity = &code_space_capacity; - int map_space_size; + intptr_t map_space_size; heap_stats.map_space_size = &map_space_size; - int map_space_capacity; + intptr_t map_space_capacity; heap_stats.map_space_capacity = &map_space_capacity; - int cell_space_size; + intptr_t cell_space_size; heap_stats.cell_space_size = &cell_space_size; - int cell_space_capacity; + intptr_t cell_space_capacity; heap_stats.cell_space_capacity = &cell_space_capacity; - int lo_space_size; + intptr_t lo_space_size; heap_stats.lo_space_size = &lo_space_size; int global_handle_count; heap_stats.global_handle_count = &global_handle_count; @@ -166,9 +166,9 @@ void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) { heap_stats.near_death_global_handle_count = &near_death_global_handle_count; int destroyed_global_handle_count; heap_stats.destroyed_global_handle_count = &destroyed_global_handle_count; - int memory_allocator_size; + intptr_t memory_allocator_size; heap_stats.memory_allocator_size = &memory_allocator_size; - int memory_allocator_capacity; + intptr_t memory_allocator_capacity; heap_stats.memory_allocator_capacity = &memory_allocator_capacity; int objects_per_type[LAST_TYPE + 1] = {0}; heap_stats.objects_per_type = objects_per_type; @@ -767,6 +767,12 @@ int TypeSwitch::match(v8::Handle value) { } +#define SET_FIELD_WRAPPED(obj, setter, cdata) do { \ + i::Handle proxy = FromCData(cdata); \ + (obj)->setter(*proxy); \ + } while (false) + + void FunctionTemplate::SetCallHandler(InvocationCallback callback, v8::Handle data) { if (IsDeadCheck("v8::FunctionTemplate::SetCallHandler()")) return; @@ -776,7 +782,7 @@ void FunctionTemplate::SetCallHandler(InvocationCallback callback, i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE); i::Handle obj = i::Handle::cast(struct_obj); - obj->set_callback(*FromCData(callback)); + SET_FIELD_WRAPPED(obj, set_callback, callback); if (data.IsEmpty()) data = v8::Undefined(); obj->set_data(*Utils::OpenHandle(*data)); Utils::OpenHandle(this)->set_call_code(*obj); @@ -792,8 +798,8 @@ static i::Handle MakeAccessorInfo( v8::PropertyAttribute attributes) { i::Handle obj = i::Factory::NewAccessorInfo(); ASSERT(getter != NULL); - obj->set_getter(*FromCData(getter)); - obj->set_setter(*FromCData(setter)); + SET_FIELD_WRAPPED(obj, set_getter, getter); + SET_FIELD_WRAPPED(obj, set_setter, setter); if (data.IsEmpty()) data = v8::Undefined(); obj->set_data(*Utils::OpenHandle(*data)); obj->set_name(*Utils::OpenHandle(*name)); @@ -877,11 +883,13 @@ void FunctionTemplate::SetNamedInstancePropertyHandler( i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE); i::Handle obj = i::Handle::cast(struct_obj); - if (getter != 0) obj->set_getter(*FromCData(getter)); - if (setter != 0) obj->set_setter(*FromCData(setter)); - if (query != 0) obj->set_query(*FromCData(query)); - if (remover != 0) obj->set_deleter(*FromCData(remover)); - if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator)); + + if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter); + if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter); + if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query); + if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover); + if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator); + if (data.IsEmpty()) data = v8::Undefined(); obj->set_data(*Utils::OpenHandle(*data)); Utils::OpenHandle(this)->set_named_property_handler(*obj); @@ -905,11 +913,13 @@ void FunctionTemplate::SetIndexedInstancePropertyHandler( i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE); i::Handle obj = i::Handle::cast(struct_obj); - if (getter != 0) obj->set_getter(*FromCData(getter)); - if (setter != 0) obj->set_setter(*FromCData(setter)); - if (query != 0) obj->set_query(*FromCData(query)); - if (remover != 0) obj->set_deleter(*FromCData(remover)); - if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator)); + + if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter); + if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter); + if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query); + if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover); + if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator); + if (data.IsEmpty()) data = v8::Undefined(); obj->set_data(*Utils::OpenHandle(*data)); Utils::OpenHandle(this)->set_indexed_property_handler(*obj); @@ -928,7 +938,7 @@ void FunctionTemplate::SetInstanceCallAsFunctionHandler( i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE); i::Handle obj = i::Handle::cast(struct_obj); - obj->set_callback(*FromCData(callback)); + SET_FIELD_WRAPPED(obj, set_callback, callback); if (data.IsEmpty()) data = v8::Undefined(); obj->set_data(*Utils::OpenHandle(*data)); Utils::OpenHandle(this)->set_instance_call_handler(*obj); @@ -1043,8 +1053,10 @@ void ObjectTemplate::SetAccessCheckCallbacks( i::Factory::NewStruct(i::ACCESS_CHECK_INFO_TYPE); i::Handle info = i::Handle::cast(struct_info); - info->set_named_callback(*FromCData(named_callback)); - info->set_indexed_callback(*FromCData(indexed_callback)); + + SET_FIELD_WRAPPED(info, set_named_callback, named_callback); + SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback); + if (data.IsEmpty()) data = v8::Undefined(); info->set_data(*Utils::OpenHandle(*data)); @@ -2646,8 +2658,9 @@ void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) { return; } i::Handle pixels = i::Factory::NewPixelArray(length, data); - self->set_map( - *i::Factory::GetSlowElementsMap(i::Handle(self->map()))); + i::Handle slow_map = + i::Factory::GetSlowElementsMap(i::Handle(self->map())); + self->set_map(*slow_map); self->set_elements(*pixels); } @@ -2701,8 +2714,9 @@ void v8::Object::SetIndexedPropertiesToExternalArrayData( } i::Handle array = i::Factory::NewExternalArray(length, array_type, data); - self->set_map( - *i::Factory::GetSlowElementsMap(i::Handle(self->map()))); + i::Handle slow_map = + i::Factory::GetSlowElementsMap(i::Handle(self->map())); + self->set_map(*slow_map); self->set_elements(*array); } @@ -4251,6 +4265,11 @@ void Debug::DebugBreak() { } +void Debug::CancelDebugBreak() { + i::StackGuard::Continue(i::DEBUGBREAK); +} + + void Debug::DebugBreakForCommand(ClientData* data) { if (!i::V8::IsRunning()) return; i::Debugger::EnqueueDebugCommand(data); @@ -4433,7 +4452,7 @@ double CpuProfileNode::GetSelfSamplesCount() const { unsigned CpuProfileNode::GetCallUid() const { IsDeadCheck("v8::CpuProfileNode::GetCallUid"); - return reinterpret_cast(this)->entry()->call_uid(); + return reinterpret_cast(this)->entry()->GetCallUid(); } diff --git a/deps/v8/src/arm/assembler-arm.h b/deps/v8/src/arm/assembler-arm.h index be9aa92f1a..1c4fd6094d 100644 --- a/deps/v8/src/arm/assembler-arm.h +++ b/deps/v8/src/arm/assembler-arm.h @@ -69,13 +69,13 @@ namespace internal { // // Core register struct Register { - bool is_valid() const { return 0 <= code_ && code_ < 16; } - bool is(Register reg) const { return code_ == reg.code_; } - int code() const { + bool is_valid() const { return 0 <= code_ && code_ < 16; } + bool is(Register reg) const { return code_ == reg.code_; } + int code() const { ASSERT(is_valid()); return code_; } - int bit() const { + int bit() const { ASSERT(is_valid()); return 1 << code_; } @@ -110,17 +110,17 @@ const Register pc = { 15 }; // Single word VFP register. struct SwVfpRegister { - bool is_valid() const { return 0 <= code_ && code_ < 32; } - bool is(SwVfpRegister reg) const { return code_ == reg.code_; } - int code() const { + bool is_valid() const { return 0 <= code_ && code_ < 32; } + bool is(SwVfpRegister reg) const { return code_ == reg.code_; } + int code() const { ASSERT(is_valid()); return code_; } - int bit() const { + int bit() const { ASSERT(is_valid()); return 1 << code_; } - void split_code(int* vm, int* m) const { + void split_code(int* vm, int* m) const { ASSERT(is_valid()); *m = code_ & 0x1; *vm = code_ >> 1; @@ -133,31 +133,31 @@ struct SwVfpRegister { // Double word VFP register. struct DwVfpRegister { // Supporting d0 to d15, can be later extended to d31. - bool is_valid() const { return 0 <= code_ && code_ < 16; } - bool is(DwVfpRegister reg) const { return code_ == reg.code_; } - SwVfpRegister low() const { + bool is_valid() const { return 0 <= code_ && code_ < 16; } + bool is(DwVfpRegister reg) const { return code_ == reg.code_; } + SwVfpRegister low() const { SwVfpRegister reg; reg.code_ = code_ * 2; ASSERT(reg.is_valid()); return reg; } - SwVfpRegister high() const { + SwVfpRegister high() const { SwVfpRegister reg; reg.code_ = (code_ * 2) + 1; ASSERT(reg.is_valid()); return reg; } - int code() const { + int code() const { ASSERT(is_valid()); return code_; } - int bit() const { + int bit() const { ASSERT(is_valid()); return 1 << code_; } - void split_code(int* vm, int* m) const { + void split_code(int* vm, int* m) const { ASSERT(is_valid()); *m = (code_ & 0x10) >> 4; *vm = code_ & 0x0F; @@ -222,13 +222,13 @@ const DwVfpRegister d15 = { 15 }; // Coprocessor register struct CRegister { - bool is_valid() const { return 0 <= code_ && code_ < 16; } - bool is(CRegister creg) const { return code_ == creg.code_; } - int code() const { + bool is_valid() const { return 0 <= code_ && code_ < 16; } + bool is(CRegister creg) const { return code_ == creg.code_; } + int code() const { ASSERT(is_valid()); return code_; } - int bit() const { + int bit() const { ASSERT(is_valid()); return 1 << code_; } diff --git a/deps/v8/src/arm/builtins-arm.cc b/deps/v8/src/arm/builtins-arm.cc index 8b21558165..cf2f426243 100644 --- a/deps/v8/src/arm/builtins-arm.cc +++ b/deps/v8/src/arm/builtins-arm.cc @@ -521,7 +521,11 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { static void Generate_JSConstructStubHelper(MacroAssembler* masm, - bool is_api_function) { + bool is_api_function, + bool count_constructions) { + // Should never count constructions for api objects. + ASSERT(!is_api_function || !count_constructions); + // Enter a construct frame. __ EnterConstructFrame(); @@ -530,9 +534,6 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, __ push(r0); // Smi-tagged arguments count. __ push(r1); // Constructor function. - // Use r7 for holding undefined which is used in several places below. - __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); - // Try to allocate the object without transitioning into C code. If any of the // preconditions is not met, the code bails out to the runtime call. Label rt_call, allocated; @@ -549,7 +550,6 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, // Load the initial map and verify that it is in fact a map. // r1: constructor function - // r7: undefined value __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); __ tst(r2, Operand(kSmiTagMask)); __ b(eq, &rt_call); @@ -561,14 +561,35 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, // instance type would be JS_FUNCTION_TYPE. // r1: constructor function // r2: initial map - // r7: undefined value __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); __ b(eq, &rt_call); + if (count_constructions) { + Label allocate; + // Decrease generous allocation count. + __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); + MemOperand constructor_count = + FieldMemOperand(r3, SharedFunctionInfo::kConstructionCountOffset); + __ ldrb(r4, constructor_count); + __ sub(r4, r4, Operand(1), SetCC); + __ strb(r4, constructor_count); + __ b(ne, &allocate); + + __ Push(r1, r2); + + __ push(r1); // constructor + // The call will replace the stub, so the countdown is only done once. + __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); + + __ pop(r2); + __ pop(r1); + + __ bind(&allocate); + } + // Now allocate the JSObject on the heap. // r1: constructor function // r2: initial map - // r7: undefined value __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset)); __ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS); @@ -578,7 +599,6 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, // r2: initial map // r3: object size // r4: JSObject (not tagged) - // r7: undefined value __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); __ mov(r5, r4); ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); @@ -588,16 +608,21 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset); __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); - // Fill all the in-object properties with undefined. + // Fill all the in-object properties with the appropriate filler. // r1: constructor function // r2: initial map // r3: object size (in words) // r4: JSObject (not tagged) // r5: First in-object property of JSObject (not tagged) - // r7: undefined value __ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object. ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize); { Label loop, entry; + if (count_constructions) { + // To allow for truncation. + __ LoadRoot(r7, Heap::kOnePointerFillerMapRootIndex); + } else { + __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); + } __ b(&entry); __ bind(&loop); __ str(r7, MemOperand(r5, kPointerSize, PostIndex)); @@ -617,7 +642,6 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, // r1: constructor function // r4: JSObject // r5: start of next object (not tagged) - // r7: undefined value __ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset)); // The field instance sizes contains both pre-allocated property fields and // in-object properties. @@ -637,7 +661,6 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, // r3: number of elements in properties array // r4: JSObject // r5: start of next object - // r7: undefined value __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize)); __ AllocateInNewSpace( r0, @@ -652,7 +675,6 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, // r3: number of elements in properties array // r4: JSObject // r5: FixedArray (not tagged) - // r7: undefined value __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex); __ mov(r2, r5); ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); @@ -667,10 +689,16 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, // r3: number of elements in properties array // r4: JSObject // r5: FixedArray (not tagged) - // r7: undefined __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2)); // End of object. ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize); { Label loop, entry; + if (count_constructions) { + __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); + } else if (FLAG_debug_code) { + __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); + __ cmp(r7, r8); + __ Assert(eq, "Undefined value not loaded."); + } __ b(&entry); __ bind(&loop); __ str(r7, MemOperand(r2, kPointerSize, PostIndex)); @@ -822,13 +850,18 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, } +void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { + Generate_JSConstructStubHelper(masm, false, true); +} + + void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { - Generate_JSConstructStubHelper(masm, false); + Generate_JSConstructStubHelper(masm, false, false); } void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { - Generate_JSConstructStubHelper(masm, true); + Generate_JSConstructStubHelper(masm, true, false); } diff --git a/deps/v8/src/arm/codegen-arm.cc b/deps/v8/src/arm/codegen-arm.cc index 6ba166f446..d273e75988 100644 --- a/deps/v8/src/arm/codegen-arm.cc +++ b/deps/v8/src/arm/codegen-arm.cc @@ -246,7 +246,7 @@ void CodeGenerator::Generate(CompilationInfo* info) { frame_->AssertIsSpilled(); for (int i = 0; i < scope()->num_parameters(); i++) { Variable* par = scope()->parameter(i); - Slot* slot = par->slot(); + Slot* slot = par->AsSlot(); if (slot != NULL && slot->type() == Slot::CONTEXT) { ASSERT(!scope()->is_global_scope()); // No params in global scope. __ ldr(r1, frame_->ParameterAt(i)); @@ -270,7 +270,7 @@ void CodeGenerator::Generate(CompilationInfo* info) { // Initialize ThisFunction reference if present. if (scope()->is_function_scope() && scope()->function() != NULL) { frame_->EmitPushRoot(Heap::kTheHoleValueRootIndex); - StoreToSlot(scope()->function()->slot(), NOT_CONST_INIT); + StoreToSlot(scope()->function()->AsSlot(), NOT_CONST_INIT); } // Initialize the function return target after the locals are set @@ -608,24 +608,24 @@ void CodeGenerator::StoreArgumentsObject(bool initial) { frame_->EmitPush(r0); } - Variable* arguments = scope()->arguments()->var(); - Variable* shadow = scope()->arguments_shadow()->var(); - ASSERT(arguments != NULL && arguments->slot() != NULL); - ASSERT(shadow != NULL && shadow->slot() != NULL); + Variable* arguments = scope()->arguments(); + Variable* shadow = scope()->arguments_shadow(); + ASSERT(arguments != NULL && arguments->AsSlot() != NULL); + ASSERT(shadow != NULL && shadow->AsSlot() != NULL); JumpTarget done; if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) { // We have to skip storing into the arguments slot if it has // already been written to. This can happen if the a function // has a local variable named 'arguments'. - LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF); + LoadFromSlot(scope()->arguments()->AsSlot(), NOT_INSIDE_TYPEOF); Register arguments = frame_->PopToRegister(); __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); __ cmp(arguments, ip); done.Branch(ne); } - StoreToSlot(arguments->slot(), NOT_CONST_INIT); + StoreToSlot(arguments->AsSlot(), NOT_CONST_INIT); if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind(); - StoreToSlot(shadow->slot(), NOT_CONST_INIT); + StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT); } @@ -641,10 +641,10 @@ void CodeGenerator::LoadTypeofExpression(Expression* expr) { Property property(&global, &key, RelocInfo::kNoPosition); Reference ref(this, &property); ref.GetValue(); - } else if (variable != NULL && variable->slot() != NULL) { + } else if (variable != NULL && variable->AsSlot() != NULL) { // For a variable that rewrites to a slot, we signal it is the immediate // subexpression of a typeof. - LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF); + LoadFromSlotCheckForArguments(variable->AsSlot(), INSIDE_TYPEOF); } else { // Anything else can be handled normally. Load(expr); @@ -695,7 +695,7 @@ void CodeGenerator::LoadReference(Reference* ref) { LoadGlobal(); ref->set_type(Reference::NAMED); } else { - ASSERT(var->slot() != NULL); + ASSERT(var->AsSlot() != NULL); ref->set_type(Reference::SLOT); } } else { @@ -1718,7 +1718,7 @@ void CodeGenerator::CallApplyLazy(Expression* applicand, // Load the receiver and the existing arguments object onto the // expression stack. Avoid allocating the arguments object here. Load(receiver); - LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF); + LoadFromSlot(scope()->arguments()->AsSlot(), NOT_INSIDE_TYPEOF); // At this point the top two stack elements are probably in registers // since they were just loaded. Ensure they are in regs and get the @@ -1950,7 +1950,7 @@ void CodeGenerator::VisitDeclaration(Declaration* node) { Comment cmnt(masm_, "[ Declaration"); Variable* var = node->proxy()->var(); ASSERT(var != NULL); // must have been resolved - Slot* slot = var->slot(); + Slot* slot = var->AsSlot(); // If it was not possible to allocate the variable at compile time, // we need to "declare" it at runtime to make sure it actually @@ -2480,8 +2480,8 @@ void CodeGenerator::VisitForStatement(ForStatement* node) { // the bottom check of the loop condition. TypeInfoCodeGenState type_info_scope(this, node->is_fast_smi_loop() ? - node->loop_variable()->slot() : - NULL, + node->loop_variable()->AsSlot() : + NULL, TypeInfo::Smi()); // If there is no update statement, label the top of the loop with the @@ -2794,8 +2794,8 @@ void CodeGenerator::VisitTryCatchStatement(TryCatchStatement* node) { // Store the caught exception in the catch variable. Variable* catch_var = node->catch_var()->var(); - ASSERT(catch_var != NULL && catch_var->slot() != NULL); - StoreToSlot(catch_var->slot(), NOT_CONST_INIT); + ASSERT(catch_var != NULL && catch_var->AsSlot() != NULL); + StoreToSlot(catch_var->AsSlot(), NOT_CONST_INIT); // Remove the exception from the stack. frame_->Drop(); @@ -3420,7 +3420,7 @@ void CodeGenerator::EmitDynamicLoadFromSlotFastCase(Slot* slot, } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { frame_->SpillAll(); - Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); + Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot(); Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); if (potential_slot != NULL) { // Generate fast case for locals that rewrite to slots. @@ -3449,7 +3449,7 @@ void CodeGenerator::EmitDynamicLoadFromSlotFastCase(Slot* slot, // variables. Then load the argument from the arguments // object using keyed load. __ ldr(r0, - ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(), + ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), r1, r2, slow)); @@ -3735,7 +3735,7 @@ void CodeGenerator::EmitSlotAssignment(Assignment* node) { Comment cmnt(masm(), "[ Variable Assignment"); Variable* var = node->target()->AsVariableProxy()->AsVariable(); ASSERT(var != NULL); - Slot* slot = var->slot(); + Slot* slot = var->AsSlot(); ASSERT(slot != NULL); // Evaluate the right-hand side. @@ -4136,14 +4136,14 @@ void CodeGenerator::VisitCall(Call* node) { // in generated code. If we succeed, there is no need to perform a // context lookup in the runtime system. JumpTarget done; - if (var->slot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) { - ASSERT(var->slot()->type() == Slot::LOOKUP); + if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) { + ASSERT(var->AsSlot()->type() == Slot::LOOKUP); JumpTarget slow; // Prepare the stack for the call to // ResolvePossiblyDirectEvalNoLookup by pushing the loaded // function, the first argument to the eval call and the // receiver. - LoadFromGlobalSlotCheckExtensions(var->slot(), + LoadFromGlobalSlotCheckExtensions(var->AsSlot(), NOT_INSIDE_TYPEOF, &slow); frame_->EmitPush(r0); @@ -4225,8 +4225,8 @@ void CodeGenerator::VisitCall(Call* node) { __ ldr(cp, frame_->Context()); frame_->EmitPush(r0); - } else if (var != NULL && var->slot() != NULL && - var->slot()->type() == Slot::LOOKUP) { + } else if (var != NULL && var->AsSlot() != NULL && + var->AsSlot()->type() == Slot::LOOKUP) { // ---------------------------------- // JavaScript examples: // @@ -4244,7 +4244,7 @@ void CodeGenerator::VisitCall(Call* node) { // Generate fast case for loading functions from slots that // correspond to local/global variables or arguments unless they // are shadowed by eval-introduced bindings. - EmitDynamicLoadFromSlotFastCase(var->slot(), + EmitDynamicLoadFromSlotFastCase(var->AsSlot(), NOT_INSIDE_TYPEOF, &slow, &done); @@ -5928,7 +5928,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { frame_->EmitPush(r0); } else if (variable != NULL) { - Slot* slot = variable->slot(); + Slot* slot = variable->AsSlot(); if (variable->is_global()) { LoadGlobal(); frame_->EmitPush(Operand(variable->name())); @@ -6062,7 +6062,7 @@ void CodeGenerator::VisitCountOperation(CountOperation* node) { bool is_const = (var != NULL && var->mode() == Variable::CONST); bool is_slot = (var != NULL && var->mode() == Variable::VAR); - if (!is_const && is_slot && type_info(var->slot()).IsSmi()) { + if (!is_const && is_slot && type_info(var->AsSlot()).IsSmi()) { // The type info declares that this variable is always a Smi. That // means it is a Smi both before and after the increment/decrement. // Lets make use of that to make a very minimal count. @@ -7207,7 +7207,7 @@ void Reference::GetValue() { switch (type_) { case SLOT: { Comment cmnt(masm, "[ Load from Slot"); - Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); + Slot* slot = expression_->AsVariableProxy()->AsVariable()->AsSlot(); ASSERT(slot != NULL); DupIfPersist(); cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); @@ -7251,7 +7251,7 @@ void Reference::SetValue(InitState init_state, WriteBarrierCharacter wb_info) { switch (type_) { case SLOT: { Comment cmnt(masm, "[ Store to Slot"); - Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); + Slot* slot = expression_->AsVariableProxy()->AsVariable()->AsSlot(); cgen_->StoreToSlot(slot, init_state); set_unloaded(); break; diff --git a/deps/v8/src/arm/codegen-arm.h b/deps/v8/src/arm/codegen-arm.h index d4c352260e..1483c0b545 100644 --- a/deps/v8/src/arm/codegen-arm.h +++ b/deps/v8/src/arm/codegen-arm.h @@ -307,9 +307,9 @@ class CodeGenerator: public AstVisitor { int NumberOfSlot(Slot* slot); // State - bool has_cc() const { return cc_reg_ != al; } - JumpTarget* true_target() const { return state_->true_target(); } - JumpTarget* false_target() const { return state_->false_target(); } + bool has_cc() const { return cc_reg_ != al; } + JumpTarget* true_target() const { return state_->true_target(); } + JumpTarget* false_target() const { return state_->false_target(); } // Track loop nesting level. int loop_nesting() const { return loop_nesting_; } diff --git a/deps/v8/src/arm/frames-arm.cc b/deps/v8/src/arm/frames-arm.cc index 47434392df..b0c0990306 100644 --- a/deps/v8/src/arm/frames-arm.cc +++ b/deps/v8/src/arm/frames-arm.cc @@ -37,17 +37,8 @@ namespace v8 { namespace internal { -StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) { - if (fp == 0) return NONE; - // Compute frame type and stack pointer. - Address sp = fp + ExitFrameConstants::kSPOffset; - - // Fill in the state. - state->sp = sp; - state->fp = fp; - state->pc_address = reinterpret_cast(sp - 1 * kPointerSize); - ASSERT(*state->pc_address != NULL); - return EXIT; +Address ExitFrame::ComputeStackPointer(Address fp) { + return fp + ExitFrameConstants::kSPOffset; } diff --git a/deps/v8/src/arm/full-codegen-arm.cc b/deps/v8/src/arm/full-codegen-arm.cc index c776d67cca..9fc0c096bb 100644 --- a/deps/v8/src/arm/full-codegen-arm.cc +++ b/deps/v8/src/arm/full-codegen-arm.cc @@ -100,7 +100,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { // Copy any necessary parameters into the context. int num_parameters = scope()->num_parameters(); for (int i = 0; i < num_parameters; i++) { - Slot* slot = scope()->parameter(i)->slot(); + Slot* slot = scope()->parameter(i)->AsSlot(); if (slot != NULL && slot->type() == Slot::CONTEXT) { int parameter_offset = StandardFrameConstants::kCallerSPOffset + (num_parameters - 1 - i) * kPointerSize; @@ -118,7 +118,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { } } - Variable* arguments = scope()->arguments()->AsVariable(); + Variable* arguments = scope()->arguments(); if (arguments != NULL) { // Function uses arguments object. Comment cmnt(masm_, "[ Allocate arguments object"); @@ -143,9 +143,8 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { __ CallStub(&stub); // Duplicate the value; move-to-slot operation might clobber registers. __ mov(r3, r0); - Move(arguments->slot(), r0, r1, r2); - Slot* dot_arguments_slot = - scope()->arguments_shadow()->AsVariable()->slot(); + Move(arguments->AsSlot(), r0, r1, r2); + Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot(); Move(dot_arguments_slot, r3, r1, r2); } @@ -253,205 +252,202 @@ FullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand( } -void FullCodeGenerator::Apply(Expression::Context context, Register reg) { - switch (context) { - case Expression::kUninitialized: - UNREACHABLE(); +void FullCodeGenerator::EffectContext::Plug(Slot* slot) const { +} - case Expression::kEffect: - // Nothing to do. - break; - case Expression::kValue: - // Move value into place. - switch (location_) { - case kAccumulator: - if (!reg.is(result_register())) __ mov(result_register(), reg); - break; - case kStack: - __ push(reg); - break; - } - break; +void FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const { + codegen()->Move(result_register(), slot); +} - case Expression::kTest: - // For simplicity we always test the accumulator register. - if (!reg.is(result_register())) __ mov(result_register(), reg); - DoTest(true_label_, false_label_, fall_through_); - break; - } + +void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const { + codegen()->Move(result_register(), slot); + __ push(result_register()); } -void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { - switch (context) { - case Expression::kUninitialized: - UNREACHABLE(); - case Expression::kEffect: - // Nothing to do. - break; - case Expression::kValue: - case Expression::kTest: - // On ARM we have to move the value into a register to do anything - // with it. - Move(result_register(), slot); - Apply(context, result_register()); - break; - } +void FullCodeGenerator::TestContext::Plug(Slot* slot) const { + // For simplicity we always test the accumulator register. + codegen()->Move(result_register(), slot); + codegen()->DoTest(true_label_, false_label_, fall_through_); } -void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { - switch (context) { - case Expression::kUninitialized: - UNREACHABLE(); - case Expression::kEffect: - break; - // Nothing to do. - case Expression::kValue: - case Expression::kTest: - // On ARM we have to move the value into a register to do anything - // with it. - __ mov(result_register(), Operand(lit->handle())); - Apply(context, result_register()); - break; +void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { +} + + +void FullCodeGenerator::AccumulatorValueContext::Plug( + Heap::RootListIndex index) const { + __ LoadRoot(result_register(), index); +} + + +void FullCodeGenerator::StackValueContext::Plug( + Heap::RootListIndex index) const { + __ LoadRoot(result_register(), index); + __ push(result_register()); +} + + +void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { + if (index == Heap::kUndefinedValueRootIndex || + index == Heap::kNullValueRootIndex || + index == Heap::kFalseValueRootIndex) { + __ b(false_label_); + } else if (index == Heap::kTrueValueRootIndex) { + __ b(true_label_); + } else { + __ LoadRoot(result_register(), index); + codegen()->DoTest(true_label_, false_label_, fall_through_); } } -void FullCodeGenerator::ApplyTOS(Expression::Context context) { - switch (context) { - case Expression::kUninitialized: - UNREACHABLE(); +void FullCodeGenerator::EffectContext::Plug(Handle lit) const { +} - case Expression::kEffect: - __ Drop(1); - break; - case Expression::kValue: - switch (location_) { - case kAccumulator: - __ pop(result_register()); - break; - case kStack: - break; - } - break; +void FullCodeGenerator::AccumulatorValueContext::Plug( + Handle lit) const { + __ mov(result_register(), Operand(lit)); +} - case Expression::kTest: - __ pop(result_register()); - DoTest(true_label_, false_label_, fall_through_); - break; + +void FullCodeGenerator::StackValueContext::Plug(Handle lit) const { + // Immediates can be pushed directly. + __ mov(result_register(), Operand(lit)); + __ push(result_register()); +} + + +void FullCodeGenerator::TestContext::Plug(Handle lit) const { + ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals. + if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { + __ b(false_label_); + } else if (lit->IsTrue() || lit->IsJSObject()) { + __ b(true_label_); + } else if (lit->IsString()) { + if (String::cast(*lit)->length() == 0) { + __ b(false_label_); + } else { + __ b(true_label_); + } + } else if (lit->IsSmi()) { + if (Smi::cast(*lit)->value() == 0) { + __ b(false_label_); + } else { + __ b(true_label_); + } + } else { + // For simplicity we always test the accumulator register. + __ mov(result_register(), Operand(lit)); + codegen()->DoTest(true_label_, false_label_, fall_through_); } } -void FullCodeGenerator::DropAndApply(int count, - Expression::Context context, - Register reg) { +void FullCodeGenerator::EffectContext::DropAndPlug(int count, + Register reg) const { ASSERT(count > 0); - ASSERT(!reg.is(sp)); - switch (context) { - case Expression::kUninitialized: - UNREACHABLE(); + __ Drop(count); +} - case Expression::kEffect: - __ Drop(count); - break; - case Expression::kValue: - switch (location_) { - case kAccumulator: - __ Drop(count); - if (!reg.is(result_register())) __ mov(result_register(), reg); - break; - case kStack: - if (count > 1) __ Drop(count - 1); - __ str(reg, MemOperand(sp)); - break; - } - break; +void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( + int count, + Register reg) const { + ASSERT(count > 0); + __ Drop(count); + __ Move(result_register(), reg); +} - case Expression::kTest: - __ Drop(count); - if (!reg.is(result_register())) __ mov(result_register(), reg); - DoTest(true_label_, false_label_, fall_through_); - break; - } + +void FullCodeGenerator::StackValueContext::DropAndPlug(int count, + Register reg) const { + ASSERT(count > 0); + if (count > 1) __ Drop(count - 1); + __ str(reg, MemOperand(sp, 0)); } -void FullCodeGenerator::Apply(Expression::Context context, - Label* materialize_true, - Label* materialize_false) { - switch (context) { - case Expression::kUninitialized: +void FullCodeGenerator::TestContext::DropAndPlug(int count, + Register reg) const { + ASSERT(count > 0); + // For simplicity we always test the accumulator register. + __ Drop(count); + __ Move(result_register(), reg); + codegen()->DoTest(true_label_, false_label_, fall_through_); +} - case Expression::kEffect: - ASSERT_EQ(materialize_true, materialize_false); - __ bind(materialize_true); - break; - case Expression::kValue: { - Label done; - switch (location_) { - case kAccumulator: - __ bind(materialize_true); - __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); - __ jmp(&done); - __ bind(materialize_false); - __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); - break; - case kStack: - __ bind(materialize_true); - __ LoadRoot(ip, Heap::kTrueValueRootIndex); - __ push(ip); - __ jmp(&done); - __ bind(materialize_false); - __ LoadRoot(ip, Heap::kFalseValueRootIndex); - __ push(ip); - break; - } - __ bind(&done); - break; - } +void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, + Label* materialize_false) const { + ASSERT_EQ(materialize_true, materialize_false); + __ bind(materialize_true); +} - case Expression::kTest: - break; - } + +void FullCodeGenerator::AccumulatorValueContext::Plug( + Label* materialize_true, + Label* materialize_false) const { + Label done; + __ bind(materialize_true); + __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); + __ jmp(&done); + __ bind(materialize_false); + __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); + __ bind(&done); } -// Convert constant control flow (true or false) to the result expected for -// a given expression context. -void FullCodeGenerator::Apply(Expression::Context context, bool flag) { - switch (context) { - case Expression::kUninitialized: - UNREACHABLE(); - break; - case Expression::kEffect: - break; - case Expression::kValue: { - Heap::RootListIndex value_root_index = - flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; - switch (location_) { - case kAccumulator: - __ LoadRoot(result_register(), value_root_index); - break; - case kStack: - __ LoadRoot(ip, value_root_index); - __ push(ip); - break; - } - break; - } - case Expression::kTest: - if (flag) { - if (true_label_ != fall_through_) __ b(true_label_); - } else { - if (false_label_ != fall_through_) __ b(false_label_); - } - break; +void FullCodeGenerator::StackValueContext::Plug( + Label* materialize_true, + Label* materialize_false) const { + Label done; + __ bind(materialize_true); + __ LoadRoot(ip, Heap::kTrueValueRootIndex); + __ push(ip); + __ jmp(&done); + __ bind(materialize_false); + __ LoadRoot(ip, Heap::kFalseValueRootIndex); + __ push(ip); + __ bind(&done); +} + + +void FullCodeGenerator::TestContext::Plug(Label* materialize_true, + Label* materialize_false) const { + ASSERT(materialize_false == false_label_); + ASSERT(materialize_true == true_label_); +} + + +void FullCodeGenerator::EffectContext::Plug(bool flag) const { +} + + +void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { + Heap::RootListIndex value_root_index = + flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; + __ LoadRoot(result_register(), value_root_index); +} + + +void FullCodeGenerator::StackValueContext::Plug(bool flag) const { + Heap::RootListIndex value_root_index = + flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; + __ LoadRoot(ip, value_root_index); + __ push(ip); +} + + +void FullCodeGenerator::TestContext::Plug(bool flag) const { + if (flag) { + if (true_label_ != fall_through_) __ b(true_label_); + } else { + if (false_label_ != fall_through_) __ b(false_label_); } } @@ -533,7 +529,7 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable, FunctionLiteral* function) { Comment cmnt(masm_, "[ Declaration"); ASSERT(variable != NULL); // Must have been resolved. - Slot* slot = variable->slot(); + Slot* slot = variable->AsSlot(); Property* prop = variable->AsProperty(); if (slot != NULL) { @@ -544,7 +540,7 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable, __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); __ str(ip, MemOperand(fp, SlotOffset(slot))); } else if (function != NULL) { - VisitForValue(function, kAccumulator); + VisitForAccumulatorValue(function); __ str(result_register(), MemOperand(fp, SlotOffset(slot))); } break; @@ -566,7 +562,7 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable, __ str(ip, ContextOperand(cp, slot->index())); // No write barrier since the_hole_value is in old space. } else if (function != NULL) { - VisitForValue(function, kAccumulator); + VisitForAccumulatorValue(function); __ str(result_register(), ContextOperand(cp, slot->index())); int offset = Context::SlotOffset(slot->index()); // We know that we have written a function, which is not a smi. @@ -593,7 +589,7 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable, } else if (function != NULL) { __ Push(cp, r2, r1); // Push initial value for function declaration. - VisitForValue(function, kStack); + VisitForStackValue(function); } else { __ mov(r0, Operand(Smi::FromInt(0))); // No initial value! __ Push(cp, r2, r1, r0); @@ -607,20 +603,20 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable, if (function != NULL || mode == Variable::CONST) { // We are declaring a function or constant that rewrites to a // property. Use (keyed) IC to set the initial value. - VisitForValue(prop->obj(), kStack); + VisitForStackValue(prop->obj()); if (function != NULL) { - VisitForValue(prop->key(), kStack); - VisitForValue(function, kAccumulator); + VisitForStackValue(prop->key()); + VisitForAccumulatorValue(function); __ pop(r1); // Key. } else { - VisitForValue(prop->key(), kAccumulator); + VisitForAccumulatorValue(prop->key()); __ mov(r1, result_register()); // Key. __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex); } __ pop(r2); // Receiver. Handle ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); // Value in r0 is ignored (declarations are statements). } } @@ -648,7 +644,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { Breakable nested_statement(this, stmt); SetStatementPosition(stmt); // Keep the switch value on the stack until a case matches. - VisitForValue(stmt->tag(), kStack); + VisitForStackValue(stmt->tag()); ZoneList* clauses = stmt->cases(); CaseClause* default_clause = NULL; // Can occur anywhere in the list. @@ -668,7 +664,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { next_test.Unuse(); // Compile the label expression. - VisitForValue(clause->label(), kAccumulator); + VisitForAccumulatorValue(clause->label()); // Perform the comparison as if via '==='. __ ldr(r1, MemOperand(sp, 0)); // Switch value. @@ -729,7 +725,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { // Get the object to enumerate over. Both SpiderMonkey and JSC // ignore null and undefined in contrast to the specification; see // ECMA-262 section 12.6.4. - VisitForValue(stmt->enumerable(), kAccumulator); + VisitForAccumulatorValue(stmt->enumerable()); __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); __ cmp(r0, ip); __ b(eq, &exit); @@ -872,13 +868,13 @@ void FullCodeGenerator::EmitNewClosure(Handle info) { __ Push(cp, r0); __ CallRuntime(Runtime::kNewClosure, 2); } - Apply(context_, r0); + context()->Plug(r0); } void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { Comment cmnt(masm_, "[ VariableProxy"); - EmitVariableLoad(expr->var(), context_); + EmitVariableLoad(expr->var()); } @@ -927,7 +923,7 @@ void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase( EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow); __ jmp(done); } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { - Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); + Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot(); Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); if (potential_slot != NULL) { // Generate fast case for locals that rewrite to slots. @@ -952,11 +948,11 @@ void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase( // variables. Then load the argument from the arguments // object using keyed load. __ ldr(r1, - ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(), + ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), slow)); __ mov(r0, Operand(key_literal->handle())); Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); __ jmp(done); } } @@ -1022,16 +1018,15 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT; Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); - __ Call(ic, mode); + EmitCallIC(ic, mode); } -void FullCodeGenerator::EmitVariableLoad(Variable* var, - Expression::Context context) { +void FullCodeGenerator::EmitVariableLoad(Variable* var) { // Four cases: non-this global variables, lookup slots, all other // types of slots, and parameters that rewrite to explicit property // accesses on the arguments object. - Slot* slot = var->slot(); + Slot* slot = var->AsSlot(); Property* property = var->AsProperty(); if (var->is_global() && !var->is_this()) { @@ -1041,8 +1036,8 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var, __ ldr(r0, CodeGenerator::GlobalObject()); __ mov(r2, Operand(var->name())); Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); - Apply(context, r0); + EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); + context()->Plug(r0); } else if (slot != NULL && slot->type() == Slot::LOOKUP) { Label done, slow; @@ -1058,24 +1053,24 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var, __ CallRuntime(Runtime::kLoadContextSlot, 2); __ bind(&done); - Apply(context, r0); + context()->Plug(r0); } else if (slot != NULL) { Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) ? "Context slot" : "Stack slot"); if (var->mode() == Variable::CONST) { - // Constants may be the hole value if they have not been initialized. - // Unhole them. - MemOperand slot_operand = EmitSlotSearch(slot, r0); - __ ldr(r0, slot_operand); - __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); - __ cmp(r0, ip); - __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); - Apply(context, r0); - } else { - Apply(context, slot); - } + // Constants may be the hole value if they have not been initialized. + // Unhole them. + MemOperand slot_operand = EmitSlotSearch(slot, r0); + __ ldr(r0, slot_operand); + __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); + __ cmp(r0, ip); + __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); + context()->Plug(r0); + } else { + context()->Plug(slot); + } } else { Comment cmnt(masm_, "Rewritten parameter"); ASSERT_NOT_NULL(property); @@ -1084,7 +1079,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var, // Assert that the object is in a slot. Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); ASSERT_NOT_NULL(object_var); - Slot* object_slot = object_var->slot(); + Slot* object_slot = object_var->AsSlot(); ASSERT_NOT_NULL(object_slot); // Load the object. @@ -1100,8 +1095,8 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var, // Call keyed load IC. It has arguments key and receiver in r0 and r1. Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); - Apply(context, r0); + EmitCallIC(ic, RelocInfo::CODE_TARGET); + context()->Plug(r0); } } @@ -1145,7 +1140,7 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { // r2: temp. __ pop(r1); __ CopyFields(r0, r1, r2.bit(), size / kPointerSize); - Apply(context_, r0); + context()->Plug(r0); } @@ -1185,11 +1180,11 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { // Fall through. case ObjectLiteral::Property::COMPUTED: if (key->handle()->IsSymbol()) { - VisitForValue(value, kAccumulator); + VisitForAccumulatorValue(value); __ mov(r2, Operand(key->handle())); __ ldr(r1, MemOperand(sp)); Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); break; } // Fall through. @@ -1197,8 +1192,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { // Duplicate receiver on stack. __ ldr(r0, MemOperand(sp)); __ push(r0); - VisitForValue(key, kStack); - VisitForValue(value, kStack); + VisitForStackValue(key); + VisitForStackValue(value); __ CallRuntime(Runtime::kSetProperty, 3); break; case ObjectLiteral::Property::GETTER: @@ -1206,21 +1201,21 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { // Duplicate receiver on stack. __ ldr(r0, MemOperand(sp)); __ push(r0); - VisitForValue(key, kStack); + VisitForStackValue(key); __ mov(r1, Operand(property->kind() == ObjectLiteral::Property::SETTER ? Smi::FromInt(1) : Smi::FromInt(0))); __ push(r1); - VisitForValue(value, kStack); + VisitForStackValue(value); __ CallRuntime(Runtime::kDefineAccessor, 4); break; } } if (result_saved) { - ApplyTOS(context_); + context()->PlugTOS(); } else { - Apply(context_, r0); + context()->Plug(r0); } } @@ -1268,7 +1263,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { __ push(r0); result_saved = true; } - VisitForValue(subexpr, kAccumulator); + VisitForAccumulatorValue(subexpr); // Store the subexpression value in the array's elements. __ ldr(r1, MemOperand(sp)); // Copy of array literal. @@ -1282,9 +1277,9 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { } if (result_saved) { - ApplyTOS(context_); + context()->PlugTOS(); } else { - Apply(context_, r0); + context()->Plug(r0); } } @@ -1317,39 +1312,38 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { case NAMED_PROPERTY: if (expr->is_compound()) { // We need the receiver both on the stack and in the accumulator. - VisitForValue(property->obj(), kAccumulator); + VisitForAccumulatorValue(property->obj()); __ push(result_register()); } else { - VisitForValue(property->obj(), kStack); + VisitForStackValue(property->obj()); } break; case KEYED_PROPERTY: if (expr->is_compound()) { - VisitForValue(property->obj(), kStack); - VisitForValue(property->key(), kAccumulator); + VisitForStackValue(property->obj()); + VisitForAccumulatorValue(property->key()); __ ldr(r1, MemOperand(sp, 0)); __ push(r0); } else { - VisitForValue(property->obj(), kStack); - VisitForValue(property->key(), kStack); + VisitForStackValue(property->obj()); + VisitForStackValue(property->key()); } break; } if (expr->is_compound()) { - Location saved_location = location_; - location_ = kAccumulator; - switch (assign_type) { - case VARIABLE: - EmitVariableLoad(expr->target()->AsVariableProxy()->var(), - Expression::kValue); - break; - case NAMED_PROPERTY: - EmitNamedPropertyLoad(property); - break; - case KEYED_PROPERTY: - EmitKeyedPropertyLoad(property); - break; + { AccumulatorValueContext context(this); + switch (assign_type) { + case VARIABLE: + EmitVariableLoad(expr->target()->AsVariableProxy()->var()); + break; + case NAMED_PROPERTY: + EmitNamedPropertyLoad(property); + break; + case KEYED_PROPERTY: + EmitKeyedPropertyLoad(property); + break; + } } Token::Value op = expr->binary_op(); @@ -1359,28 +1353,26 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ASSERT(constant == kRightConstant || constant == kNoConstants); if (constant == kNoConstants) { __ push(r0); // Left operand goes on the stack. - VisitForValue(expr->value(), kAccumulator); + VisitForAccumulatorValue(expr->value()); } OverwriteMode mode = expr->value()->ResultOverwriteAllowed() ? OVERWRITE_RIGHT : NO_OVERWRITE; SetSourcePosition(expr->position() + 1); + AccumulatorValueContext context(this); if (ShouldInlineSmiCase(op)) { EmitInlineSmiBinaryOp(expr, op, - Expression::kValue, mode, expr->target(), expr->value(), constant); } else { - EmitBinaryOp(op, Expression::kValue, mode); + EmitBinaryOp(op, mode); } - location_ = saved_location; - } else { - VisitForValue(expr->value(), kAccumulator); + VisitForAccumulatorValue(expr->value()); } // Record source position before possible IC call. @@ -1390,8 +1382,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { switch (assign_type) { case VARIABLE: EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), - expr->op(), - context_); + expr->op()); break; case NAMED_PROPERTY: EmitNamedPropertyAssignment(expr); @@ -1409,7 +1400,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { __ mov(r2, Operand(key->handle())); // Call load IC. It has arguments receiver and property name r0 and r2. Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); } @@ -1417,29 +1408,27 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { SetSourcePosition(prop->position()); // Call keyed load IC. It has arguments key and receiver in r0 and r1. Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); } void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, Token::Value op, - Expression::Context context, OverwriteMode mode, Expression* left, Expression* right, ConstantOperand constant) { ASSERT(constant == kNoConstants); // Only handled case. - EmitBinaryOp(op, context, mode); + EmitBinaryOp(op, mode); } void FullCodeGenerator::EmitBinaryOp(Token::Value op, - Expression::Context context, OverwriteMode mode) { __ pop(r1); GenericBinaryOpStub stub(op, mode, r1, r0); __ CallStub(&stub); - Apply(context, r0); + context()->Plug(r0); } @@ -1465,28 +1454,29 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { switch (assign_type) { case VARIABLE: { Variable* var = expr->AsVariableProxy()->var(); - EmitVariableAssignment(var, Token::ASSIGN, Expression::kEffect); + EffectContext context(this); + EmitVariableAssignment(var, Token::ASSIGN); break; } case NAMED_PROPERTY: { __ push(r0); // Preserve value. - VisitForValue(prop->obj(), kAccumulator); + VisitForAccumulatorValue(prop->obj()); __ mov(r1, r0); __ pop(r0); // Restore value. __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); break; } case KEYED_PROPERTY: { __ push(r0); // Preserve value. - VisitForValue(prop->obj(), kStack); - VisitForValue(prop->key(), kAccumulator); + VisitForStackValue(prop->obj()); + VisitForAccumulatorValue(prop->key()); __ mov(r1, r0); __ pop(r2); __ pop(r0); // Restore value. Handle ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); break; } } @@ -1494,12 +1484,11 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { void FullCodeGenerator::EmitVariableAssignment(Variable* var, - Token::Value op, - Expression::Context context) { + Token::Value op) { // Left-hand sides that rewrite to explicit property accesses do not reach // here. ASSERT(var != NULL); - ASSERT(var->is_global() || var->slot() != NULL); + ASSERT(var->is_global() || var->AsSlot() != NULL); if (var->is_global()) { ASSERT(!var->is_this()); @@ -1509,13 +1498,13 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, __ mov(r2, Operand(var->name())); __ ldr(r1, CodeGenerator::GlobalObject()); Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { // Perform the assignment for non-const variables and for initialization // of const variables. Const assignments are simply skipped. Label done; - Slot* slot = var->slot(); + Slot* slot = var->AsSlot(); switch (slot->type()) { case Slot::PARAMETER: case Slot::LOCAL: @@ -1565,7 +1554,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, __ bind(&done); } - Apply(context, result_register()); + context()->Plug(result_register()); } @@ -1598,7 +1587,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { } Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); // If the assignment ends an initialization block, revert to fast case. if (expr->ends_initialization_block()) { @@ -1608,9 +1597,9 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { __ push(ip); __ CallRuntime(Runtime::kToFastProperties, 1); __ pop(r0); - DropAndApply(1, context_, r0); + context()->DropAndPlug(1, r0); } else { - Apply(context_, r0); + context()->Plug(r0); } } @@ -1642,7 +1631,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { } Handle ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); // If the assignment ends an initialization block, revert to fast case. if (expr->ends_initialization_block()) { @@ -1652,9 +1641,9 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { __ push(ip); __ CallRuntime(Runtime::kToFastProperties, 1); __ pop(r0); - DropAndApply(1, context_, r0); + context()->DropAndPlug(1, r0); } else { - Apply(context_, r0); + context()->Plug(r0); } } @@ -1664,16 +1653,15 @@ void FullCodeGenerator::VisitProperty(Property* expr) { Expression* key = expr->key(); if (key->IsPropertyName()) { - VisitForValue(expr->obj(), kAccumulator); + VisitForAccumulatorValue(expr->obj()); EmitNamedPropertyLoad(expr); - Apply(context_, r0); } else { - VisitForValue(expr->obj(), kStack); - VisitForValue(expr->key(), kAccumulator); + VisitForStackValue(expr->obj()); + VisitForAccumulatorValue(expr->key()); __ pop(r1); EmitKeyedPropertyLoad(expr); - Apply(context_, r0); } + context()->Plug(r0); } void FullCodeGenerator::EmitCallWithIC(Call* expr, @@ -1683,7 +1671,7 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, ZoneList* args = expr->arguments(); int arg_count = args->length(); for (int i = 0; i < arg_count; i++) { - VisitForValue(args->at(i), kStack); + VisitForStackValue(args->at(i)); } __ mov(r2, Operand(name)); // Record source position for debugger. @@ -1691,10 +1679,10 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, // Call the IC initialization code. InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; Handle ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); - __ Call(ic, mode); + EmitCallIC(ic, mode); // Restore context register. __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); - Apply(context_, r0); + context()->Plug(r0); } @@ -1705,9 +1693,9 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, ZoneList* args = expr->arguments(); int arg_count = args->length(); for (int i = 0; i < arg_count; i++) { - VisitForValue(args->at(i), kStack); + VisitForStackValue(args->at(i)); } - VisitForValue(key, kAccumulator); + VisitForAccumulatorValue(key); __ mov(r2, r0); // Record source position for debugger. SetSourcePosition(expr->position()); @@ -1715,10 +1703,10 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; Handle ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count, in_loop); - __ Call(ic, mode); + EmitCallIC(ic, mode); // Restore context register. __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); - Apply(context_, r0); + context()->Plug(r0); } @@ -1727,7 +1715,7 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) { ZoneList* args = expr->arguments(); int arg_count = args->length(); for (int i = 0; i < arg_count; i++) { - VisitForValue(args->at(i), kStack); + VisitForStackValue(args->at(i)); } // Record source position for debugger. SetSourcePosition(expr->position()); @@ -1736,7 +1724,7 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) { __ CallStub(&stub); // Restore context register. __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); - DropAndApply(1, context_, r0); + context()->DropAndPlug(1, r0); } @@ -1750,7 +1738,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { // resolve the function we need to call and the receiver of the // call. Then we call the resolved function using the given // arguments. - VisitForValue(fun, kStack); + VisitForStackValue(fun); __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); __ push(r2); // Reserved receiver slot. @@ -1758,7 +1746,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { ZoneList* args = expr->arguments(); int arg_count = args->length(); for (int i = 0; i < arg_count; i++) { - VisitForValue(args->at(i), kStack); + VisitForStackValue(args->at(i)); } // Push copy of the function - found below the arguments. @@ -1790,26 +1778,26 @@ void FullCodeGenerator::VisitCall(Call* expr) { __ CallStub(&stub); // Restore context register. __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); - DropAndApply(1, context_, r0); + context()->DropAndPlug(1, r0); } else if (var != NULL && !var->is_this() && var->is_global()) { // Push global object as receiver for the call IC. __ ldr(r0, CodeGenerator::GlobalObject()); __ push(r0); EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); - } else if (var != NULL && var->slot() != NULL && - var->slot()->type() == Slot::LOOKUP) { + } else if (var != NULL && var->AsSlot() != NULL && + var->AsSlot()->type() == Slot::LOOKUP) { // Call to a lookup slot (dynamically introduced variable). Label slow, done; // Generate code for loading from variables potentially shadowed // by eval-introduced variables. - EmitDynamicLoadFromSlotFastCase(var->slot(), + EmitDynamicLoadFromSlotFastCase(var->AsSlot(), NOT_INSIDE_TYPEOF, &slow, &done); __ bind(&slow); - // Call the runtime to find the function to call (returned in eax) + // Call the runtime to find the function to call (returned in r0) // and the object holding it (returned in edx). __ push(context_register()); __ mov(r2, Operand(var->name())); @@ -1840,21 +1828,21 @@ void FullCodeGenerator::VisitCall(Call* expr) { Literal* key = prop->key()->AsLiteral(); if (key != NULL && key->handle()->IsSymbol()) { // Call to a named property, use call IC. - VisitForValue(prop->obj(), kStack); + VisitForStackValue(prop->obj()); EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); } else { // Call to a keyed property. // For a synthetic property use keyed load IC followed by function call, // for a regular property use keyed CallIC. - VisitForValue(prop->obj(), kStack); + VisitForStackValue(prop->obj()); if (prop->is_synthetic()) { - VisitForValue(prop->key(), kAccumulator); + VisitForAccumulatorValue(prop->key()); // Record source code position for IC call. SetSourcePosition(prop->position()); __ pop(r1); // We do not need to keep the receiver. Handle ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); __ ldr(r1, CodeGenerator::GlobalObject()); __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); __ Push(r0, r1); // Function, receiver. @@ -1873,7 +1861,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { loop_depth() == 0) { lit->set_try_full_codegen(true); } - VisitForValue(fun, kStack); + VisitForStackValue(fun); // Load global receiver object. __ ldr(r1, CodeGenerator::GlobalObject()); __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); @@ -1893,13 +1881,13 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { // Push constructor on the stack. If it's not a function it's used as // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is // ignored. - VisitForValue(expr->expression(), kStack); + VisitForStackValue(expr->expression()); // Push the arguments ("left-to-right") on the stack. ZoneList* args = expr->arguments(); int arg_count = args->length(); for (int i = 0; i < arg_count; i++) { - VisitForValue(args->at(i), kStack); + VisitForStackValue(args->at(i)); } // Call the construct call builtin that handles allocation and @@ -1912,59 +1900,59 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { Handle construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); - Apply(context_, r0); + context()->Plug(r0); } void FullCodeGenerator::EmitIsSmi(ZoneList* args) { ASSERT(args->length() == 1); - VisitForValue(args->at(0), kAccumulator); + VisitForAccumulatorValue(args->at(0)); Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; Label* fall_through = NULL; - PrepareTest(&materialize_true, &materialize_false, - &if_true, &if_false, &fall_through); + context()->PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ BranchOnSmi(r0, if_true); __ b(if_false); - Apply(context_, if_true, if_false); + context()->Plug(if_true, if_false); } void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList* args) { ASSERT(args->length() == 1); - VisitForValue(args->at(0), kAccumulator); + VisitForAccumulatorValue(args->at(0)); Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; Label* fall_through = NULL; - PrepareTest(&materialize_true, &materialize_false, - &if_true, &if_false, &fall_through); + context()->PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ tst(r0, Operand(kSmiTagMask | 0x80000000)); Split(eq, if_true, if_false, fall_through); - Apply(context_, if_true, if_false); + context()->Plug(if_true, if_false); } void FullCodeGenerator::EmitIsObject(ZoneList* args) { ASSERT(args->length() == 1); - VisitForValue(args->at(0), kAccumulator); + VisitForAccumulatorValue(args->at(0)); Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; Label* fall_through = NULL; - PrepareTest(&materialize_true, &materialize_false, - &if_true, &if_false, &fall_through); + context()->PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ BranchOnSmi(r0, if_false); __ LoadRoot(ip, Heap::kNullValueRootIndex); @@ -1981,41 +1969,41 @@ void FullCodeGenerator::EmitIsObject(ZoneList* args) { __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE)); Split(le, if_true, if_false, fall_through); - Apply(context_, if_true, if_false); + context()->Plug(if_true, if_false); } void FullCodeGenerator::EmitIsSpecObject(ZoneList* args) { ASSERT(args->length() == 1); - VisitForValue(args->at(0), kAccumulator); + VisitForAccumulatorValue(args->at(0)); Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; Label* fall_through = NULL; - PrepareTest(&materialize_true, &materialize_false, - &if_true, &if_false, &fall_through); + context()->PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ BranchOnSmi(r0, if_false); __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); Split(ge, if_true, if_false, fall_through); - Apply(context_, if_true, if_false); + context()->Plug(if_true, if_false); } void FullCodeGenerator::EmitIsUndetectableObject(ZoneList* args) { ASSERT(args->length() == 1); - VisitForValue(args->at(0), kAccumulator); + VisitForAccumulatorValue(args->at(0)); Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; Label* fall_through = NULL; - PrepareTest(&materialize_true, &materialize_false, - &if_true, &if_false, &fall_through); + context()->PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ BranchOnSmi(r0, if_false); __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); @@ -2023,7 +2011,7 @@ void FullCodeGenerator::EmitIsUndetectableObject(ZoneList* args) { __ tst(r1, Operand(1 << Map::kIsUndetectable)); Split(ne, if_true, if_false, fall_through); - Apply(context_, if_true, if_false); + context()->Plug(if_true, if_false); } @@ -2032,80 +2020,80 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( ASSERT(args->length() == 1); - VisitForValue(args->at(0), kAccumulator); + VisitForAccumulatorValue(args->at(0)); Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; Label* fall_through = NULL; - PrepareTest(&materialize_true, &materialize_false, - &if_true, &if_false, &fall_through); + context()->PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only // used in a few functions in runtime.js which should not normally be hit by // this compiler. __ jmp(if_false); - Apply(context_, if_true, if_false); + context()->Plug(if_true, if_false); } void FullCodeGenerator::EmitIsFunction(ZoneList* args) { ASSERT(args->length() == 1); - VisitForValue(args->at(0), kAccumulator); + VisitForAccumulatorValue(args->at(0)); Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; Label* fall_through = NULL; - PrepareTest(&materialize_true, &materialize_false, - &if_true, &if_false, &fall_through); + context()->PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ BranchOnSmi(r0, if_false); __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); Split(eq, if_true, if_false, fall_through); - Apply(context_, if_true, if_false); + context()->Plug(if_true, if_false); } void FullCodeGenerator::EmitIsArray(ZoneList* args) { ASSERT(args->length() == 1); - VisitForValue(args->at(0), kAccumulator); + VisitForAccumulatorValue(args->at(0)); Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; Label* fall_through = NULL; - PrepareTest(&materialize_true, &materialize_false, - &if_true, &if_false, &fall_through); + context()->PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ BranchOnSmi(r0, if_false); __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); Split(eq, if_true, if_false, fall_through); - Apply(context_, if_true, if_false); + context()->Plug(if_true, if_false); } void FullCodeGenerator::EmitIsRegExp(ZoneList* args) { ASSERT(args->length() == 1); - VisitForValue(args->at(0), kAccumulator); + VisitForAccumulatorValue(args->at(0)); Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; Label* fall_through = NULL; - PrepareTest(&materialize_true, &materialize_false, - &if_true, &if_false, &fall_through); + context()->PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ BranchOnSmi(r0, if_false); __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); Split(eq, if_true, if_false, fall_through); - Apply(context_, if_true, if_false); + context()->Plug(if_true, if_false); } @@ -2117,8 +2105,8 @@ void FullCodeGenerator::EmitIsConstructCall(ZoneList* args) { Label* if_true = NULL; Label* if_false = NULL; Label* fall_through = NULL; - PrepareTest(&materialize_true, &materialize_false, - &if_true, &if_false, &fall_through); + context()->PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); // Get the frame pointer for the calling frame. __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); @@ -2136,7 +2124,7 @@ void FullCodeGenerator::EmitIsConstructCall(ZoneList* args) { __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); Split(eq, if_true, if_false, fall_through); - Apply(context_, if_true, if_false); + context()->Plug(if_true, if_false); } @@ -2144,21 +2132,21 @@ void FullCodeGenerator::EmitObjectEquals(ZoneList* args) { ASSERT(args->length() == 2); // Load the two objects into registers and perform the comparison. - VisitForValue(args->at(0), kStack); - VisitForValue(args->at(1), kAccumulator); + VisitForStackValue(args->at(0)); + VisitForAccumulatorValue(args->at(1)); Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; Label* fall_through = NULL; - PrepareTest(&materialize_true, &materialize_false, - &if_true, &if_false, &fall_through); + context()->PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ pop(r1); __ cmp(r0, r1); Split(eq, if_true, if_false, fall_through); - Apply(context_, if_true, if_false); + context()->Plug(if_true, if_false); } @@ -2166,13 +2154,13 @@ void FullCodeGenerator::EmitArguments(ZoneList* args) { ASSERT(args->length() == 1); // ArgumentsAccessStub expects the key in edx and the formal - // parameter count in eax. - VisitForValue(args->at(0), kAccumulator); + // parameter count in r0. + VisitForAccumulatorValue(args->at(0)); __ mov(r1, r0); __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters()))); ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); __ CallStub(&stub); - Apply(context_, r0); + context()->Plug(r0); } @@ -2194,7 +2182,7 @@ void FullCodeGenerator::EmitArgumentsLength(ZoneList* args) { __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); __ bind(&exit); - Apply(context_, r0); + context()->Plug(r0); } @@ -2202,7 +2190,7 @@ void FullCodeGenerator::EmitClassOf(ZoneList* args) { ASSERT(args->length() == 1); Label done, null, function, non_function_constructor; - VisitForValue(args->at(0), kAccumulator); + VisitForAccumulatorValue(args->at(0)); // If the object is a smi, we return null. __ BranchOnSmi(r0, &null); @@ -2248,7 +2236,7 @@ void FullCodeGenerator::EmitClassOf(ZoneList* args) { // All done. __ bind(&done); - Apply(context_, r0); + context()->Plug(r0); } @@ -2263,14 +2251,14 @@ void FullCodeGenerator::EmitLog(ZoneList* args) { ASSERT_EQ(args->length(), 3); #ifdef ENABLE_LOGGING_AND_PROFILING if (CodeGenerator::ShouldGenerateLog(args->at(0))) { - VisitForValue(args->at(1), kStack); - VisitForValue(args->at(2), kStack); + VisitForStackValue(args->at(1)); + VisitForStackValue(args->at(2)); __ CallRuntime(Runtime::kLog, 2); } #endif // Finally, we're expected to leave a value on the top of the stack. __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); - Apply(context_, r0); + context()->Plug(r0); } @@ -2320,7 +2308,7 @@ void FullCodeGenerator::EmitRandomHeapNumber(ZoneList* args) { ExternalReference::fill_heap_number_with_random_function(), 1); } - Apply(context_, r0); + context()->Plug(r0); } @@ -2328,11 +2316,11 @@ void FullCodeGenerator::EmitSubString(ZoneList* args) { // Load the arguments on the stack and call the stub. SubStringStub stub; ASSERT(args->length() == 3); - VisitForValue(args->at(0), kStack); - VisitForValue(args->at(1), kStack); - VisitForValue(args->at(2), kStack); + VisitForStackValue(args->at(0)); + VisitForStackValue(args->at(1)); + VisitForStackValue(args->at(2)); __ CallStub(&stub); - Apply(context_, r0); + context()->Plug(r0); } @@ -2340,19 +2328,19 @@ void FullCodeGenerator::EmitRegExpExec(ZoneList* args) { // Load the arguments on the stack and call the stub. RegExpExecStub stub; ASSERT(args->length() == 4); - VisitForValue(args->at(0), kStack); - VisitForValue(args->at(1), kStack); - VisitForValue(args->at(2), kStack); - VisitForValue(args->at(3), kStack); + VisitForStackValue(args->at(0)); + VisitForStackValue(args->at(1)); + VisitForStackValue(args->at(2)); + VisitForStackValue(args->at(3)); __ CallStub(&stub); - Apply(context_, r0); + context()->Plug(r0); } void FullCodeGenerator::EmitValueOf(ZoneList* args) { ASSERT(args->length() == 1); - VisitForValue(args->at(0), kAccumulator); // Load the object. + VisitForAccumulatorValue(args->at(0)); // Load the object. Label done; // If the object is a smi return the object. @@ -2363,25 +2351,25 @@ void FullCodeGenerator::EmitValueOf(ZoneList* args) { __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); __ bind(&done); - Apply(context_, r0); + context()->Plug(r0); } void FullCodeGenerator::EmitMathPow(ZoneList* args) { // Load the arguments on the stack and call the runtime function. ASSERT(args->length() == 2); - VisitForValue(args->at(0), kStack); - VisitForValue(args->at(1), kStack); + VisitForStackValue(args->at(0)); + VisitForStackValue(args->at(1)); __ CallRuntime(Runtime::kMath_pow, 2); - Apply(context_, r0); + context()->Plug(r0); } void FullCodeGenerator::EmitSetValueOf(ZoneList* args) { ASSERT(args->length() == 2); - VisitForValue(args->at(0), kStack); // Load the object. - VisitForValue(args->at(1), kAccumulator); // Load the value. + VisitForStackValue(args->at(0)); // Load the object. + VisitForAccumulatorValue(args->at(1)); // Load the value. __ pop(r1); // r0 = value. r1 = object. Label done; @@ -2399,7 +2387,7 @@ void FullCodeGenerator::EmitSetValueOf(ZoneList* args) { __ RecordWrite(r1, Operand(JSValue::kValueOffset - kHeapObjectTag), r2, r3); __ bind(&done); - Apply(context_, r0); + context()->Plug(r0); } @@ -2407,18 +2395,18 @@ void FullCodeGenerator::EmitNumberToString(ZoneList* args) { ASSERT_EQ(args->length(), 1); // Load the argument on the stack and call the stub. - VisitForValue(args->at(0), kStack); + VisitForStackValue(args->at(0)); NumberToStringStub stub; __ CallStub(&stub); - Apply(context_, r0); + context()->Plug(r0); } void FullCodeGenerator::EmitStringCharFromCode(ZoneList* args) { ASSERT(args->length() == 1); - VisitForValue(args->at(0), kAccumulator); + VisitForAccumulatorValue(args->at(0)); Label done; StringCharFromCodeGenerator generator(r0, r1); @@ -2429,15 +2417,15 @@ void FullCodeGenerator::EmitStringCharFromCode(ZoneList* args) { generator.GenerateSlow(masm_, call_helper); __ bind(&done); - Apply(context_, r1); + context()->Plug(r1); } void FullCodeGenerator::EmitStringCharCodeAt(ZoneList* args) { ASSERT(args->length() == 2); - VisitForValue(args->at(0), kStack); - VisitForValue(args->at(1), kAccumulator); + VisitForStackValue(args->at(0)); + VisitForAccumulatorValue(args->at(1)); Register object = r1; Register index = r0; @@ -2476,15 +2464,15 @@ void FullCodeGenerator::EmitStringCharCodeAt(ZoneList* args) { generator.GenerateSlow(masm_, call_helper); __ bind(&done); - Apply(context_, result); + context()->Plug(result); } void FullCodeGenerator::EmitStringCharAt(ZoneList* args) { ASSERT(args->length() == 2); - VisitForValue(args->at(0), kStack); - VisitForValue(args->at(1), kAccumulator); + VisitForStackValue(args->at(0)); + VisitForAccumulatorValue(args->at(1)); Register object = r1; Register index = r0; @@ -2525,58 +2513,58 @@ void FullCodeGenerator::EmitStringCharAt(ZoneList* args) { generator.GenerateSlow(masm_, call_helper); __ bind(&done); - Apply(context_, result); + context()->Plug(result); } void FullCodeGenerator::EmitStringAdd(ZoneList* args) { ASSERT_EQ(2, args->length()); - VisitForValue(args->at(0), kStack); - VisitForValue(args->at(1), kStack); + VisitForStackValue(args->at(0)); + VisitForStackValue(args->at(1)); StringAddStub stub(NO_STRING_ADD_FLAGS); __ CallStub(&stub); - Apply(context_, r0); + context()->Plug(r0); } void FullCodeGenerator::EmitStringCompare(ZoneList* args) { ASSERT_EQ(2, args->length()); - VisitForValue(args->at(0), kStack); - VisitForValue(args->at(1), kStack); + VisitForStackValue(args->at(0)); + VisitForStackValue(args->at(1)); StringCompareStub stub; __ CallStub(&stub); - Apply(context_, r0); + context()->Plug(r0); } void FullCodeGenerator::EmitMathSin(ZoneList* args) { // Load the argument on the stack and call the runtime. ASSERT(args->length() == 1); - VisitForValue(args->at(0), kStack); + VisitForStackValue(args->at(0)); __ CallRuntime(Runtime::kMath_sin, 1); - Apply(context_, r0); + context()->Plug(r0); } void FullCodeGenerator::EmitMathCos(ZoneList* args) { // Load the argument on the stack and call the runtime. ASSERT(args->length() == 1); - VisitForValue(args->at(0), kStack); + VisitForStackValue(args->at(0)); __ CallRuntime(Runtime::kMath_cos, 1); - Apply(context_, r0); + context()->Plug(r0); } void FullCodeGenerator::EmitMathSqrt(ZoneList* args) { // Load the argument on the stack and call the runtime function. ASSERT(args->length() == 1); - VisitForValue(args->at(0), kStack); + VisitForStackValue(args->at(0)); __ CallRuntime(Runtime::kMath_sqrt, 1); - Apply(context_, r0); + context()->Plug(r0); } @@ -2584,38 +2572,38 @@ void FullCodeGenerator::EmitCallFunction(ZoneList* args) { ASSERT(args->length() >= 2); int arg_count = args->length() - 2; // For receiver and function. - VisitForValue(args->at(0), kStack); // Receiver. + VisitForStackValue(args->at(0)); // Receiver. for (int i = 0; i < arg_count; i++) { - VisitForValue(args->at(i + 1), kStack); + VisitForStackValue(args->at(i + 1)); } - VisitForValue(args->at(arg_count + 1), kAccumulator); // Function. + VisitForAccumulatorValue(args->at(arg_count + 1)); // Function. // InvokeFunction requires function in r1. Move it in there. if (!result_register().is(r1)) __ mov(r1, result_register()); ParameterCount count(arg_count); __ InvokeFunction(r1, count, CALL_FUNCTION); __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); - Apply(context_, r0); + context()->Plug(r0); } void FullCodeGenerator::EmitRegExpConstructResult(ZoneList* args) { ASSERT(args->length() == 3); - VisitForValue(args->at(0), kStack); - VisitForValue(args->at(1), kStack); - VisitForValue(args->at(2), kStack); + VisitForStackValue(args->at(0)); + VisitForStackValue(args->at(1)); + VisitForStackValue(args->at(2)); __ CallRuntime(Runtime::kRegExpConstructResult, 3); - Apply(context_, r0); + context()->Plug(r0); } void FullCodeGenerator::EmitSwapElements(ZoneList* args) { ASSERT(args->length() == 3); - VisitForValue(args->at(0), kStack); - VisitForValue(args->at(1), kStack); - VisitForValue(args->at(2), kStack); + VisitForStackValue(args->at(0)); + VisitForStackValue(args->at(1)); + VisitForStackValue(args->at(2)); __ CallRuntime(Runtime::kSwapElements, 3); - Apply(context_, r0); + context()->Plug(r0); } @@ -2630,11 +2618,11 @@ void FullCodeGenerator::EmitGetFromCache(ZoneList* args) { if (jsfunction_result_caches->length() <= cache_id) { __ Abort("Attempt to use undefined cache."); __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); - Apply(context_, r0); + context()->Plug(r0); return; } - VisitForValue(args->at(1), kAccumulator); + VisitForAccumulatorValue(args->at(1)); Register key = r0; Register cache = r1; @@ -2666,7 +2654,7 @@ void FullCodeGenerator::EmitGetFromCache(ZoneList* args) { __ CallRuntime(Runtime::kGetFromCache, 2); __ bind(&done); - Apply(context_, r0); + context()->Plug(r0); } @@ -2678,8 +2666,8 @@ void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList* args) { Register tmp = r2; Register tmp2 = r3; - VisitForValue(args->at(0), kStack); - VisitForValue(args->at(1), kAccumulator); + VisitForStackValue(args->at(0)); + VisitForAccumulatorValue(args->at(1)); __ pop(left); Label done, fail, ok; @@ -2707,19 +2695,19 @@ void FullCodeGenerator::EmitIsRegExpEquivalent(ZoneList* args) { __ LoadRoot(r0, Heap::kTrueValueRootIndex); __ bind(&done); - Apply(context_, r0); + context()->Plug(r0); } void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList* args) { - VisitForValue(args->at(0), kAccumulator); + VisitForAccumulatorValue(args->at(0)); Label materialize_true, materialize_false; Label* if_true = NULL; Label* if_false = NULL; Label* fall_through = NULL; - PrepareTest(&materialize_true, &materialize_false, - &if_true, &if_false, &fall_through); + context()->PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); __ tst(r0, Operand(String::kContainsCachedArrayIndexMask)); @@ -2727,16 +2715,16 @@ void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList* args) { __ b(eq, if_true); __ b(if_false); - Apply(context_, if_true, if_false); + context()->Plug(if_true, if_false); } void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList* args) { ASSERT(args->length() == 1); - VisitForValue(args->at(0), kAccumulator); + VisitForAccumulatorValue(args->at(0)); __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); __ IndexFromHash(r0, r0); - Apply(context_, r0); + context()->Plug(r0); } @@ -2761,7 +2749,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { // Push the arguments ("left-to-right"). int arg_count = args->length(); for (int i = 0; i < arg_count; i++) { - VisitForValue(args->at(i), kStack); + VisitForStackValue(args->at(i)); } if (expr->is_jsruntime()) { @@ -2769,14 +2757,14 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { __ mov(r2, Operand(expr->name())); Handle ic = CodeGenerator::ComputeCallInitialize(arg_count, NOT_IN_LOOP); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); // Restore context register. __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); } else { // Call the C runtime function. __ CallRuntime(expr->function(), arg_count); } - Apply(context_, r0); + context()->Plug(r0); } @@ -2790,20 +2778,20 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { // Result of deleting non-property, non-variable reference is true. // The subexpression may have side effects. VisitForEffect(expr->expression()); - Apply(context_, true); + context()->Plug(true); } else if (var != NULL && !var->is_global() && - var->slot() != NULL && - var->slot()->type() != Slot::LOOKUP) { + var->AsSlot() != NULL && + var->AsSlot()->type() != Slot::LOOKUP) { // Result of deleting non-global, non-dynamic variables is false. // The subexpression does not have side effects. - Apply(context_, false); + context()->Plug(false); } else { // Property or variable reference. Call the delete builtin with // object and property name as arguments. if (prop != NULL) { - VisitForValue(prop->obj(), kStack); - VisitForValue(prop->key(), kStack); + VisitForStackValue(prop->obj()); + VisitForStackValue(prop->key()); } else if (var->is_global()) { __ ldr(r1, CodeGenerator::GlobalObject()); __ mov(r0, Operand(var->name())); @@ -2820,7 +2808,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { __ push(r2); } __ InvokeBuiltin(Builtins::DELETE, CALL_JS); - Apply(context_, r0); + context()->Plug(r0); } break; } @@ -2828,26 +2816,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { case Token::VOID: { Comment cmnt(masm_, "[ UnaryOperation (VOID)"); VisitForEffect(expr->expression()); - switch (context_) { - case Expression::kUninitialized: - UNREACHABLE(); - break; - case Expression::kEffect: - break; - case Expression::kValue: - __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); - switch (location_) { - case kAccumulator: - break; - case kStack: - __ push(result_register()); - break; - } - break; - case Expression::kTest: - __ jmp(false_label_); - break; - } + context()->Plug(Heap::kUndefinedValueRootIndex); break; } @@ -2859,31 +2828,33 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { Label* fall_through = NULL; // Notice that the labels are swapped. - PrepareTest(&materialize_true, &materialize_false, - &if_false, &if_true, &fall_through); + context()->PrepareTest(&materialize_true, &materialize_false, + &if_false, &if_true, &fall_through); VisitForControl(expr->expression(), if_true, if_false, fall_through); - Apply(context_, if_false, if_true); // Labels swapped. + context()->Plug(if_false, if_true); // Labels swapped. break; } case Token::TYPEOF: { Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); - VisitForTypeofValue(expr->expression(), kStack); + { StackValueContext context(this); + VisitForTypeofValue(expr->expression()); + } __ CallRuntime(Runtime::kTypeof, 1); - Apply(context_, r0); + context()->Plug(r0); break; } case Token::ADD: { Comment cmt(masm_, "[ UnaryOperation (ADD)"); - VisitForValue(expr->expression(), kAccumulator); + VisitForAccumulatorValue(expr->expression()); Label no_conversion; __ tst(result_register(), Operand(kSmiTagMask)); __ b(eq, &no_conversion); __ push(r0); __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); __ bind(&no_conversion); - Apply(context_, result_register()); + context()->Plug(result_register()); break; } @@ -2897,9 +2868,9 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { NO_UNARY_FLAGS); // GenericUnaryOpStub expects the argument to be in the // accumulator register r0. - VisitForValue(expr->expression(), kAccumulator); + VisitForAccumulatorValue(expr->expression()); __ CallStub(&stub); - Apply(context_, r0); + context()->Plug(r0); break; } @@ -2907,7 +2878,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)"); // The generic unary operation stub expects the argument to be // in the accumulator register r0. - VisitForValue(expr->expression(), kAccumulator); + VisitForAccumulatorValue(expr->expression()); Label done; bool inline_smi_code = ShouldInlineSmiCase(expr->op()); if (inline_smi_code) { @@ -2928,7 +2899,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { GenericUnaryOpStub stub(Token::BIT_NOT, mode, flags); __ CallStub(&stub); __ bind(&done); - Apply(context_, r0); + context()->Plug(r0); break; } @@ -2964,25 +2935,22 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { // Evaluate expression and get value. if (assign_type == VARIABLE) { ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); - Location saved_location = location_; - location_ = kAccumulator; - EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), - Expression::kValue); - location_ = saved_location; + AccumulatorValueContext context(this); + EmitVariableLoad(expr->expression()->AsVariableProxy()->var()); } else { // Reserve space for result of postfix operation. - if (expr->is_postfix() && context_ != Expression::kEffect) { + if (expr->is_postfix() && !context()->IsEffect()) { __ mov(ip, Operand(Smi::FromInt(0))); __ push(ip); } if (assign_type == NAMED_PROPERTY) { // Put the object both on the stack and in the accumulator. - VisitForValue(prop->obj(), kAccumulator); + VisitForAccumulatorValue(prop->obj()); __ push(r0); EmitNamedPropertyLoad(prop); } else { - VisitForValue(prop->obj(), kStack); - VisitForValue(prop->key(), kAccumulator); + VisitForStackValue(prop->obj()); + VisitForAccumulatorValue(prop->key()); __ ldr(r1, MemOperand(sp, 0)); __ push(r0); EmitKeyedPropertyLoad(prop); @@ -2998,29 +2966,21 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { // Save result for postfix expressions. if (expr->is_postfix()) { - switch (context_) { - case Expression::kUninitialized: - UNREACHABLE(); - case Expression::kEffect: - // Do not save result. - break; - case Expression::kValue: - case Expression::kTest: - // Save the result on the stack. If we have a named or keyed property - // we store the result under the receiver that is currently on top - // of the stack. - switch (assign_type) { - case VARIABLE: - __ push(r0); - break; - case NAMED_PROPERTY: - __ str(r0, MemOperand(sp, kPointerSize)); - break; - case KEYED_PROPERTY: - __ str(r0, MemOperand(sp, 2 * kPointerSize)); - break; - } - break; + if (!context()->IsEffect()) { + // Save the result on the stack. If we have a named or keyed property + // we store the result under the receiver that is currently on top + // of the stack. + switch (assign_type) { + case VARIABLE: + __ push(r0); + break; + case NAMED_PROPERTY: + __ str(r0, MemOperand(sp, kPointerSize)); + break; + case KEYED_PROPERTY: + __ str(r0, MemOperand(sp, 2 * kPointerSize)); + break; + } } } @@ -3047,31 +3007,31 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { switch (assign_type) { case VARIABLE: if (expr->is_postfix()) { - EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), - Token::ASSIGN, - Expression::kEffect); - // For all contexts except kEffect: We have the result on + { EffectContext context(this); + EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), + Token::ASSIGN); + } + // For all contexts except EffectConstant We have the result on // top of the stack. - if (context_ != Expression::kEffect) { - ApplyTOS(context_); + if (!context()->IsEffect()) { + context()->PlugTOS(); } } else { EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), - Token::ASSIGN, - context_); + Token::ASSIGN); } break; case NAMED_PROPERTY: { __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); __ pop(r1); Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); if (expr->is_postfix()) { - if (context_ != Expression::kEffect) { - ApplyTOS(context_); + if (!context()->IsEffect()) { + context()->PlugTOS(); } } else { - Apply(context_, r0); + context()->Plug(r0); } break; } @@ -3079,13 +3039,13 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { __ pop(r1); // Key. __ pop(r2); // Receiver. Handle ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); - __ Call(ic, RelocInfo::CODE_TARGET); + EmitCallIC(ic, RelocInfo::CODE_TARGET); if (expr->is_postfix()) { - if (context_ != Expression::kEffect) { - ApplyTOS(context_); + if (!context()->IsEffect()) { + context()->PlugTOS(); } } else { - Apply(context_, r0); + context()->Plug(r0); } break; } @@ -3093,7 +3053,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { } -void FullCodeGenerator::VisitForTypeofValue(Expression* expr, Location where) { +void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { + ASSERT(!context()->IsEffect()); + ASSERT(!context()->IsTest()); VariableProxy* proxy = expr->AsVariableProxy(); if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { Comment cmnt(masm_, "Global variable"); @@ -3102,16 +3064,16 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr, Location where) { Handle ic(Builtins::builtin(Builtins::LoadIC_Initialize)); // Use a regular load, not a contextual load, to avoid a reference // error. - __ Call(ic, RelocInfo::CODE_TARGET); - if (where == kStack) __ push(r0); + EmitCallIC(ic, RelocInfo::CODE_TARGET); + context()->Plug(r0); } else if (proxy != NULL && - proxy->var()->slot() != NULL && - proxy->var()->slot()->type() == Slot::LOOKUP) { + proxy->var()->AsSlot() != NULL && + proxy->var()->AsSlot()->type() == Slot::LOOKUP) { Label done, slow; // Generate code for loading from variables potentially shadowed // by eval-introduced variables. - Slot* slot = proxy->var()->slot(); + Slot* slot = proxy->var()->AsSlot(); EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); __ bind(&slow); @@ -3120,10 +3082,10 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr, Location where) { __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); __ bind(&done); - if (where == kStack) __ push(r0); + context()->Plug(r0); } else { // This expression cannot throw a reference error at the top level. - VisitForValue(expr, where); + Visit(expr); } } @@ -3145,7 +3107,9 @@ bool FullCodeGenerator::TryLiteralCompare(Token::Value op, if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false; Handle check = Handle::cast(right_literal_value); - VisitForTypeofValue(left_unary->expression(), kAccumulator); + { AccumulatorValueContext context(this); + VisitForTypeofValue(left_unary->expression()); + } if (check->Equals(Heap::number_symbol())) { __ tst(r0, Operand(kSmiTagMask)); __ b(eq, if_true); @@ -3231,8 +3195,8 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { Label* if_true = NULL; Label* if_false = NULL; Label* fall_through = NULL; - PrepareTest(&materialize_true, &materialize_false, - &if_true, &if_false, &fall_through); + context()->PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); // First we try a fast inlined version of the compare when one of // the operands is a literal. @@ -3240,14 +3204,14 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { Expression* left = expr->left(); Expression* right = expr->right(); if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) { - Apply(context_, if_true, if_false); + context()->Plug(if_true, if_false); return; } - VisitForValue(expr->left(), kStack); + VisitForStackValue(expr->left()); switch (op) { case Token::IN: - VisitForValue(expr->right(), kStack); + VisitForStackValue(expr->right()); __ InvokeBuiltin(Builtins::IN, CALL_JS); __ LoadRoot(ip, Heap::kTrueValueRootIndex); __ cmp(r0, ip); @@ -3255,7 +3219,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { break; case Token::INSTANCEOF: { - VisitForValue(expr->right(), kStack); + VisitForStackValue(expr->right()); InstanceofStub stub; __ CallStub(&stub); // The stub returns 0 for true. @@ -3265,7 +3229,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { } default: { - VisitForValue(expr->right(), kAccumulator); + VisitForAccumulatorValue(expr->right()); Condition cc = eq; bool strict = false; switch (op) { @@ -3323,7 +3287,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { // Convert the result of the comparison into one expected for this // expression's context. - Apply(context_, if_true, if_false); + context()->Plug(if_true, if_false); } @@ -3333,10 +3297,10 @@ void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { Label* if_true = NULL; Label* if_false = NULL; Label* fall_through = NULL; - PrepareTest(&materialize_true, &materialize_false, - &if_true, &if_false, &fall_through); + context()->PrepareTest(&materialize_true, &materialize_false, + &if_true, &if_false, &fall_through); - VisitForValue(expr->expression(), kAccumulator); + VisitForAccumulatorValue(expr->expression()); __ LoadRoot(r1, Heap::kNullValueRootIndex); __ cmp(r0, r1); if (expr->is_strict()) { @@ -3355,20 +3319,31 @@ void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { __ cmp(r1, Operand(1 << Map::kIsUndetectable)); Split(eq, if_true, if_false, fall_through); } - Apply(context_, if_true, if_false); + context()->Plug(if_true, if_false); } void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); - Apply(context_, r0); + context()->Plug(r0); } -Register FullCodeGenerator::result_register() { return r0; } +Register FullCodeGenerator::result_register() { + return r0; +} -Register FullCodeGenerator::context_register() { return cp; } +Register FullCodeGenerator::context_register() { + return cp; +} + + +void FullCodeGenerator::EmitCallIC(Handle ic, RelocInfo::Mode mode) { + ASSERT(mode == RelocInfo::CODE_TARGET || + mode == RelocInfo::CODE_TARGET_CONTEXT); + __ Call(ic, mode); +} void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { diff --git a/deps/v8/src/arm/ic-arm.cc b/deps/v8/src/arm/ic-arm.cc index 1a76db2ce3..eab4c6e8ed 100644 --- a/deps/v8/src/arm/ic-arm.cc +++ b/deps/v8/src/arm/ic-arm.cc @@ -967,6 +967,14 @@ bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { } +bool LoadIC::PatchInlinedContextualLoad(Address address, + Object* map, + Object* cell) { + // TODO(): implement this. + return false; +} + + bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) { // Find the end of the inlined code for the store if there is an // inlined version of the store. @@ -1236,7 +1244,6 @@ void KeyedLoadIC::GenerateString(MacroAssembler* masm) { // -- r1 : receiver // ----------------------------------- Label miss; - Label index_out_of_range; Register receiver = r1; Register index = r0; @@ -1251,7 +1258,7 @@ void KeyedLoadIC::GenerateString(MacroAssembler* masm) { result, &miss, // When not a string. &miss, // When not a number. - &index_out_of_range, + &miss, // When index out of range. STRING_INDEX_IS_ARRAY_INDEX); char_at_generator.GenerateFast(masm); __ Ret(); @@ -1259,10 +1266,6 @@ void KeyedLoadIC::GenerateString(MacroAssembler* masm) { ICRuntimeCallHelper call_helper; char_at_generator.GenerateSlow(masm, call_helper); - __ bind(&index_out_of_range); - __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); - __ Ret(); - __ bind(&miss); GenerateMiss(masm); } @@ -1581,8 +1584,9 @@ void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { // Check that the receiver isn't a smi. __ BranchOnSmi(r1, &slow); - // Check that the key is a smi. - __ BranchOnNotSmi(r0, &slow); + // Check that the key is an array index, that is Uint32. + __ tst(r0, Operand(kSmiTagMask | kSmiSignMask)); + __ b(ne, &slow); // Get the map of the receiver. __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); diff --git a/deps/v8/src/arm/simulator-arm.cc b/deps/v8/src/arm/simulator-arm.cc index 64262b2b81..40be9bb818 100644 --- a/deps/v8/src/arm/simulator-arm.cc +++ b/deps/v8/src/arm/simulator-arm.cc @@ -294,7 +294,7 @@ void Debugger::Debug() { } else if (GetVFPSingleValue(arg1, &svalue)) { PrintF("%s: %f \n", arg1, svalue); } else if (GetVFPDoubleValue(arg1, &dvalue)) { - PrintF("%s: %lf \n", arg1, dvalue); + PrintF("%s: %f \n", arg1, dvalue); } else { PrintF("%s unrecognized\n", arg1); } @@ -349,7 +349,8 @@ void Debugger::Debug() { end = cur + words; while (cur < end) { - PrintF(" 0x%08x: 0x%08x %10d\n", cur, *cur, *cur); + PrintF(" 0x%08x: 0x%08x %10d\n", + reinterpret_cast(cur), *cur, *cur); cur++; } } else if (strcmp(cmd, "disasm") == 0) { @@ -382,7 +383,8 @@ void Debugger::Debug() { while (cur < end) { dasm.InstructionDecode(buffer, cur); - PrintF(" 0x%08x %s\n", cur, buffer.start()); + PrintF(" 0x%08x %s\n", + reinterpret_cast(cur), buffer.start()); cur += Instr::kInstrSize; } } else if (strcmp(cmd, "gdb") == 0) { @@ -1061,7 +1063,7 @@ uintptr_t Simulator::StackLimit() const { // Unsupported instructions use Format to print an error and stop execution. void Simulator::Format(Instr* instr, const char* format) { PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n", - instr, format); + reinterpret_cast(instr), format); UNIMPLEMENTED(); } @@ -2650,7 +2652,7 @@ void Simulator::InstructionDecode(Instr* instr) { v8::internal::EmbeddedVector buffer; dasm.InstructionDecode(buffer, reinterpret_cast(instr)); - PrintF(" 0x%08x %s\n", instr, buffer.start()); + PrintF(" 0x%08x %s\n", reinterpret_cast(instr), buffer.start()); } if (instr->ConditionField() == special_condition) { DecodeUnconditional(instr); diff --git a/deps/v8/src/arm/stub-cache-arm.cc b/deps/v8/src/arm/stub-cache-arm.cc index 0da5f64696..97f94952d7 100644 --- a/deps/v8/src/arm/stub-cache-arm.cc +++ b/deps/v8/src/arm/stub-cache-arm.cc @@ -266,7 +266,12 @@ void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( - MacroAssembler* masm, int index, Register prototype) { + MacroAssembler* masm, int index, Register prototype, Label* miss) { + // Check we're still in the same context. + __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); + __ Move(ip, Top::global()); + __ cmp(prototype, ip); + __ b(ne, miss); // Get the global function with the given index. JSFunction* function = JSFunction::cast(Top::global_context()->get(index)); // Load its initial map. The global functions all have initial maps. @@ -1434,7 +1439,8 @@ Object* CallStubCompiler::CompileStringCharCodeAtCall( // Check that the maps starting from the prototype haven't changed. GenerateDirectLoadGlobalFunctionPrototype(masm(), Context::STRING_FUNCTION_INDEX, - r0); + r0, + &miss); ASSERT(object != holder); CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r1, r3, r4, name, &miss); @@ -1505,7 +1511,8 @@ Object* CallStubCompiler::CompileStringCharAtCall(Object* object, // Check that the maps starting from the prototype haven't changed. GenerateDirectLoadGlobalFunctionPrototype(masm(), Context::STRING_FUNCTION_INDEX, - r0); + r0, + &miss); ASSERT(object != holder); CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r1, r3, r4, name, &miss); @@ -1626,6 +1633,118 @@ Object* CallStubCompiler::CompileStringFromCharCodeCall( } +Object* CallStubCompiler::CompileMathFloorCall(Object* object, + JSObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name) { + // TODO(872): implement this. + return Heap::undefined_value(); +} + + +Object* CallStubCompiler::CompileMathAbsCall(Object* object, + JSObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name) { + // ----------- S t a t e ------------- + // -- r2 : function name + // -- lr : return address + // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) + // -- ... + // -- sp[argc * 4] : receiver + // ----------------------------------- + + const int argc = arguments().immediate(); + + // If the object is not a JSObject or we got an unexpected number of + // arguments, bail out to the regular call. + if (!object->IsJSObject() || argc != 1) return Heap::undefined_value(); + + Label miss; + GenerateNameCheck(name, &miss); + + if (cell == NULL) { + __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); + + STATIC_ASSERT(kSmiTag == 0); + __ tst(r1, Operand(kSmiTagMask)); + __ b(eq, &miss); + + CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, + &miss); + } else { + ASSERT(cell->value() == function); + GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); + GenerateLoadFunctionFromCell(cell, function, &miss); + } + + // Load the (only) argument into r0. + __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); + + // Check if the argument is a smi. + Label not_smi; + STATIC_ASSERT(kSmiTag == 0); + __ BranchOnNotSmi(r0, ¬_smi); + + // Do bitwise not or do nothing depending on the sign of the + // argument. + __ eor(r1, r0, Operand(r0, ASR, kBitsPerInt - 1)); + + // Add 1 or do nothing depending on the sign of the argument. + __ sub(r0, r1, Operand(r0, ASR, kBitsPerInt - 1), SetCC); + + // If the result is still negative, go to the slow case. + // This only happens for the most negative smi. + Label slow; + __ b(mi, &slow); + + // Smi case done. + __ Drop(argc + 1); + __ Ret(); + + // Check if the argument is a heap number and load its exponent and + // sign. + __ bind(¬_smi); + __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, true); + __ ldr(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset)); + + // Check the sign of the argument. If the argument is positive, + // just return it. + Label negative_sign; + __ tst(r1, Operand(HeapNumber::kSignMask)); + __ b(ne, &negative_sign); + __ Drop(argc + 1); + __ Ret(); + + // If the argument is negative, clear the sign, and return a new + // number. + __ bind(&negative_sign); + __ eor(r1, r1, Operand(HeapNumber::kSignMask)); + __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); + __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); + __ AllocateHeapNumber(r0, r4, r5, r6, &slow); + __ str(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset)); + __ str(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); + __ Drop(argc + 1); + __ Ret(); + + // Tail call the full function. We do not have to patch the receiver + // because the function makes no use of it. + __ bind(&slow); + __ InvokeFunction(function, arguments(), JUMP_FUNCTION); + + __ bind(&miss); + // r2: function name. + Object* obj = GenerateMissBranch(); + if (obj->IsFailure()) return obj; + + // Return the generated code. + return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); +} + + Object* CallStubCompiler::CompileCallConstant(Object* object, JSObject* holder, JSFunction* function, @@ -1705,7 +1824,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, __ b(hs, &miss); // Check that the maps starting from the prototype haven't changed. GenerateDirectLoadGlobalFunctionPrototype( - masm(), Context::STRING_FUNCTION_INDEX, r0); + masm(), Context::STRING_FUNCTION_INDEX, r0, &miss); CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, r1, r4, name, &miss); } @@ -1725,7 +1844,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, __ bind(&fast); // Check that the maps starting from the prototype haven't changed. GenerateDirectLoadGlobalFunctionPrototype( - masm(), Context::NUMBER_FUNCTION_INDEX, r0); + masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss); CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, r1, r4, name, &miss); } @@ -1748,7 +1867,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, __ bind(&fast); // Check that the maps starting from the prototype haven't changed. GenerateDirectLoadGlobalFunctionPrototype( - masm(), Context::BOOLEAN_FUNCTION_INDEX, r0); + masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss); CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, r1, r4, name, &miss); } @@ -2067,7 +2186,10 @@ Object* LoadStubCompiler::CompileLoadNonexistent(String* name, name, r1, &miss); - if (cell->IsFailure()) return cell; + if (cell->IsFailure()) { + miss.Unuse(); + return cell; + } } // Return undefined if maps of the full prototype chain are still the @@ -2117,7 +2239,10 @@ Object* LoadStubCompiler::CompileLoadCallback(String* name, Failure* failure = Failure::InternalError(); bool success = GenerateLoadCallback(object, holder, r0, r2, r3, r1, r4, callback, name, &miss, &failure); - if (!success) return failure; + if (!success) { + miss.Unuse(); + return failure; + } __ bind(&miss); GenerateLoadMiss(masm(), Code::LOAD_IC); @@ -2212,11 +2337,11 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object, } __ mov(r0, r4); - __ IncrementCounter(&Counters::named_load_global_inline, 1, r1, r3); + __ IncrementCounter(&Counters::named_load_global_stub, 1, r1, r3); __ Ret(); __ bind(&miss); - __ IncrementCounter(&Counters::named_load_global_inline_miss, 1, r1, r3); + __ IncrementCounter(&Counters::named_load_global_stub_miss, 1, r1, r3); GenerateLoadMiss(masm(), Code::LOAD_IC); // Return the generated code. @@ -2265,7 +2390,10 @@ Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, Failure* failure = Failure::InternalError(); bool success = GenerateLoadCallback(receiver, holder, r1, r0, r2, r3, r4, callback, name, &miss, &failure); - if (!success) return failure; + if (!success) { + miss.Unuse(); + return failure; + } __ bind(&miss); GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); diff --git a/deps/v8/src/assembler.cc b/deps/v8/src/assembler.cc index 6a46f61595..b6efdb97e5 100644 --- a/deps/v8/src/assembler.cc +++ b/deps/v8/src/assembler.cc @@ -465,7 +465,7 @@ const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) { void RelocInfo::Print() { PrintF("%p %s", pc_, RelocModeName(rmode_)); if (IsComment(rmode_)) { - PrintF(" (%s)", data_); + PrintF(" (%s)", reinterpret_cast(data_)); } else if (rmode_ == EMBEDDED_OBJECT) { PrintF(" ("); target_object()->ShortPrint(); @@ -479,7 +479,7 @@ void RelocInfo::Print() { Code* code = Code::GetCodeFromTargetAddress(target_address()); PrintF(" (%s) (%p)", Code::Kind2String(code->kind()), target_address()); } else if (IsPosition(rmode_)) { - PrintF(" (%d)", data()); + PrintF(" (%" V8_PTR_PREFIX "d)", data()); } PrintF("\n"); diff --git a/deps/v8/src/assembler.h b/deps/v8/src/assembler.h index 1577433591..d28bf43709 100644 --- a/deps/v8/src/assembler.h +++ b/deps/v8/src/assembler.h @@ -57,7 +57,7 @@ class Label BASE_EMBEDDED { INLINE(void Unuse()) { pos_ = 0; } - INLINE(bool is_bound() const) { return pos_ < 0; } + INLINE(bool is_bound() const) { return pos_ < 0; } INLINE(bool is_unused() const) { return pos_ == 0; } INLINE(bool is_linked() const) { return pos_ > 0; } @@ -91,6 +91,57 @@ class Label BASE_EMBEDDED { }; +// ----------------------------------------------------------------------------- +// NearLabels are labels used for short jumps (in Intel jargon). +// NearLabels should be used if it can be guaranteed that the jump range is +// within -128 to +127. We already use short jumps when jumping backwards, +// so using a NearLabel will only have performance impact if used for forward +// jumps. +class NearLabel BASE_EMBEDDED { + public: + NearLabel() { Unuse(); } + ~NearLabel() { ASSERT(!is_linked()); } + + void Unuse() { + pos_ = -1; + unresolved_branches_ = 0; +#ifdef DEBUG + for (int i = 0; i < kMaxUnresolvedBranches; i++) { + unresolved_positions_[i] = -1; + } +#endif + } + + int pos() { + ASSERT(is_bound()); + return pos_; + } + + bool is_bound() { return pos_ >= 0; } + bool is_linked() { return !is_bound() && unresolved_branches_ > 0; } + bool is_unused() { return !is_bound() && unresolved_branches_ == 0; } + + void bind_to(int position) { + ASSERT(!is_bound()); + pos_ = position; + } + + void link_to(int position) { + ASSERT(!is_bound()); + ASSERT(unresolved_branches_ < kMaxUnresolvedBranches); + unresolved_positions_[unresolved_branches_++] = position; + } + + private: + static const int kMaxUnresolvedBranches = 8; + int pos_; + int unresolved_branches_; + int unresolved_positions_[kMaxUnresolvedBranches]; + + friend class Assembler; +}; + + // ----------------------------------------------------------------------------- // Relocation information @@ -181,10 +232,10 @@ class RelocInfo BASE_EMBEDDED { static inline int ModeMask(Mode mode) { return 1 << mode; } // Accessors - byte* pc() const { return pc_; } + byte* pc() const { return pc_; } void set_pc(byte* pc) { pc_ = pc; } Mode rmode() const { return rmode_; } - intptr_t data() const { return data_; } + intptr_t data() const { return data_; } // Apply a relocation by delta bytes INLINE(void apply(intptr_t delta)); @@ -339,7 +390,7 @@ class RelocIterator: public Malloced { explicit RelocIterator(const CodeDesc& desc, int mode_mask = -1); // Iteration - bool done() const { return done_; } + bool done() const { return done_; } void next(); // Return pointer valid until next next(). diff --git a/deps/v8/src/ast.cc b/deps/v8/src/ast.cc index 9ff1be73bc..f47dffd8d7 100644 --- a/deps/v8/src/ast.cc +++ b/deps/v8/src/ast.cc @@ -70,6 +70,16 @@ CountOperation* ExpressionStatement::StatementAsCountOperation() { } +VariableProxy::VariableProxy(Variable* var) + : name_(var->name()), + var_(NULL), // Will be set by the call to BindTo. + is_this_(var->is_this()), + inside_with_(false), + is_trivial_(false) { + BindTo(var); +} + + VariableProxy::VariableProxy(Handle name, bool is_this, bool inside_with) diff --git a/deps/v8/src/ast.h b/deps/v8/src/ast.h index 9fcf25672f..fc34fd4614 100644 --- a/deps/v8/src/ast.h +++ b/deps/v8/src/ast.h @@ -118,35 +118,38 @@ typedef ZoneList > ZoneStringList; typedef ZoneList > ZoneObjectList; +#define DECLARE_NODE_TYPE(type) \ + virtual void Accept(AstVisitor* v); \ + virtual AstNode::Type node_type() const { return AstNode::k##type; } \ + virtual type* As##type() { return this; } + + class AstNode: public ZoneObject { public: +#define DECLARE_TYPE_ENUM(type) k##type, + enum Type { + AST_NODE_LIST(DECLARE_TYPE_ENUM) + kInvalid = -1 + }; +#undef DECLARE_TYPE_ENUM + virtual ~AstNode() { } + virtual void Accept(AstVisitor* v) = 0; + virtual Type node_type() const { return kInvalid; } + + // Type testing & conversion functions overridden by concrete subclasses. +#define DECLARE_NODE_FUNCTIONS(type) \ + virtual type* As##type() { return NULL; } + AST_NODE_LIST(DECLARE_NODE_FUNCTIONS) +#undef DECLARE_NODE_FUNCTIONS - // Type testing & conversion. virtual Statement* AsStatement() { return NULL; } - virtual Block* AsBlock() { return NULL; } - virtual ExpressionStatement* AsExpressionStatement() { return NULL; } - virtual EmptyStatement* AsEmptyStatement() { return NULL; } virtual Expression* AsExpression() { return NULL; } - virtual Literal* AsLiteral() { return NULL; } - virtual Slot* AsSlot() { return NULL; } - virtual VariableProxy* AsVariableProxy() { return NULL; } - virtual Property* AsProperty() { return NULL; } - virtual Call* AsCall() { return NULL; } virtual TargetCollector* AsTargetCollector() { return NULL; } virtual BreakableStatement* AsBreakableStatement() { return NULL; } virtual IterationStatement* AsIterationStatement() { return NULL; } - virtual ForStatement* AsForStatement() { return NULL; } - virtual UnaryOperation* AsUnaryOperation() { return NULL; } - virtual CountOperation* AsCountOperation() { return NULL; } - virtual BinaryOperation* AsBinaryOperation() { return NULL; } - virtual Assignment* AsAssignment() { return NULL; } - virtual FunctionLiteral* AsFunctionLiteral() { return NULL; } virtual MaterializedLiteral* AsMaterializedLiteral() { return NULL; } - virtual ObjectLiteral* AsObjectLiteral() { return NULL; } - virtual ArrayLiteral* AsArrayLiteral() { return NULL; } - virtual CompareOperation* AsCompareOperation() { return NULL; } }; @@ -155,7 +158,6 @@ class Statement: public AstNode { Statement() : statement_pos_(RelocInfo::kNoPosition) {} virtual Statement* AsStatement() { return this; } - virtual ReturnStatement* AsReturnStatement() { return NULL; } virtual Assignment* StatementAsSimpleAssignment() { return NULL; } virtual CountOperation* StatementAsCountOperation() { return NULL; } @@ -172,18 +174,6 @@ class Statement: public AstNode { class Expression: public AstNode { public: - enum Context { - // Not assigned a context yet, or else will not be visited during - // code generation. - kUninitialized, - // Evaluated for its side effects. - kEffect, - // Evaluated for its value (and side effects). - kValue, - // Evaluated for control flow (and side effects). - kTest - }; - Expression() : bitfields_(0) {} virtual Expression* AsExpression() { return this; } @@ -325,9 +315,7 @@ class Block: public BreakableStatement { public: inline Block(ZoneStringList* labels, int capacity, bool is_initializer_block); - virtual void Accept(AstVisitor* v); - - virtual Block* AsBlock() { return this; } + DECLARE_NODE_TYPE(Block) virtual Assignment* StatementAsSimpleAssignment() { if (statements_.length() != 1) return NULL; @@ -342,7 +330,7 @@ class Block: public BreakableStatement { void AddStatement(Statement* statement) { statements_.Add(statement); } ZoneList* statements() { return &statements_; } - bool is_initializer_block() const { return is_initializer_block_; } + bool is_initializer_block() const { return is_initializer_block_; } private: ZoneList statements_; @@ -361,11 +349,11 @@ class Declaration: public AstNode { ASSERT(fun == NULL || mode == Variable::VAR); } - virtual void Accept(AstVisitor* v); + DECLARE_NODE_TYPE(Declaration) - VariableProxy* proxy() const { return proxy_; } - Variable::Mode mode() const { return mode_; } - FunctionLiteral* fun() const { return fun_; } // may be NULL + VariableProxy* proxy() const { return proxy_; } + Variable::Mode mode() const { return mode_; } + FunctionLiteral* fun() const { return fun_; } // may be NULL private: VariableProxy* proxy_; @@ -402,13 +390,13 @@ class DoWhileStatement: public IterationStatement { public: explicit inline DoWhileStatement(ZoneStringList* labels); + DECLARE_NODE_TYPE(DoWhileStatement) + void Initialize(Expression* cond, Statement* body) { IterationStatement::Initialize(body); cond_ = cond; } - virtual void Accept(AstVisitor* v); - Expression* cond() const { return cond_; } // Position where condition expression starts. We need it to make @@ -426,13 +414,13 @@ class WhileStatement: public IterationStatement { public: explicit WhileStatement(ZoneStringList* labels); + DECLARE_NODE_TYPE(WhileStatement) + void Initialize(Expression* cond, Statement* body) { IterationStatement::Initialize(body); cond_ = cond; } - virtual void Accept(AstVisitor* v); - Expression* cond() const { return cond_; } bool may_have_function_literal() const { return may_have_function_literal_; @@ -452,7 +440,7 @@ class ForStatement: public IterationStatement { public: explicit inline ForStatement(ZoneStringList* labels); - virtual ForStatement* AsForStatement() { return this; } + DECLARE_NODE_TYPE(ForStatement) void Initialize(Statement* init, Expression* cond, @@ -464,13 +452,11 @@ class ForStatement: public IterationStatement { next_ = next; } - virtual void Accept(AstVisitor* v); - - Statement* init() const { return init_; } + Statement* init() const { return init_; } void set_init(Statement* stmt) { init_ = stmt; } - Expression* cond() const { return cond_; } + Expression* cond() const { return cond_; } void set_cond(Expression* expr) { cond_ = expr; } - Statement* next() const { return next_; } + Statement* next() const { return next_; } void set_next(Statement* stmt) { next_ = stmt; } bool may_have_function_literal() const { @@ -498,14 +484,14 @@ class ForInStatement: public IterationStatement { public: explicit inline ForInStatement(ZoneStringList* labels); + DECLARE_NODE_TYPE(ForInStatement) + void Initialize(Expression* each, Expression* enumerable, Statement* body) { IterationStatement::Initialize(body); each_ = each; enumerable_ = enumerable; } - virtual void Accept(AstVisitor* v); - Expression* each() const { return each_; } Expression* enumerable() const { return enumerable_; } @@ -520,10 +506,7 @@ class ExpressionStatement: public Statement { explicit ExpressionStatement(Expression* expression) : expression_(expression) { } - virtual void Accept(AstVisitor* v); - - // Type testing & conversion. - virtual ExpressionStatement* AsExpressionStatement() { return this; } + DECLARE_NODE_TYPE(ExpressionStatement) virtual Assignment* StatementAsSimpleAssignment(); virtual CountOperation* StatementAsCountOperation(); @@ -541,9 +524,9 @@ class ContinueStatement: public Statement { explicit ContinueStatement(IterationStatement* target) : target_(target) { } - virtual void Accept(AstVisitor* v); + DECLARE_NODE_TYPE(ContinueStatement) - IterationStatement* target() const { return target_; } + IterationStatement* target() const { return target_; } private: IterationStatement* target_; @@ -555,9 +538,9 @@ class BreakStatement: public Statement { explicit BreakStatement(BreakableStatement* target) : target_(target) { } - virtual void Accept(AstVisitor* v); + DECLARE_NODE_TYPE(BreakStatement) - BreakableStatement* target() const { return target_; } + BreakableStatement* target() const { return target_; } private: BreakableStatement* target_; @@ -569,10 +552,7 @@ class ReturnStatement: public Statement { explicit ReturnStatement(Expression* expression) : expression_(expression) { } - virtual void Accept(AstVisitor* v); - - // Type testing & conversion. - virtual ReturnStatement* AsReturnStatement() { return this; } + DECLARE_NODE_TYPE(ReturnStatement) Expression* expression() { return expression_; } @@ -586,9 +566,9 @@ class WithEnterStatement: public Statement { explicit WithEnterStatement(Expression* expression, bool is_catch_block) : expression_(expression), is_catch_block_(is_catch_block) { } - virtual void Accept(AstVisitor* v); + DECLARE_NODE_TYPE(WithEnterStatement) - Expression* expression() const { return expression_; } + Expression* expression() const { return expression_; } bool is_catch_block() const { return is_catch_block_; } @@ -602,7 +582,7 @@ class WithExitStatement: public Statement { public: WithExitStatement() { } - virtual void Accept(AstVisitor* v); + DECLARE_NODE_TYPE(WithExitStatement) }; @@ -610,13 +590,13 @@ class CaseClause: public ZoneObject { public: CaseClause(Expression* label, ZoneList* statements); - bool is_default() const { return label_ == NULL; } - Expression* label() const { + bool is_default() const { return label_ == NULL; } + Expression* label() const { CHECK(!is_default()); return label_; } JumpTarget* body_target() { return &body_target_; } - ZoneList* statements() const { return statements_; } + ZoneList* statements() const { return statements_; } private: Expression* label_; @@ -629,15 +609,15 @@ class SwitchStatement: public BreakableStatement { public: explicit inline SwitchStatement(ZoneStringList* labels); + DECLARE_NODE_TYPE(SwitchStatement) + void Initialize(Expression* tag, ZoneList* cases) { tag_ = tag; cases_ = cases; } - virtual void Accept(AstVisitor* v); - - Expression* tag() const { return tag_; } - ZoneList* cases() const { return cases_; } + Expression* tag() const { return tag_; } + ZoneList* cases() const { return cases_; } private: Expression* tag_; @@ -659,7 +639,7 @@ class IfStatement: public Statement { then_statement_(then_statement), else_statement_(else_statement) { } - virtual void Accept(AstVisitor* v); + DECLARE_NODE_TYPE(IfStatement) bool HasThenStatement() const { return !then_statement()->IsEmpty(); } bool HasElseStatement() const { return !else_statement()->IsEmpty(); } @@ -729,10 +709,10 @@ class TryCatchStatement: public TryStatement { catch_block_(catch_block) { } - virtual void Accept(AstVisitor* v); + DECLARE_NODE_TYPE(TryCatchStatement) - VariableProxy* catch_var() const { return catch_var_; } - Block* catch_block() const { return catch_block_; } + VariableProxy* catch_var() const { return catch_var_; } + Block* catch_block() const { return catch_block_; } private: VariableProxy* catch_var_; @@ -746,7 +726,7 @@ class TryFinallyStatement: public TryStatement { : TryStatement(try_block), finally_block_(finally_block) { } - virtual void Accept(AstVisitor* v); + DECLARE_NODE_TYPE(TryFinallyStatement) Block* finally_block() const { return finally_block_; } @@ -757,18 +737,13 @@ class TryFinallyStatement: public TryStatement { class DebuggerStatement: public Statement { public: - virtual void Accept(AstVisitor* v); + DECLARE_NODE_TYPE(DebuggerStatement) }; class EmptyStatement: public Statement { public: - EmptyStatement() {} - - virtual void Accept(AstVisitor* v); - - // Type testing & conversion. - virtual EmptyStatement* AsEmptyStatement() { return this; } + DECLARE_NODE_TYPE(EmptyStatement) }; @@ -776,13 +751,11 @@ class Literal: public Expression { public: explicit Literal(Handle handle) : handle_(handle) { } - virtual void Accept(AstVisitor* v); + DECLARE_NODE_TYPE(Literal) + virtual bool IsTrivial() { return true; } virtual bool IsSmiLiteral() { return handle_->IsSmi(); } - // Type testing & conversion. - virtual Literal* AsLiteral() { return this; } - // Check if this literal is identical to the other literal. bool IsIdenticalTo(const Literal* other) const { return handle_.is_identical_to(other->handle_); @@ -876,8 +849,7 @@ class ObjectLiteral: public MaterializedLiteral { properties_(properties), fast_elements_(fast_elements) {} - virtual ObjectLiteral* AsObjectLiteral() { return this; } - virtual void Accept(AstVisitor* v); + DECLARE_NODE_TYPE(ObjectLiteral) Handle constant_properties() const { return constant_properties_; @@ -903,7 +875,7 @@ class RegExpLiteral: public MaterializedLiteral { pattern_(pattern), flags_(flags) {} - virtual void Accept(AstVisitor* v); + DECLARE_NODE_TYPE(RegExpLiteral) Handle pattern() const { return pattern_; } Handle flags() const { return flags_; } @@ -926,8 +898,7 @@ class ArrayLiteral: public MaterializedLiteral { constant_elements_(constant_elements), values_(values) {} - virtual void Accept(AstVisitor* v); - virtual ArrayLiteral* AsArrayLiteral() { return this; } + DECLARE_NODE_TYPE(ArrayLiteral) Handle constant_elements() const { return constant_elements_; } ZoneList* values() const { return values_; } @@ -947,7 +918,7 @@ class CatchExtensionObject: public Expression { : key_(key), value_(value) { } - virtual void Accept(AstVisitor* v); + DECLARE_NODE_TYPE(CatchExtensionObject) Literal* key() const { return key_; } VariableProxy* value() const { return value_; } @@ -960,19 +931,20 @@ class CatchExtensionObject: public Expression { class VariableProxy: public Expression { public: - virtual void Accept(AstVisitor* v); + explicit VariableProxy(Variable* var); + + DECLARE_NODE_TYPE(VariableProxy) // Type testing & conversion virtual Property* AsProperty() { return var_ == NULL ? NULL : var_->AsProperty(); } - virtual VariableProxy* AsVariableProxy() { - return this; - } - Variable* AsVariable() { - return this == NULL || var_ == NULL ? NULL : var_->AsVariable(); + if (this == NULL || var_ == NULL) return NULL; + Expression* rewrite = var_->rewrite(); + if (rewrite == NULL || rewrite->AsSlot() != NULL) return var_; + return NULL; } virtual bool IsValidLeftHandSide() { @@ -994,10 +966,10 @@ class VariableProxy: public Expression { return (variable == NULL) ? false : variable->is_arguments(); } - Handle name() const { return name_; } - Variable* var() const { return var_; } - bool is_this() const { return is_this_; } - bool inside_with() const { return inside_with_; } + Handle name() const { return name_; } + Variable* var() const { return var_; } + bool is_this() const { return is_this_; } + bool inside_with() const { return inside_with_; } void MarkAsTrivial() { is_trivial_ = true; } @@ -1062,10 +1034,7 @@ class Slot: public Expression { ASSERT(var != NULL); } - virtual void Accept(AstVisitor* v); - - // Type testing & conversion - virtual Slot* AsSlot() { return this; } + DECLARE_NODE_TYPE(Slot) bool IsStackAllocated() { return type_ == PARAMETER || type_ == LOCAL; } @@ -1092,10 +1061,7 @@ class Property: public Expression { Property(Expression* obj, Expression* key, int pos, Type type = NORMAL) : obj_(obj), key_(key), pos_(pos), type_(type) { } - virtual void Accept(AstVisitor* v); - - // Type testing & conversion - virtual Property* AsProperty() { return this; } + DECLARE_NODE_TYPE(Property) virtual bool IsValidLeftHandSide() { return true; } @@ -1124,10 +1090,7 @@ class Call: public Expression { Call(Expression* expression, ZoneList* arguments, int pos) : expression_(expression), arguments_(arguments), pos_(pos) { } - virtual void Accept(AstVisitor* v); - - // Type testing and conversion. - virtual Call* AsCall() { return this; } + DECLARE_NODE_TYPE(Call) Expression* expression() const { return expression_; } ZoneList* arguments() const { return arguments_; } @@ -1149,7 +1112,7 @@ class CallNew: public Expression { CallNew(Expression* expression, ZoneList* arguments, int pos) : expression_(expression), arguments_(arguments), pos_(pos) { } - virtual void Accept(AstVisitor* v); + DECLARE_NODE_TYPE(CallNew) Expression* expression() const { return expression_; } ZoneList* arguments() const { return arguments_; } @@ -1173,7 +1136,7 @@ class CallRuntime: public Expression { ZoneList* arguments) : name_(name), function_(function), arguments_(arguments) { } - virtual void Accept(AstVisitor* v); + DECLARE_NODE_TYPE(CallRuntime) Handle name() const { return name_; } Runtime::Function* function() const { return function_; } @@ -1194,11 +1157,9 @@ class UnaryOperation: public Expression { ASSERT(Token::IsUnaryOp(op)); } - virtual void Accept(AstVisitor* v); - virtual bool ResultOverwriteAllowed(); + DECLARE_NODE_TYPE(UnaryOperation) - // Type testing & conversion - virtual UnaryOperation* AsUnaryOperation() { return this; } + virtual bool ResultOverwriteAllowed(); Token::Value op() const { return op_; } Expression* expression() const { return expression_; } @@ -1222,11 +1183,9 @@ class BinaryOperation: public Expression { // Create the binary operation corresponding to a compound assignment. explicit BinaryOperation(Assignment* assignment); - virtual void Accept(AstVisitor* v); - virtual bool ResultOverwriteAllowed(); + DECLARE_NODE_TYPE(BinaryOperation) - // Type testing & conversion - virtual BinaryOperation* AsBinaryOperation() { return this; } + virtual bool ResultOverwriteAllowed(); Token::Value op() const { return op_; } Expression* left() const { return left_; } @@ -1248,12 +1207,12 @@ class IncrementOperation: public Expression { ASSERT(Token::IsCountOp(op)); } + DECLARE_NODE_TYPE(IncrementOperation) + Token::Value op() const { return op_; } bool is_increment() { return op_ == Token::INC; } Expression* expression() const { return expression_; } - virtual void Accept(AstVisitor* v); - private: Token::Value op_; Expression* expression_; @@ -1266,9 +1225,7 @@ class CountOperation: public Expression { CountOperation(bool is_prefix, IncrementOperation* increment, int pos) : is_prefix_(is_prefix), increment_(increment), pos_(pos) { } - virtual void Accept(AstVisitor* v); - - virtual CountOperation* AsCountOperation() { return this; } + DECLARE_NODE_TYPE(CountOperation) bool is_prefix() const { return is_prefix_; } bool is_postfix() const { return !is_prefix_; } @@ -1301,16 +1258,13 @@ class CompareOperation: public Expression { ASSERT(Token::IsCompareOp(op)); } - virtual void Accept(AstVisitor* v); + DECLARE_NODE_TYPE(CompareOperation) Token::Value op() const { return op_; } Expression* left() const { return left_; } Expression* right() const { return right_; } int position() const { return pos_; } - // Type testing & conversion - virtual CompareOperation* AsCompareOperation() { return this; } - private: Token::Value op_; Expression* left_; @@ -1324,7 +1278,7 @@ class CompareToNull: public Expression { CompareToNull(bool is_strict, Expression* expression) : is_strict_(is_strict), expression_(expression) { } - virtual void Accept(AstVisitor* v); + DECLARE_NODE_TYPE(CompareToNull) bool is_strict() const { return is_strict_; } Token::Value op() const { return is_strict_ ? Token::EQ_STRICT : Token::EQ; } @@ -1349,7 +1303,7 @@ class Conditional: public Expression { then_expression_position_(then_expression_position), else_expression_position_(else_expression_position) { } - virtual void Accept(AstVisitor* v); + DECLARE_NODE_TYPE(Conditional) Expression* condition() const { return condition_; } Expression* then_expression() const { return then_expression_; } @@ -1375,8 +1329,7 @@ class Assignment: public Expression { ASSERT(Token::IsAssignmentOp(op)); } - virtual void Accept(AstVisitor* v); - virtual Assignment* AsAssignment() { return this; } + DECLARE_NODE_TYPE(Assignment) Assignment* AsSimpleAssignment() { return !is_compound() ? this : NULL; } @@ -1413,7 +1366,7 @@ class Throw: public Expression { Throw(Expression* exception, int pos) : exception_(exception), pos_(pos) {} - virtual void Accept(AstVisitor* v); + DECLARE_NODE_TYPE(Throw) Expression* exception() const { return exception_; } int position() const { return pos_; } @@ -1459,14 +1412,11 @@ class FunctionLiteral: public Expression { #endif } - virtual void Accept(AstVisitor* v); - - // Type testing & conversion - virtual FunctionLiteral* AsFunctionLiteral() { return this; } + DECLARE_NODE_TYPE(FunctionLiteral) - Handle name() const { return name_; } - Scope* scope() const { return scope_; } - ZoneList* body() const { return body_; } + Handle name() const { return name_; } + Scope* scope() const { return scope_; } + ZoneList* body() const { return body_; } void set_function_token_position(int pos) { function_token_position_ = pos; } int function_token_position() const { return function_token_position_; } int start_position() const { return start_position_; } @@ -1486,7 +1436,7 @@ class FunctionLiteral: public Expression { bool AllowsLazyCompilation(); - Handle inferred_name() const { return inferred_name_; } + Handle inferred_name() const { return inferred_name_; } void set_inferred_name(Handle inferred_name) { inferred_name_ = inferred_name; } @@ -1529,12 +1479,12 @@ class SharedFunctionInfoLiteral: public Expression { Handle shared_function_info) : shared_function_info_(shared_function_info) { } + DECLARE_NODE_TYPE(SharedFunctionInfoLiteral) + Handle shared_function_info() const { return shared_function_info_; } - virtual void Accept(AstVisitor* v); - private: Handle shared_function_info_; }; @@ -1542,7 +1492,7 @@ class SharedFunctionInfoLiteral: public Expression { class ThisFunction: public Expression { public: - virtual void Accept(AstVisitor* v); + DECLARE_NODE_TYPE(ThisFunction) }; diff --git a/deps/v8/src/bootstrapper.cc b/deps/v8/src/bootstrapper.cc index 6e6c2c639c..aa8d8e5ac2 100644 --- a/deps/v8/src/bootstrapper.cc +++ b/deps/v8/src/bootstrapper.cc @@ -1064,8 +1064,11 @@ bool Genesis::InstallNatives() { // global object. static const PropertyAttributes attributes = static_cast(READ_ONLY | DONT_DELETE); - SetProperty(builtins, Factory::LookupAsciiSymbol("global"), - Handle(global_context()->global()), attributes); + Handle global_symbol = Factory::LookupAsciiSymbol("global"); + SetProperty(builtins, + global_symbol, + Handle(global_context()->global()), + attributes); // Setup the reference from the global object to the builtins object. JSGlobalObject::cast(global_context()->global())->set_builtins(*builtins); @@ -1344,33 +1347,41 @@ bool Genesis::InstallNatives() { } -static void InstallCustomCallGenerator( - Handle holder_function, - CallStubCompiler::CustomGeneratorOwner owner_flag, - const char* function_name, - int id) { - Handle owner; - if (owner_flag == CallStubCompiler::FUNCTION) { - owner = Handle::cast(holder_function); - } else { - ASSERT(owner_flag == CallStubCompiler::INSTANCE_PROTOTYPE); - owner = Handle( - JSObject::cast(holder_function->instance_prototype())); +static Handle ResolveCustomCallGeneratorHolder( + Handle global_context, + const char* holder_expr) { + Handle global(global_context->global()); + const char* period_pos = strchr(holder_expr, '.'); + if (period_pos == NULL) { + return Handle::cast( + GetProperty(global, Factory::LookupAsciiSymbol(holder_expr))); } + ASSERT_EQ(".prototype", period_pos); + Vector property(holder_expr, + static_cast(period_pos - holder_expr)); + Handle function = Handle::cast( + GetProperty(global, Factory::LookupSymbol(property))); + return Handle(JSObject::cast(function->prototype())); +} + + +static void InstallCustomCallGenerator(Handle holder, + const char* function_name, + int id) { Handle name = Factory::LookupAsciiSymbol(function_name); - Handle function(JSFunction::cast(owner->GetProperty(*name))); + Handle function(JSFunction::cast(holder->GetProperty(*name))); function->shared()->set_function_data(Smi::FromInt(id)); } void Genesis::InstallCustomCallGenerators() { HandleScope scope; -#define INSTALL_CALL_GENERATOR(holder_fun, owner_flag, fun_name, name) \ - { \ - Handle holder(global_context()->holder_fun##_function()); \ - const int id = CallStubCompiler::k##name##CallGenerator; \ - InstallCustomCallGenerator(holder, CallStubCompiler::owner_flag, \ - #fun_name, id); \ +#define INSTALL_CALL_GENERATOR(holder_expr, fun_name, name) \ + { \ + Handle holder = ResolveCustomCallGeneratorHolder( \ + global_context(), #holder_expr); \ + const int id = CallStubCompiler::k##name##CallGenerator; \ + InstallCustomCallGenerator(holder, #fun_name, id); \ } CUSTOM_CALL_IC_GENERATORS(INSTALL_CALL_GENERATOR) #undef INSTALL_CALL_GENERATOR @@ -1405,8 +1416,14 @@ void Genesis::InstallJSFunctionResultCaches() { Handle caches = Factory::NewFixedArray(kNumberOfCaches, TENURED); int index = 0; -#define F(size, func) caches->set(index++, CreateCache(size, func)); - JSFUNCTION_RESULT_CACHE_LIST(F) + +#define F(size, func) do { \ + FixedArray* cache = CreateCache((size), (func)); \ + caches->set(index++, cache); \ + } while (false) + + JSFUNCTION_RESULT_CACHE_LIST(F); + #undef F global_context()->set_jsfunction_result_caches(*caches); diff --git a/deps/v8/src/builtins.h b/deps/v8/src/builtins.h index 7e49f3133a..b5e8c4e8f6 100644 --- a/deps/v8/src/builtins.h +++ b/deps/v8/src/builtins.h @@ -65,6 +65,7 @@ enum BuiltinExtraArguments { #define BUILTIN_LIST_A(V) \ V(ArgumentsAdaptorTrampoline, BUILTIN, UNINITIALIZED) \ V(JSConstructCall, BUILTIN, UNINITIALIZED) \ + V(JSConstructStubCountdown, BUILTIN, UNINITIALIZED) \ V(JSConstructStubGeneric, BUILTIN, UNINITIALIZED) \ V(JSConstructStubApi, BUILTIN, UNINITIALIZED) \ V(JSEntryTrampoline, BUILTIN, UNINITIALIZED) \ @@ -249,6 +250,7 @@ class Builtins : public AllStatic { CFunctionId id, BuiltinExtraArguments extra_args); static void Generate_JSConstructCall(MacroAssembler* masm); + static void Generate_JSConstructStubCountdown(MacroAssembler* masm); static void Generate_JSConstructStubGeneric(MacroAssembler* masm); static void Generate_JSConstructStubApi(MacroAssembler* masm); static void Generate_JSEntryTrampoline(MacroAssembler* masm); diff --git a/deps/v8/src/codegen.cc b/deps/v8/src/codegen.cc index daf1c0db61..92241d1c51 100644 --- a/deps/v8/src/codegen.cc +++ b/deps/v8/src/codegen.cc @@ -289,7 +289,7 @@ void CodeGenerator::ProcessDeclarations(ZoneList* declarations) { for (int i = 0; i < length; i++) { Declaration* node = declarations->at(i); Variable* var = node->proxy()->var(); - Slot* slot = var->slot(); + Slot* slot = var->AsSlot(); // If it was not possible to allocate the variable at compile // time, we need to "declare" it at runtime to make sure it @@ -310,7 +310,7 @@ void CodeGenerator::ProcessDeclarations(ZoneList* declarations) { for (int j = 0, i = 0; i < length; i++) { Declaration* node = declarations->at(i); Variable* var = node->proxy()->var(); - Slot* slot = var->slot(); + Slot* slot = var->AsSlot(); if ((slot != NULL && slot->type() == Slot::LOOKUP) || !var->is_global()) { // Skip - already processed. diff --git a/deps/v8/src/compilation-cache.cc b/deps/v8/src/compilation-cache.cc index 7402e6857d..b0449c47f4 100644 --- a/deps/v8/src/compilation-cache.cc +++ b/deps/v8/src/compilation-cache.cc @@ -110,6 +110,9 @@ class CompilationCacheScript : public CompilationSubCache { void Put(Handle source, Handle function_info); private: + MUST_USE_RESULT Object* TryTablePut( + Handle source, Handle function_info); + // Note: Returns a new hash table if operation results in expansion. Handle TablePut( Handle source, Handle function_info); @@ -137,6 +140,12 @@ class CompilationCacheEval: public CompilationSubCache { Handle function_info); private: + MUST_USE_RESULT Object* TryTablePut( + Handle source, + Handle context, + Handle function_info); + + // Note: Returns a new hash table if operation results in expansion. Handle TablePut( Handle source, @@ -159,6 +168,10 @@ class CompilationCacheRegExp: public CompilationSubCache { JSRegExp::Flags flags, Handle data); private: + MUST_USE_RESULT Object* TryTablePut(Handle source, + JSRegExp::Flags flags, + Handle data); + // Note: Returns a new hash table if operation results in expansion. Handle TablePut(Handle source, JSRegExp::Flags flags, @@ -320,11 +333,18 @@ Handle CompilationCacheScript::Lookup(Handle source, } +Object* CompilationCacheScript::TryTablePut( + Handle source, + Handle function_info) { + Handle table = GetFirstTable(); + return table->Put(*source, *function_info); +} + + Handle CompilationCacheScript::TablePut( Handle source, Handle function_info) { - CALL_HEAP_FUNCTION(GetFirstTable()->Put(*source, *function_info), - CompilationCacheTable); + CALL_HEAP_FUNCTION(TryTablePut(source, function_info), CompilationCacheTable); } @@ -366,13 +386,20 @@ Handle CompilationCacheEval::Lookup( } +Object* CompilationCacheEval::TryTablePut( + Handle source, + Handle context, + Handle function_info) { + Handle table = GetFirstTable(); + return table->PutEval(*source, *context, *function_info); +} + + Handle CompilationCacheEval::TablePut( Handle source, Handle context, Handle function_info) { - CALL_HEAP_FUNCTION(GetFirstTable()->PutEval(*source, - *context, - *function_info), + CALL_HEAP_FUNCTION(TryTablePut(source, context, function_info), CompilationCacheTable); } @@ -415,12 +442,20 @@ Handle CompilationCacheRegExp::Lookup(Handle source, } +Object* CompilationCacheRegExp::TryTablePut( + Handle source, + JSRegExp::Flags flags, + Handle data) { + Handle table = GetFirstTable(); + return table->PutRegExp(*source, flags, *data); +} + + Handle CompilationCacheRegExp::TablePut( Handle source, JSRegExp::Flags flags, Handle data) { - CALL_HEAP_FUNCTION(GetFirstTable()->PutRegExp(*source, flags, *data), - CompilationCacheTable); + CALL_HEAP_FUNCTION(TryTablePut(source, flags, data), CompilationCacheTable); } diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc index f65f941567..6ef5a1c50d 100755 --- a/deps/v8/src/compiler.cc +++ b/deps/v8/src/compiler.cc @@ -120,8 +120,9 @@ Handle MakeCodeForLiveEdit(CompilationInfo* info) { Handle context = Handle::null(); Handle code = MakeCode(context, info); if (!info->shared_info().is_null()) { - info->shared_info()->set_scope_info( - *SerializedScopeInfo::Create(info->scope())); + Handle scope_info = + SerializedScopeInfo::Create(info->scope()); + info->shared_info()->set_scope_info(*scope_info); } return code; } @@ -145,9 +146,10 @@ static Handle MakeFunctionInfo(bool is_global, bool is_json = (validate == Compiler::VALIDATE_JSON); #ifdef ENABLE_DEBUGGER_SUPPORT if (is_eval || is_json) { - script->set_compilation_type( - is_json ? Smi::FromInt(Script::COMPILATION_TYPE_JSON) : - Smi::FromInt(Script::COMPILATION_TYPE_EVAL)); + Script::CompilationType compilation_type = is_json + ? Script::COMPILATION_TYPE_JSON + : Script::COMPILATION_TYPE_EVAL; + script->set_compilation_type(Smi::FromInt(compilation_type)); // For eval scripts add information on the function from which eval was // called. if (is_eval) { @@ -170,16 +172,16 @@ static Handle MakeFunctionInfo(bool is_global, ASSERT(is_eval || is_global); // Build AST. + EagerCompilationInfo info(script, is_eval); FunctionLiteral* lit = MakeAST(is_global, script, extension, pre_data, is_json); - LiveEditFunctionTracker live_edit_tracker(lit); - // Check for parse errors. if (lit == NULL) { ASSERT(Top::has_pending_exception()); return Handle::null(); } + info.set_function(lit); // Measure how long it takes to do the compilation; only take the // rest of the function into account to avoid overlap with the @@ -190,7 +192,7 @@ static Handle MakeFunctionInfo(bool is_global, HistogramTimerScope timer(rate); // Compile the code. - CompilationInfo info(lit, script, is_eval); + LiveEditFunctionTracker live_edit_tracker(lit); Handle code = MakeCode(context, &info); // Check for stack-overflow exceptions. @@ -375,20 +377,12 @@ bool Compiler::CompileLazy(CompilationInfo* info) { // Compute name, source code and script data. Handle shared = info->shared_info(); - Handle name(String::cast(shared->name())); - - int start_position = shared->start_position(); - int end_position = shared->end_position(); - bool is_expression = shared->is_expression(); - Counters::total_compile_size.Increment(end_position - start_position); + int compiled_size = shared->end_position() - shared->start_position(); + Counters::total_compile_size.Increment(compiled_size); // Generate the AST for the lazily compiled function. The AST may be // NULL in case of parser stack overflow. - FunctionLiteral* lit = MakeLazyAST(info->script(), - name, - start_position, - end_position, - is_expression); + FunctionLiteral* lit = MakeLazyAST(shared); // Check for parse errors. if (lit == NULL) { @@ -412,18 +406,20 @@ bool Compiler::CompileLazy(CompilationInfo* info) { } RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, - name, + Handle(String::cast(shared->name())), Handle(shared->inferred_name()), - start_position, + shared->start_position(), info->script(), code); // Update the shared function info with the compiled code and the scope info. // Please note, that the order of the sharedfunction initialization is - // important since set_scope_info might trigger a GC, causing the ASSERT - // below to be invalid if the code was flushed. By settting the code + // important since SerializedScopeInfo::Create might trigger a GC, causing + // the ASSERT below to be invalid if the code was flushed. By setting the code // object last we avoid this. - shared->set_scope_info(*SerializedScopeInfo::Create(info->scope())); + Handle scope_info = + SerializedScopeInfo::Create(info->scope()); + shared->set_scope_info(*scope_info); shared->set_code(*code); if (!info->closure().is_null()) { info->closure()->set_code(*code); @@ -479,7 +475,8 @@ Handle Compiler::BuildFunctionInfo(FunctionLiteral* literal, // Generate code and return it. The way that the compilation mode // is controlled by the command-line flags is described in // the static helper function MakeCode. - CompilationInfo info(literal, script, false); + EagerCompilationInfo info(script, false); + info.set_function(literal); bool is_run_once = literal->try_full_codegen(); bool use_full = FLAG_full_compiler && !literal->contains_loops(); diff --git a/deps/v8/src/compiler.h b/deps/v8/src/compiler.h index ed26603f42..ae0d6def6d 100644 --- a/deps/v8/src/compiler.h +++ b/deps/v8/src/compiler.h @@ -41,118 +41,109 @@ namespace internal { // is constructed based on the resources available at compile-time. class CompilationInfo BASE_EMBEDDED { public: - // Lazy compilation of a JSFunction. - CompilationInfo(Handle closure, - int loop_nesting, - Handle receiver) - : closure_(closure), - function_(NULL), - is_eval_(false), - loop_nesting_(loop_nesting), - receiver_(receiver) { - Initialize(); - ASSERT(!closure_.is_null() && - shared_info_.is_null() && - script_.is_null()); - } + virtual ~CompilationInfo() {} + + // Dispatched behavior. + virtual Handle shared_info() const = 0; - // Lazy compilation based on SharedFunctionInfo. - explicit CompilationInfo(Handle shared_info) - : shared_info_(shared_info), - function_(NULL), - is_eval_(false), - loop_nesting_(0) { - Initialize(); - ASSERT(closure_.is_null() && - !shared_info_.is_null() && - script_.is_null()); + virtual Handle