Browse Source

Upgrade to v8 1.2.7

v0.7.4-release
Ryan 16 years ago
parent
commit
696f024557
  1. 15
      deps/v8/AUTHORS
  2. 89
      deps/v8/ChangeLog
  3. 6
      deps/v8/SConstruct
  4. 18
      deps/v8/benchmarks/README.txt
  5. 51
      deps/v8/benchmarks/base.js
  6. 8
      deps/v8/benchmarks/deltablue.js
  7. 1
      deps/v8/benchmarks/earley-boyer.js
  8. 2521
      deps/v8/benchmarks/raytrace.js
  9. 23
      deps/v8/benchmarks/revisions.html
  10. 2
      deps/v8/benchmarks/richards.js
  11. 12
      deps/v8/benchmarks/run.html
  12. 1
      deps/v8/benchmarks/run.js
  13. 378
      deps/v8/benchmarks/splay.js
  14. 3
      deps/v8/include/v8-debug.h
  15. 29
      deps/v8/include/v8.h
  16. 16
      deps/v8/src/SConscript
  17. 74
      deps/v8/src/accessors.cc
  18. 41
      deps/v8/src/accessors.h
  19. 3
      deps/v8/src/allocation.cc
  20. 3
      deps/v8/src/allocation.h
  21. 84
      deps/v8/src/api.cc
  22. 3
      deps/v8/src/arguments.h
  23. 3
      deps/v8/src/arm/assembler-arm-inl.h
  24. 7
      deps/v8/src/arm/assembler-arm.cc
  25. 9
      deps/v8/src/arm/assembler-arm.h
  26. 5
      deps/v8/src/arm/builtins-arm.cc
  27. 46
      deps/v8/src/arm/codegen-arm-inl.h
  28. 586
      deps/v8/src/arm/codegen-arm.cc
  29. 11
      deps/v8/src/arm/codegen-arm.h
  30. 3
      deps/v8/src/arm/constants-arm.h
  31. 3
      deps/v8/src/arm/cpu-arm.cc
  32. 3
      deps/v8/src/arm/debug-arm.cc
  33. 3
      deps/v8/src/arm/disasm-arm.cc
  34. 3
      deps/v8/src/arm/frames-arm.cc
  35. 3
      deps/v8/src/arm/frames-arm.h
  36. 13
      deps/v8/src/arm/ic-arm.cc
  37. 147
      deps/v8/src/arm/jump-target-arm.cc
  38. 28
      deps/v8/src/arm/macro-assembler-arm.cc
  39. 3
      deps/v8/src/arm/macro-assembler-arm.h
  40. 3
      deps/v8/src/arm/regexp-macro-assembler-arm.cc
  41. 3
      deps/v8/src/arm/regexp-macro-assembler-arm.h
  42. 103
      deps/v8/src/arm/register-allocator-arm-inl.h
  43. 55
      deps/v8/src/arm/register-allocator-arm.cc
  44. 43
      deps/v8/src/arm/register-allocator-arm.h
  45. 3
      deps/v8/src/arm/simulator-arm.cc
  46. 3
      deps/v8/src/arm/simulator-arm.h
  47. 44
      deps/v8/src/arm/stub-cache-arm.cc
  48. 77
      deps/v8/src/arm/virtual-frame-arm.cc
  49. 198
      deps/v8/src/arm/virtual-frame-arm.h
  50. 33
      deps/v8/src/assembler.cc
  51. 11
      deps/v8/src/assembler.h
  52. 3
      deps/v8/src/ast.cc
  53. 3
      deps/v8/src/ast.h
  54. 80
      deps/v8/src/bootstrapper.cc
  55. 3
      deps/v8/src/bootstrapper.h
  56. 46
      deps/v8/src/builtins.cc
  57. 65
      deps/v8/src/builtins.h
  58. 3
      deps/v8/src/bytecodes-irregexp.h
  59. 3
      deps/v8/src/char-predicates-inl.h
  60. 3
      deps/v8/src/char-predicates.h
  61. 5
      deps/v8/src/code-stubs.cc
  62. 7
      deps/v8/src/code-stubs.h
  63. 3
      deps/v8/src/code.h
  64. 27
      deps/v8/src/codegen-inl.h
  65. 98
      deps/v8/src/codegen.cc
  66. 89
      deps/v8/src/codegen.h
  67. 159
      deps/v8/src/compilation-cache.cc
  68. 18
      deps/v8/src/compilation-cache.h
  69. 49
      deps/v8/src/compiler.cc
  70. 22
      deps/v8/src/compiler.h
  71. 3
      deps/v8/src/contexts.cc
  72. 6
      deps/v8/src/contexts.h
  73. 3
      deps/v8/src/conversions-inl.h
  74. 3
      deps/v8/src/conversions.cc
  75. 3
      deps/v8/src/conversions.h
  76. 3
      deps/v8/src/counters.cc
  77. 5
      deps/v8/src/counters.h
  78. 3
      deps/v8/src/cpu.h
  79. 5
      deps/v8/src/d8-posix.cc
  80. 12
      deps/v8/src/d8.cc
  81. 56
      deps/v8/src/d8.js
  82. 3
      deps/v8/src/dateparser-inl.h
  83. 3
      deps/v8/src/dateparser.cc
  84. 3
      deps/v8/src/dateparser.h
  85. 3
      deps/v8/src/debug-agent.cc
  86. 3
      deps/v8/src/debug-agent.h
  87. 267
      deps/v8/src/debug-delay.js
  88. 319
      deps/v8/src/debug.cc
  89. 136
      deps/v8/src/debug.h
  90. 12
      deps/v8/src/disassembler.cc
  91. 3
      deps/v8/src/disassembler.h
  92. 44
      deps/v8/src/execution.cc
  93. 7
      deps/v8/src/execution.h
  94. 14
      deps/v8/src/factory.cc
  95. 10
      deps/v8/src/factory.h
  96. 6
      deps/v8/src/flag-definitions.h
  97. 7
      deps/v8/src/flags.cc
  98. 3
      deps/v8/src/flags.h
  99. 265
      deps/v8/src/frame-element.h
  100. 3
      deps/v8/src/frames-inl.h

15
deps/v8/AUTHORS

@ -5,11 +5,14 @@
Google Inc. Google Inc.
Rene Rebe <rene@exactcode.de>
Rafal Krypa <rafal@krypa.net>
Jay Freeman <saurik@saurik.com>
Daniel James <dnljms@gmail.com>
Paolo Giarrusso <p.giarrusso@gmail.com>
Daniel Andersson <kodandersson@gmail.com>
Alexander Botero-Lowry <alexbl@FreeBSD.org> Alexander Botero-Lowry <alexbl@FreeBSD.org>
Craig Schlenter <craig.schlenter@gmail.com>
Daniel Andersson <kodandersson@gmail.com>
Daniel James <dnljms@gmail.com>
Jay Freeman <saurik@saurik.com>
Joel Stanley <joel.stan@gmail.com>
Matt Hanselman <mjhanselman@gmail.com> Matt Hanselman <mjhanselman@gmail.com>
Paolo Giarrusso <p.giarrusso@gmail.com>
Rafal Krypa <rafal@krypa.net>
Rene Rebe <rene@exactcode.de>
Ryan Dahl <coldredlemur@gmail.com>

89
deps/v8/ChangeLog

@ -1,3 +1,92 @@
2009-06-08: Version 1.2.7
Improved debugger and profiler support.
Reduced compilation time by improving the handling of deferred
code.
Optimized interceptor accesses where the property is on the object
on which the interceptors is attached.
Fixed compilation problem on GCC 4.4 by changing the stack
alignment to 16 bytes.
Fixed handle creation to follow stric aliasing rules.
Fixed compilation on FreeBSD.
Introduced API for forcing the deletion of a property ignoring
interceptors and attributes.
2009-05-29: Version 1.2.6
Added a histogram recording hit rates at different levels of the
compilation cache.
Added stack overflow check for the RegExp analysis phase. Previously a
very long regexp graph could overflow the stack with recursive calls.
Use a dynamic buffer when collecting log events in memory.
Added start/stop events to the profiler log.
Fixed infinite loop which could happen when setting a debug break while
executing a RegExp compiled to native code.
Fixed handling of lastIndexOf called with negative index (issue 351).
Fixed irregular crash in profiler test (issue 358).
Fixed compilation issues with some versions of gcc.
2009-05-26: Version 1.2.5
Fixed bug in initial boundary check for Boyer-Moore text
search (issue 349).
Fixed compilation issues with MinGW and gcc 4.3+ and added support
for armv7 and cortex-a8 architectures. Patches by Lei Zhang and
Craig Schlenter.
Added a script cache to the debugger.
Optimized compilation performance by improving internal data
structures and avoiding expensive property load optimizations for
code that's infrequently executed.
Exposed the calling JavaScript context through the static API
function Context::GetCalling().
2009-05-18: Version 1.2.4
Improved performance of floating point number allocation for ARM
platforms.
Fixed crash when using the instanceof operator on functions with
number values in their prototype chain (issue 341).
Optimized virtual frame operations in the code generator to speed
up compilation time and allocated the frames in the zone.
Made the representation of virtual frames and jump targets in the
code generator much more compact.
Avoided linear search for non-locals in scope code when resolving
variables inside with and eval scopes.
Optimized lexical scanner by dealing with whitespace as part of
the token scanning instead of as a separate step before it.
Changed the scavenging collector so that promoted objects do not
reside in the old generation while their remembered set is being
swept for pointers into the young generation.
Fixed numeric overflow handling when compiling count operations.
2009-05-11: Version 1.2.3 2009-05-11: Version 1.2.3
Fixed bug in reporting of out-of-memory situations. Fixed bug in reporting of out-of-memory situations.

6
deps/v8/SConstruct

@ -44,10 +44,10 @@ if ANDROID_TOP is None:
ANDROID_TOP="" ANDROID_TOP=""
# TODO: Sort these issues out properly but as a temporary solution for gcc 4.4 # TODO: Sort these issues out properly but as a temporary solution for gcc 4.4
# on linux we need these compiler flags to avoid a mksnapshot segfault, avoid # on linux we need these compiler flags to avoid crashes in the v8 test suite
# crashes in the v8 test suite and avoid dtoa.c strict aliasing issues # and avoid dtoa.c strict aliasing issues
if os.environ.get('GCC_VERSION') == '44': if os.environ.get('GCC_VERSION') == '44':
GCC_EXTRA_CCFLAGS = ['-fno-tree-vectorize', '-fno-tree-vrp'] GCC_EXTRA_CCFLAGS = ['-fno-tree-vrp']
GCC_DTOA_EXTRA_CCFLAGS = ['-fno-strict-aliasing'] GCC_DTOA_EXTRA_CCFLAGS = ['-fno-strict-aliasing']
else: else:
GCC_EXTRA_CCFLAGS = [] GCC_EXTRA_CCFLAGS = []

18
deps/v8/benchmarks/README.txt

@ -40,3 +40,21 @@ pages where it occurs and the number of times it is executed while
loading each page. Finally the literal letters in the data are loading each page. Finally the literal letters in the data are
encoded using ROT13 in a way that does not affect how the regexps encoded using ROT13 in a way that does not affect how the regexps
match their input. match their input.
Changes from Version 3 to Version 4
===================================
The Splay benchmark is a newcomer in version 4. It manipulates a
splay tree by adding and removing data nodes, thus exercising the
memory management subsystem of the JavaScript engine.
Furthermore, all the unused parts of the Prototype library were
removed from the RayTrace benchmark. This does not affect the running
of the benchmark.
Changes from Version 4 to Version 5
===================================
Removed duplicate line in random seed code.

51
deps/v8/benchmarks/base.js

@ -31,10 +31,15 @@
// A benchmark has a name (string) and a function that will be run to // A benchmark has a name (string) and a function that will be run to
// do the performance measurement. // do the performance measurement. The optional setup and tearDown
function Benchmark(name, run) { // arguments are functions that will be invoked before and after
// running the benchmark, but the running time of these functions will
// not be accounted for in the benchmark score.
function Benchmark(name, run, setup, tearDown) {
this.name = name; this.name = name;
this.run = run; this.run = run;
this.Setup = setup ? setup : function() { };
this.TearDown = tearDown ? tearDown : function() { };
} }
@ -73,7 +78,7 @@ BenchmarkSuite.suites = [];
// Scores are not comparable across versions. Bump the version if // Scores are not comparable across versions. Bump the version if
// you're making changes that will affect that scores, e.g. if you add // you're making changes that will affect that scores, e.g. if you add
// a new benchmark or change an existing one. // a new benchmark or change an existing one.
BenchmarkSuite.version = '3'; BenchmarkSuite.version = '5';
// To make the benchmark results predictable, we replace Math.random // To make the benchmark results predictable, we replace Math.random
@ -86,7 +91,6 @@ Math.random = (function() {
seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff; seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff;
seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff; seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff;
seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff; seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff;
seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff;
seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff; seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff;
seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff; seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff;
return (seed & 0xfffffff) / 0x10000000; return (seed & 0xfffffff) / 0x10000000;
@ -114,7 +118,7 @@ BenchmarkSuite.RunSuites = function(runner) {
continuation = suite.RunStep(runner); continuation = suite.RunStep(runner);
} }
if (continuation && typeof window != 'undefined' && window.setTimeout) { if (continuation && typeof window != 'undefined' && window.setTimeout) {
window.setTimeout(RunStep, 100); window.setTimeout(RunStep, 25);
return; return;
} }
} }
@ -194,7 +198,7 @@ BenchmarkSuite.prototype.NotifyError = function(error) {
// Runs a single benchmark for at least a second and computes the // Runs a single benchmark for at least a second and computes the
// average time it takes to run a single iteration. // average time it takes to run a single iteration.
BenchmarkSuite.prototype.RunSingle = function(benchmark) { BenchmarkSuite.prototype.RunSingleBenchmark = function(benchmark) {
var elapsed = 0; var elapsed = 0;
var start = new Date(); var start = new Date();
for (var n = 0; elapsed < 1000; n++) { for (var n = 0; elapsed < 1000; n++) {
@ -216,18 +220,45 @@ BenchmarkSuite.prototype.RunStep = function(runner) {
var length = this.benchmarks.length; var length = this.benchmarks.length;
var index = 0; var index = 0;
var suite = this; var suite = this;
function RunNext() {
// Run the setup, the actual benchmark, and the tear down in three
// separate steps to allow the framework to yield between any of the
// steps.
function RunNextSetup() {
if (index < length) { if (index < length) {
try { try {
suite.RunSingle(suite.benchmarks[index++]); suite.benchmarks[index].Setup();
} catch (e) { } catch (e) {
suite.NotifyError(e); suite.NotifyError(e);
return null; return null;
} }
return RunNext; return RunNextBenchmark;
} }
suite.NotifyResult(); suite.NotifyResult();
return null; return null;
} }
return RunNext();
function RunNextBenchmark() {
try {
suite.RunSingleBenchmark(suite.benchmarks[index]);
} catch (e) {
suite.NotifyError(e);
return null;
}
return RunNextTearDown;
}
function RunNextTearDown() {
try {
suite.benchmarks[index++].TearDown();
} catch (e) {
suite.NotifyError(e);
return null;
}
return RunNextSetup;
}
// Start out running the setup.
return RunNextSetup();
} }

8
deps/v8/benchmarks/deltablue.js

@ -16,10 +16,10 @@
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// This implementation of the DeltaBlue benchmark is derived // This implementation of the DeltaBlue benchmark is derived
// from the Smalltalk implementation by John Maloney and Mario // from the Smalltalk implementation by John Maloney and Mario
// Wolczko. Some parts have been translated directly, whereas // Wolczko. Some parts have been translated directly, whereas
// others have been modified more aggresively to make it feel // others have been modified more aggresively to make it feel
// more like a JavaScript program. // more like a JavaScript program.

1
deps/v8/benchmarks/earley-boyer.js

@ -4682,4 +4682,3 @@ function RunBenchmark(name, count, run, warn) {
} }
var BgL_runzd2benchmarkzd2 = RunBenchmark; var BgL_runzd2benchmarkzd2 = RunBenchmark;

2521
deps/v8/benchmarks/raytrace.js

File diff suppressed because it is too large

23
deps/v8/benchmarks/revisions.html

@ -20,6 +20,25 @@ the benchmark suite.
</p> </p>
<div class="subtitle"><h3>Version 5 (<a href="http://v8.googlecode.com/svn/data/benchmarks/v5/run.html">link</a>)</h3></div>
<p>Removed a duplicate line in the base random seed code.
</p>
<div class="subtitle"><h3>Version 4 (<a href="http://v8.googlecode.com/svn/data/benchmarks/v4/run.html">link</a>)</h3></div>
<p>The <i>Splay</i> benchmark is a newcomer in version 4. It
manipulates a splay tree by adding and removing data nodes, thus
exercising the memory management subsystem of the JavaScript engine.
</p>
<p>
Furthermore, all the unused parts of the Prototype library were
removed from the RayTrace benchmark. This does not affect the running
of the benchmark.
</p>
<div class="subtitle"><h3>Version 3 (<a href="http://v8.googlecode.com/svn/data/benchmarks/v3/run.html">link</a>)</h3></div> <div class="subtitle"><h3>Version 3 (<a href="http://v8.googlecode.com/svn/data/benchmarks/v3/run.html">link</a>)</h3></div>
<p>Version 3 adds a new benchmark, <i>RegExp</i>. The RegExp <p>Version 3 adds a new benchmark, <i>RegExp</i>. The RegExp
@ -32,9 +51,10 @@ encoded using ROT13 in a way that does not affect how the regexps
match their input. match their input.
</p> </p>
<div class="subtitle"><h3>Version 2 (<a href="http://v8.googlecode.com/svn/data/benchmarks/v2/run.html">link</a>)</h3></div> <div class="subtitle"><h3>Version 2 (<a href="http://v8.googlecode.com/svn/data/benchmarks/v2/run.html">link</a>)</h3></div>
<p>For version 2 the crypto benchmark was fixed. Previously, the <p>For version 2 the Crypto benchmark was fixed. Previously, the
decryption stage was given plaintext as input, which resulted in an decryption stage was given plaintext as input, which resulted in an
error. Now, the decryption stage is given the output of the error. Now, the decryption stage is given the output of the
encryption stage as input. The result is checked against the original encryption stage as input. The result is checked against the original
@ -49,6 +69,7 @@ results of their calculations. This is to avoid accidentally
obtaining scores that are the result of an incorrect JavaScript engine obtaining scores that are the result of an incorrect JavaScript engine
optimization.</p> optimization.</p>
<div class="subtitle"><h3>Version 1 (<a href="http://v8.googlecode.com/svn/data/benchmarks/v1/run.html">link</a>)</h3></div> <div class="subtitle"><h3>Version 1 (<a href="http://v8.googlecode.com/svn/data/benchmarks/v1/run.html">link</a>)</h3></div>
<p>Initial release.</p> <p>Initial release.</p>

2
deps/v8/benchmarks/richards.js

@ -30,7 +30,7 @@
// benchmark from: // benchmark from:
// //
// http://www.cl.cam.ac.uk/~mr10/Bench.html // http://www.cl.cam.ac.uk/~mr10/Bench.html
// //
// The benchmark was originally implemented in BCPL by // The benchmark was originally implemented in BCPL by
// Martin Richards. // Martin Richards.

12
deps/v8/benchmarks/run.html

@ -8,6 +8,7 @@
<script type="text/javascript" src="raytrace.js"></script> <script type="text/javascript" src="raytrace.js"></script>
<script type="text/javascript" src="earley-boyer.js"></script> <script type="text/javascript" src="earley-boyer.js"></script>
<script type="text/javascript" src="regexp.js"></script> <script type="text/javascript" src="regexp.js"></script>
<script type="text/javascript" src="splay.js"></script>
<link type="text/css" rel="stylesheet" href="style.css"></link> <link type="text/css" rel="stylesheet" href="style.css"></link>
<script type="text/javascript"> <script type="text/javascript">
var completed = 0; var completed = 0;
@ -72,12 +73,13 @@ higher scores means better performance: <em>Bigger is better!</em>
<ul> <ul>
<li><b>Richards</b><br/>OS kernel simulation benchmark, originally written in BCPL by Martin Richards (<i>539 lines</i>).</li> <li><b>Richards</b><br/>OS kernel simulation benchmark, originally written in BCPL by Martin Richards (<i>539 lines</i>).</li>
<li><b>DeltaBlue</b><br/>One-way constraint solver, originally written in Smalltalk by John Maloney and Mario Wolczko (<i>880 lines</i>).</li> <li><b>DeltaBlue</b><br/>One-way constraint solver, originally written in Smalltalk by John Maloney and Mario Wolczko (<i>880 lines</i>).</li>
<li><b>Crypto</b><br/>Encryption and decryption benchmark based on code by Tom Wu (<i>1689 lines</i>).</li> <li><b>Crypto</b><br/>Encryption and decryption benchmark based on code by Tom Wu (<i>1698 lines</i>).</li>
<li><b>RayTrace</b><br/>Ray tracer benchmark based on code by <a href="http://flog.co.nz/">Adam Burmister</a> (<i>3418 lines</i>).</li> <li><b>RayTrace</b><br/>Ray tracer benchmark based on code by <a href="http://flog.co.nz/">Adam Burmister</a> (<i>935 lines</i>).</li>
<li><b>EarleyBoyer</b><br/>Classic Scheme benchmarks, translated to JavaScript by Florian Loitsch's Scheme2Js compiler (<i>4682 lines</i>).</li> <li><b>EarleyBoyer</b><br/>Classic Scheme benchmarks, translated to JavaScript by Florian Loitsch's Scheme2Js compiler (<i>4685 lines</i>).</li>
<li><b>RegExp</b><br/>Regular expression benchmark generated by extracting regular expression operations from 50 of the most popular web pages <li><b>RegExp</b><br/>Regular expression benchmark generated by extracting regular expression operations from 50 of the most popular web pages
(<i>4758 lines</i>). (<i>1614 lines</i>).
</li> </li>
<li><b>Splay</b><br/>Data manipulation benchmark that deals with splay trees and exercises the automatic memory management subsystem (<i>378 lines</i>).</li>
</ul> </ul>
<p> <p>
@ -90,7 +92,7 @@ the <a href="http://v8.googlecode.com/svn/data/benchmarks/current/revisions.html
</td><td style="text-align: center"> </td><td style="text-align: center">
<div class="run"> <div class="run">
<div id="status" style="text-align: center; margin-top: 60px; font-size: 120%; font-weight: bold;">Starting...</div> <div id="status" style="text-align: center; margin-top: 50px; font-size: 120%; font-weight: bold;">Starting...</div>
<div style="text-align: left; margin: 30px 0 0 90px;" id="results"> <div style="text-align: left; margin: 30px 0 0 90px;" id="results">
<div> <div>
</div> </div>

1
deps/v8/benchmarks/run.js

@ -33,6 +33,7 @@ load('crypto.js');
load('raytrace.js'); load('raytrace.js');
load('earley-boyer.js'); load('earley-boyer.js');
load('regexp.js'); load('regexp.js');
load('splay.js');
var success = true; var success = true;

378
deps/v8/benchmarks/splay.js

@ -0,0 +1,378 @@
// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// This benchmark is based on a JavaScript log processing module used
// by the V8 profiler to generate execution time profiles for runs of
// JavaScript applications, and it effectively measures how fast the
// JavaScript engine is at allocating nodes and reclaiming the memory
// used for old nodes. Because of the way splay trees work, the engine
// also has to deal with a lot of changes to the large tree object
// graph.
var Splay = new BenchmarkSuite('Splay', 126125, [
new Benchmark("Splay", SplayRun, SplaySetup, SplayTearDown)
]);
// Configuration.
var kSplayTreeSize = 8000;
var kSplayTreeModifications = 80;
var kSplayTreePayloadDepth = 5;
var splayTree = null;
function GeneratePayloadTree(depth, key) {
if (depth == 0) {
return {
array : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
string : 'String for key ' + key + ' in leaf node'
};
} else {
return {
left: GeneratePayloadTree(depth - 1, key),
right: GeneratePayloadTree(depth - 1, key)
};
}
}
function GenerateKey() {
// The benchmark framework guarantees that Math.random is
// deterministic; see base.js.
return Math.random();
}
function InsertNewNode() {
// Insert new node with a unique key.
var key;
do {
key = GenerateKey();
} while (splayTree.find(key) != null);
splayTree.insert(key, GeneratePayloadTree(kSplayTreePayloadDepth, key));
return key;
}
function SplaySetup() {
splayTree = new SplayTree();
for (var i = 0; i < kSplayTreeSize; i++) InsertNewNode();
}
function SplayTearDown() {
// Allow the garbage collector to reclaim the memory
// used by the splay tree no matter how we exit the
// tear down function.
var keys = splayTree.exportKeys();
splayTree = null;
// Verify that the splay tree has the right size.
var length = keys.length;
if (length != kSplayTreeSize) {
throw new Error("Splay tree has wrong size");
}
// Verify that the splay tree has sorted, unique keys.
for (var i = 0; i < length - 1; i++) {
if (keys[i] >= keys[i + 1]) {
throw new Error("Splay tree not sorted");
}
}
}
function SplayRun() {
// Replace a few nodes in the splay tree.
for (var i = 0; i < kSplayTreeModifications; i++) {
var key = InsertNewNode();
var greatest = splayTree.findGreatestLessThan(key);
if (greatest == null) splayTree.remove(key);
else splayTree.remove(greatest.key);
}
}
/**
* Constructs a Splay tree. A splay tree is a self-balancing binary
* search tree with the additional property that recently accessed
* elements are quick to access again. It performs basic operations
* such as insertion, look-up and removal in O(log(n)) amortized time.
*
* @constructor
*/
function SplayTree() {
};
/**
* Pointer to the root node of the tree.
*
* @type {SplayTree.Node}
* @private
*/
SplayTree.prototype.root_ = null;
/**
* @return {boolean} Whether the tree is empty.
*/
SplayTree.prototype.isEmpty = function() {
return !this.root_;
};
/**
* Inserts a node into the tree with the specified key and value if
* the tree does not already contain a node with the specified key. If
* the value is inserted, it becomes the root of the tree.
*
* @param {number} key Key to insert into the tree.
* @param {*} value Value to insert into the tree.
*/
SplayTree.prototype.insert = function(key, value) {
if (this.isEmpty()) {
this.root_ = new SplayTree.Node(key, value);
return;
}
// Splay on the key to move the last node on the search path for
// the key to the root of the tree.
this.splay_(key);
if (this.root_.key == key) {
return;
}
var node = new SplayTree.Node(key, value);
if (key > this.root_.key) {
node.left = this.root_;
node.right = this.root_.right;
this.root_.right = null;
} else {
node.right = this.root_;
node.left = this.root_.left;
this.root_.left = null;
}
this.root_ = node;
};
/**
* Removes a node with the specified key from the tree if the tree
* contains a node with this key. The removed node is returned. If the
* key is not found, an exception is thrown.
*
* @param {number} key Key to find and remove from the tree.
* @return {SplayTree.Node} The removed node.
*/
SplayTree.prototype.remove = function(key) {
if (this.isEmpty()) {
throw Error('Key not found: ' + key);
}
this.splay_(key);
if (this.root_.key != key) {
throw Error('Key not found: ' + key);
}
var removed = this.root_;
if (!this.root_.left) {
this.root_ = this.root_.right;
} else {
var right = this.root_.right;
this.root_ = this.root_.left;
// Splay to make sure that the new root has an empty right child.
this.splay_(key);
// Insert the original right child as the right child of the new
// root.
this.root_.right = right;
}
return removed;
};
/**
* Returns the node having the specified key or null if the tree doesn't contain
* a node with the specified key.
*
* @param {number} key Key to find in the tree.
* @return {SplayTree.Node} Node having the specified key.
*/
SplayTree.prototype.find = function(key) {
if (this.isEmpty()) {
return null;
}
this.splay_(key);
return this.root_.key == key ? this.root_ : null;
};
/**
* @return {SplayTree.Node} Node having the maximum key value that
* is less or equal to the specified key value.
*/
SplayTree.prototype.findGreatestLessThan = function(key) {
if (this.isEmpty()) {
return null;
}
// Splay on the key to move the node with the given key or the last
// node on the search path to the top of the tree.
this.splay_(key);
// Now the result is either the root node or the greatest node in
// the left subtree.
if (this.root_.key <= key) {
return this.root_;
} else if (this.root_.left) {
return this.findMax(this.root_.left);
} else {
return null;
}
};
/**
* @return {Array<*>} An array containing all the keys of tree's nodes.
*/
SplayTree.prototype.exportKeys = function() {
var result = [];
if (!this.isEmpty()) {
this.root_.traverse_(function(node) { result.push(node.key); });
}
return result;
};
/**
* Perform the splay operation for the given key. Moves the node with
* the given key to the top of the tree. If no node has the given
* key, the last node on the search path is moved to the top of the
* tree. This is the simplified top-down splaying algorithm from:
* "Self-adjusting Binary Search Trees" by Sleator and Tarjan
*
* @param {number} key Key to splay the tree on.
* @private
*/
SplayTree.prototype.splay_ = function(key) {
if (this.isEmpty()) {
return;
}
// Create a dummy node. The use of the dummy node is a bit
// counter-intuitive: The right child of the dummy node will hold
// the L tree of the algorithm. The left child of the dummy node
// will hold the R tree of the algorithm. Using a dummy node, left
// and right will always be nodes and we avoid special cases.
var dummy, left, right;
dummy = left = right = new SplayTree.Node(null, null);
var current = this.root_;
while (true) {
if (key < current.key) {
if (!current.left) {
break;
}
if (key < current.left.key) {
// Rotate right.
var tmp = current.left;
current.left = tmp.right;
tmp.right = current;
current = tmp;
if (!current.left) {
break;
}
}
// Link right.
right.left = current;
right = current;
current = current.left;
} else if (key > current.key) {
if (!current.right) {
break;
}
if (key > current.right.key) {
// Rotate left.
var tmp = current.right;
current.right = tmp.left;
tmp.left = current;
current = tmp;
if (!current.right) {
break;
}
}
// Link left.
left.right = current;
left = current;
current = current.right;
} else {
break;
}
}
// Assemble.
left.right = current.left;
right.left = current.right;
current.left = dummy.right;
current.right = dummy.left;
this.root_ = current;
};
/**
* Constructs a Splay tree node.
*
* @param {number} key Key.
* @param {*} value Value.
*/
SplayTree.Node = function(key, value) {
this.key = key;
this.value = value;
};
/**
* @type {SplayTree.Node}
*/
SplayTree.Node.prototype.left = null;
/**
* @type {SplayTree.Node}
*/
SplayTree.Node.prototype.right = null;
/**
* Performs an ordered traversal of the subtree starting at
* this SplayTree.Node.
*
* @param {function(SplayTree.Node)} f Visitor function.
* @private
*/
SplayTree.Node.prototype.traverse_ = function(f) {
var current = this;
while (current) {
var left = current.left;
if (left) left.traverse_(f);
f(current);
current = current.right;
}
};

3
deps/v8/include/v8-debug.h

@ -75,7 +75,8 @@ enum DebugEvent {
Exception = 2, Exception = 2,
NewFunction = 3, NewFunction = 3,
BeforeCompile = 4, BeforeCompile = 4,
AfterCompile = 5 AfterCompile = 5,
ScriptCollected = 6
}; };

29
deps/v8/include/v8.h

@ -41,6 +41,10 @@
#include <stdio.h> #include <stdio.h>
#ifdef _WIN32 #ifdef _WIN32
// When compiling on MinGW stdint.h is available.
#ifdef __MINGW32__
#include <stdint.h>
#else // __MINGW32__
typedef signed char int8_t; typedef signed char int8_t;
typedef unsigned char uint8_t; typedef unsigned char uint8_t;
typedef short int16_t; // NOLINT typedef short int16_t; // NOLINT
@ -49,7 +53,8 @@ typedef int int32_t;
typedef unsigned int uint32_t; typedef unsigned int uint32_t;
typedef __int64 int64_t; typedef __int64 int64_t;
typedef unsigned __int64 uint64_t; typedef unsigned __int64 uint64_t;
// intptr_t is defined in crtdefs.h through stdio.h. // intptr_t and friends are defined in crtdefs.h through stdio.h.
#endif // __MINGW32__
// Setup for Windows DLL export/import. When building the V8 DLL the // Setup for Windows DLL export/import. When building the V8 DLL the
// BUILDING_V8_SHARED needs to be defined. When building a program which uses // BUILDING_V8_SHARED needs to be defined. When building a program which uses
@ -1051,7 +1056,7 @@ class V8EXPORT Object : public Value {
Handle<Value> value, Handle<Value> value,
PropertyAttribute attribs = None); PropertyAttribute attribs = None);
// Sets a local property on this object, bypassing interceptors and // Sets a local property on this object bypassing interceptors and
// overriding accessors or read-only properties. // overriding accessors or read-only properties.
// //
// Note that if the object has an interceptor the property will be set // Note that if the object has an interceptor the property will be set
@ -1062,13 +1067,21 @@ class V8EXPORT Object : public Value {
bool ForceSet(Handle<Value> key, bool ForceSet(Handle<Value> key,
Handle<Value> value, Handle<Value> value,
PropertyAttribute attribs = None); PropertyAttribute attribs = None);
Local<Value> Get(Handle<Value> key); Local<Value> Get(Handle<Value> key);
// TODO(1245389): Replace the type-specific versions of these // TODO(1245389): Replace the type-specific versions of these
// functions with generic ones that accept a Handle<Value> key. // functions with generic ones that accept a Handle<Value> key.
bool Has(Handle<String> key); bool Has(Handle<String> key);
bool Delete(Handle<String> key); bool Delete(Handle<String> key);
// Delete a property on this object bypassing interceptors and
// ignoring dont-delete attributes.
bool ForceDelete(Handle<Value> key);
bool Has(uint32_t index); bool Has(uint32_t index);
bool Delete(uint32_t index); bool Delete(uint32_t index);
/** /**
@ -2079,6 +2092,11 @@ class V8EXPORT V8 {
*/ */
static void ResumeProfiler(); static void ResumeProfiler();
/**
* Return whether profiler is currently paused.
*/
static bool IsProfilerPaused();
/** /**
* If logging is performed into a memory buffer (via --logfile=*), allows to * If logging is performed into a memory buffer (via --logfile=*), allows to
* retrieve previously written messages. This can be used for retrieving * retrieve previously written messages. This can be used for retrieving
@ -2245,6 +2263,13 @@ class V8EXPORT Context {
/** Returns the context that is on the top of the stack. */ /** Returns the context that is on the top of the stack. */
static Local<Context> GetCurrent(); static Local<Context> GetCurrent();
/**
* Returns the context of the calling JavaScript code. That is the
* context of the top-most JavaScript frame. If there are no
* JavaScript frames an empty handle is returned.
*/
static Local<Context> GetCalling();
/** /**
* Sets the security token for the context. To access an object in * Sets the security token for the context. To access an object in
* another context, the security tokens must match. * another context, the security tokens must match.

16
deps/v8/src/SConscript

@ -43,14 +43,14 @@ SOURCES = {
'flags.cc', 'frames.cc', 'func-name-inferrer.cc', 'flags.cc', 'frames.cc', 'func-name-inferrer.cc',
'global-handles.cc', 'handles.cc', 'hashmap.cc', 'global-handles.cc', 'handles.cc', 'hashmap.cc',
'heap.cc', 'ic.cc', 'interpreter-irregexp.cc', 'jsregexp.cc', 'heap.cc', 'ic.cc', 'interpreter-irregexp.cc', 'jsregexp.cc',
'jump-target.cc', 'log.cc', 'mark-compact.cc', 'messages.cc', 'objects.cc', 'jump-target.cc', 'log.cc', 'log-utils.cc', 'mark-compact.cc', 'messages.cc',
'oprofile-agent.cc', 'parser.cc', 'property.cc', 'regexp-macro-assembler.cc', 'objects.cc', 'oprofile-agent.cc', 'parser.cc', 'property.cc',
'regexp-macro-assembler-irregexp.cc', 'regexp-stack.cc', 'regexp-macro-assembler.cc', 'regexp-macro-assembler-irregexp.cc',
'register-allocator.cc', 'rewriter.cc', 'runtime.cc', 'scanner.cc', 'regexp-stack.cc', 'register-allocator.cc', 'rewriter.cc', 'runtime.cc',
'scopeinfo.cc', 'scopes.cc', 'serialize.cc', 'snapshot-common.cc', 'scanner.cc', 'scopeinfo.cc', 'scopes.cc', 'serialize.cc',
'spaces.cc', 'string-stream.cc', 'stub-cache.cc', 'token.cc', 'top.cc', 'snapshot-common.cc', 'spaces.cc', 'string-stream.cc', 'stub-cache.cc',
'unicode.cc', 'usage-analyzer.cc', 'utils.cc', 'v8-counters.cc', 'token.cc', 'top.cc', 'unicode.cc', 'usage-analyzer.cc', 'utils.cc',
'v8.cc', 'v8threads.cc', 'variables.cc', 'version.cc', 'v8-counters.cc', 'v8.cc', 'v8threads.cc', 'variables.cc', 'version.cc',
'virtual-frame.cc', 'zone.cc' 'virtual-frame.cc', 'zone.cc'
], ],
'arch:arm': [ 'arch:arm': [

74
deps/v8/src/accessors.cc

@ -34,7 +34,8 @@
#include "top.h" #include "top.h"
#include "zone-inl.h" #include "zone-inl.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
template <class C> template <class C>
@ -287,6 +288,24 @@ const AccessorDescriptor Accessors::ScriptType = {
}; };
//
// Accessors::ScriptCompilationType
//
Object* Accessors::ScriptGetCompilationType(Object* object, void*) {
Object* script = JSValue::cast(object)->value();
return Script::cast(script)->compilation_type();
}
const AccessorDescriptor Accessors::ScriptCompilationType = {
ScriptGetCompilationType,
IllegalSetter,
0
};
// //
// Accessors::ScriptGetLineEnds // Accessors::ScriptGetLineEnds
// //
@ -313,9 +332,8 @@ const AccessorDescriptor Accessors::ScriptLineEnds = {
Object* Accessors::ScriptGetContextData(Object* object, void*) { Object* Accessors::ScriptGetContextData(Object* object, void*) {
HandleScope scope; Object* script = JSValue::cast(object)->value();
Handle<Script> script(Script::cast(JSValue::cast(object)->value())); return Script::cast(script)->context_data();
return script->context_data();
} }
@ -326,6 +344,54 @@ const AccessorDescriptor Accessors::ScriptContextData = {
}; };
//
// Accessors::ScriptGetEvalFromFunction
//
Object* Accessors::ScriptGetEvalFromFunction(Object* object, void*) {
Object* script = JSValue::cast(object)->value();
return Script::cast(script)->eval_from_function();
}
const AccessorDescriptor Accessors::ScriptEvalFromFunction = {
ScriptGetEvalFromFunction,
IllegalSetter,
0
};
//
// Accessors::ScriptGetEvalFromPosition
//
Object* Accessors::ScriptGetEvalFromPosition(Object* object, void*) {
HandleScope scope;
Handle<Script> script(Script::cast(JSValue::cast(object)->value()));
// If this is not a script compiled through eval there is no eval position.
int compilation_type = Smi::cast(script->compilation_type())->value();
if (compilation_type != Script::COMPILATION_TYPE_EVAL) {
return Heap::undefined_value();
}
// Get the function from where eval was called and find the source position
// from the instruction offset.
Handle<Code> code(JSFunction::cast(script->eval_from_function())->code());
return Smi::FromInt(code->SourcePosition(code->instruction_start() +
script->eval_from_instructions_offset()->value()));
}
const AccessorDescriptor Accessors::ScriptEvalFromPosition = {
ScriptGetEvalFromPosition,
IllegalSetter,
0
};
// //
// Accessors::FunctionPrototype // Accessors::FunctionPrototype
// //

41
deps/v8/src/accessors.h

@ -28,27 +28,31 @@
#ifndef V8_ACCESSORS_H_ #ifndef V8_ACCESSORS_H_
#define V8_ACCESSORS_H_ #define V8_ACCESSORS_H_
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// The list of accessor descriptors. This is a second-order macro // The list of accessor descriptors. This is a second-order macro
// taking a macro to be applied to all accessor descriptor names. // taking a macro to be applied to all accessor descriptor names.
#define ACCESSOR_DESCRIPTOR_LIST(V) \ #define ACCESSOR_DESCRIPTOR_LIST(V) \
V(FunctionPrototype) \ V(FunctionPrototype) \
V(FunctionLength) \ V(FunctionLength) \
V(FunctionName) \ V(FunctionName) \
V(FunctionArguments) \ V(FunctionArguments) \
V(FunctionCaller) \ V(FunctionCaller) \
V(ArrayLength) \ V(ArrayLength) \
V(StringLength) \ V(StringLength) \
V(ScriptSource) \ V(ScriptSource) \
V(ScriptName) \ V(ScriptName) \
V(ScriptId) \ V(ScriptId) \
V(ScriptLineOffset) \ V(ScriptLineOffset) \
V(ScriptColumnOffset) \ V(ScriptColumnOffset) \
V(ScriptData) \ V(ScriptData) \
V(ScriptType) \ V(ScriptType) \
V(ScriptLineEnds) \ V(ScriptCompilationType) \
V(ScriptContextData) \ V(ScriptLineEnds) \
V(ScriptContextData) \
V(ScriptEvalFromFunction) \
V(ScriptEvalFromPosition) \
V(ObjectPrototype) V(ObjectPrototype)
// Accessors contains all predefined proxy accessors. // Accessors contains all predefined proxy accessors.
@ -88,8 +92,11 @@ class Accessors : public AllStatic {
static Object* ScriptGetColumnOffset(Object* object, void*); static Object* ScriptGetColumnOffset(Object* object, void*);
static Object* ScriptGetData(Object* object, void*); static Object* ScriptGetData(Object* object, void*);
static Object* ScriptGetType(Object* object, void*); static Object* ScriptGetType(Object* object, void*);
static Object* ScriptGetCompilationType(Object* object, void*);
static Object* ScriptGetLineEnds(Object* object, void*); static Object* ScriptGetLineEnds(Object* object, void*);
static Object* ScriptGetContextData(Object* object, void*); static Object* ScriptGetContextData(Object* object, void*);
static Object* ScriptGetEvalFromFunction(Object* object, void*);
static Object* ScriptGetEvalFromPosition(Object* object, void*);
static Object* ObjectGetPrototype(Object* receiver, void*); static Object* ObjectGetPrototype(Object* receiver, void*);
static Object* ObjectSetPrototype(JSObject* receiver, Object* value, void*); static Object* ObjectSetPrototype(JSObject* receiver, Object* value, void*);

3
deps/v8/src/allocation.cc

@ -29,7 +29,8 @@
#include "v8.h" #include "v8.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
void* Malloced::New(size_t size) { void* Malloced::New(size_t size) {

3
deps/v8/src/allocation.h

@ -28,7 +28,8 @@
#ifndef V8_ALLOCATION_H_ #ifndef V8_ALLOCATION_H_
#define V8_ALLOCATION_H_ #define V8_ALLOCATION_H_
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// A class that controls whether allocation is allowed. This is for // A class that controls whether allocation is allowed. This is for

84
deps/v8/src/api.cc

@ -99,7 +99,6 @@ static i::HandleScopeImplementer thread_local;
// --- E x c e p t i o n B e h a v i o r --- // --- E x c e p t i o n B e h a v i o r ---
static bool has_shut_down = false;
static FatalErrorCallback exception_behavior = NULL; static FatalErrorCallback exception_behavior = NULL;
@ -123,7 +122,7 @@ static FatalErrorCallback& GetFatalErrorHandler() {
// When V8 cannot allocated memory FatalProcessOutOfMemory is called. // When V8 cannot allocated memory FatalProcessOutOfMemory is called.
// The default fatal error handler is called and execution is stopped. // The default fatal error handler is called and execution is stopped.
void i::V8::FatalProcessOutOfMemory(const char* location) { void i::V8::FatalProcessOutOfMemory(const char* location) {
has_shut_down = true; i::V8::SetFatalError();
FatalErrorCallback callback = GetFatalErrorHandler(); FatalErrorCallback callback = GetFatalErrorHandler();
{ {
LEAVE_V8; LEAVE_V8;
@ -142,13 +141,13 @@ void V8::SetFatalErrorHandler(FatalErrorCallback that) {
bool Utils::ReportApiFailure(const char* location, const char* message) { bool Utils::ReportApiFailure(const char* location, const char* message) {
FatalErrorCallback callback = GetFatalErrorHandler(); FatalErrorCallback callback = GetFatalErrorHandler();
callback(location, message); callback(location, message);
has_shut_down = true; i::V8::SetFatalError();
return false; return false;
} }
bool V8::IsDead() { bool V8::IsDead() {
return has_shut_down; return i::V8::IsDead();
} }
@ -186,7 +185,8 @@ static bool ReportEmptyHandle(const char* location) {
* yet been done. * yet been done.
*/ */
static inline bool IsDeadCheck(const char* location) { static inline bool IsDeadCheck(const char* location) {
return has_shut_down ? ReportV8Dead(location) : false; return !i::V8::IsRunning()
&& i::V8::IsDead() ? ReportV8Dead(location) : false;
} }
@ -205,9 +205,14 @@ static inline bool EmptyCheck(const char* location, const v8::Data* obj) {
static i::StringInputBuffer write_input_buffer; static i::StringInputBuffer write_input_buffer;
static void EnsureInitialized(const char* location) { static inline bool EnsureInitialized(const char* location) {
if (IsDeadCheck(location)) return; if (i::V8::IsRunning()) {
ApiCheck(v8::V8::Initialize(), location, "Error initializing V8"); return true;
}
if (IsDeadCheck(location)) {
return false;
}
return ApiCheck(v8::V8::Initialize(), location, "Error initializing V8");
} }
@ -225,29 +230,25 @@ void ImplementationUtilities::ZapHandleRange(void** begin, void** end) {
v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() { v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() {
if (IsDeadCheck("v8::Undefined()")) return v8::Handle<v8::Primitive>(); if (!EnsureInitialized("v8::Undefined()")) return v8::Handle<v8::Primitive>();
EnsureInitialized("v8::Undefined()");
return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value())); return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value()));
} }
v8::Handle<v8::Primitive> ImplementationUtilities::Null() { v8::Handle<v8::Primitive> ImplementationUtilities::Null() {
if (IsDeadCheck("v8::Null()")) return v8::Handle<v8::Primitive>(); if (!EnsureInitialized("v8::Null()")) return v8::Handle<v8::Primitive>();
EnsureInitialized("v8::Null()");
return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::null_value())); return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::null_value()));
} }
v8::Handle<v8::Boolean> ImplementationUtilities::True() { v8::Handle<v8::Boolean> ImplementationUtilities::True() {
if (IsDeadCheck("v8::True()")) return v8::Handle<v8::Boolean>(); if (!EnsureInitialized("v8::True()")) return v8::Handle<v8::Boolean>();
EnsureInitialized("v8::True()");
return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::true_value())); return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::true_value()));
} }
v8::Handle<v8::Boolean> ImplementationUtilities::False() { v8::Handle<v8::Boolean> ImplementationUtilities::False() {
if (IsDeadCheck("v8::False()")) return v8::Handle<v8::Boolean>(); if (!EnsureInitialized("v8::False()")) return v8::Handle<v8::Boolean>();
EnsureInitialized("v8::False()");
return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::false_value())); return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::false_value()));
} }
@ -373,21 +374,21 @@ void V8::ClearWeak(void** obj) {
bool V8::IsGlobalNearDeath(void** obj) { bool V8::IsGlobalNearDeath(void** obj) {
LOG_API("IsGlobalNearDeath"); LOG_API("IsGlobalNearDeath");
if (has_shut_down) return false; if (!i::V8::IsRunning()) return false;
return i::GlobalHandles::IsNearDeath(reinterpret_cast<i::Object**>(obj)); return i::GlobalHandles::IsNearDeath(reinterpret_cast<i::Object**>(obj));
} }
bool V8::IsGlobalWeak(void** obj) { bool V8::IsGlobalWeak(void** obj) {
LOG_API("IsGlobalWeak"); LOG_API("IsGlobalWeak");
if (has_shut_down) return false; if (!i::V8::IsRunning()) return false;
return i::GlobalHandles::IsWeak(reinterpret_cast<i::Object**>(obj)); return i::GlobalHandles::IsWeak(reinterpret_cast<i::Object**>(obj));
} }
void V8::DisposeGlobal(void** obj) { void V8::DisposeGlobal(void** obj) {
LOG_API("DisposeGlobal"); LOG_API("DisposeGlobal");
if (has_shut_down) return; if (!i::V8::IsRunning()) return;
i::Object** ptr = reinterpret_cast<i::Object**>(obj); i::Object** ptr = reinterpret_cast<i::Object**>(obj);
if ((*ptr)->IsGlobalContext()) i::Heap::NotifyContextDisposed(); if ((*ptr)->IsGlobalContext()) i::Heap::NotifyContextDisposed();
i::GlobalHandles::Destroy(ptr); i::GlobalHandles::Destroy(ptr);
@ -415,7 +416,8 @@ int HandleScope::NumberOfHandles() {
void** v8::HandleScope::CreateHandle(void* value) { void** v8::HandleScope::CreateHandle(void* value) {
return i::HandleScope::CreateHandle(value); return reinterpret_cast<void**>(
i::HandleScope::CreateHandle(reinterpret_cast<i::Object*>(value)));
} }
@ -431,7 +433,7 @@ void Context::Enter() {
void Context::Exit() { void Context::Exit() {
if (has_shut_down) return; if (!i::V8::IsRunning()) return;
if (!ApiCheck(thread_local.LeaveLastContext(), if (!ApiCheck(thread_local.LeaveLastContext(),
"v8::Context::Exit()", "v8::Context::Exit()",
"Cannot exit non-entered context")) { "Cannot exit non-entered context")) {
@ -1890,6 +1892,19 @@ bool v8::Object::ForceSet(v8::Handle<Value> key,
} }
bool v8::Object::ForceDelete(v8::Handle<Value> key) {
ON_BAILOUT("v8::Object::ForceDelete()", return false);
ENTER_V8;
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
EXCEPTION_PREAMBLE();
i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
has_pending_exception = obj.is_null();
EXCEPTION_BAILOUT_CHECK(false);
return obj->IsTrue();
}
Local<Value> v8::Object::Get(v8::Handle<Value> key) { Local<Value> v8::Object::Get(v8::Handle<Value> key) {
ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>()); ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
ENTER_V8; ENTER_V8;
@ -2450,7 +2465,7 @@ void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
// --- E n v i r o n m e n t --- // --- E n v i r o n m e n t ---
bool v8::V8::Initialize() { bool v8::V8::Initialize() {
if (i::V8::HasBeenSetup()) return true; if (i::V8::IsRunning()) return true;
ENTER_V8; ENTER_V8;
HandleScope scope; HandleScope scope;
if (i::Snapshot::Initialize()) { if (i::Snapshot::Initialize()) {
@ -2612,6 +2627,13 @@ v8::Local<v8::Context> Context::GetCurrent() {
} }
v8::Local<v8::Context> Context::GetCalling() {
if (IsDeadCheck("v8::Context::GetCalling()")) return Local<Context>();
i::Handle<i::Context> context(i::Top::GetCallingGlobalContext());
return Utils::ToLocal(context);
}
v8::Local<v8::Object> Context::Global() { v8::Local<v8::Object> Context::Global() {
if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>(); if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
i::Object** ctx = reinterpret_cast<i::Object**>(this); i::Object** ctx = reinterpret_cast<i::Object**>(this);
@ -3116,16 +3138,28 @@ void V8::PauseProfiler() {
#endif #endif
} }
void V8::ResumeProfiler() { void V8::ResumeProfiler() {
#ifdef ENABLE_LOGGING_AND_PROFILING #ifdef ENABLE_LOGGING_AND_PROFILING
i::Logger::ResumeProfiler(); i::Logger::ResumeProfiler();
#endif #endif
} }
bool V8::IsProfilerPaused() {
#ifdef ENABLE_LOGGING_AND_PROFILING
return i::Logger::IsProfilerPaused();
#else
return true;
#endif
}
int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) { int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
#ifdef ENABLE_LOGGING_AND_PROFILING #ifdef ENABLE_LOGGING_AND_PROFILING
return i::Logger::GetLogLines(from_pos, dest_buf, max_size); return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
#endif #endif
return 0;
} }
String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) { String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
@ -3312,7 +3346,7 @@ bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
void Debug::DebugBreak() { void Debug::DebugBreak() {
if (!i::V8::HasBeenSetup()) return; if (!i::V8::IsRunning()) return;
i::StackGuard::DebugBreak(); i::StackGuard::DebugBreak();
} }
@ -3354,7 +3388,7 @@ void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
void Debug::SendCommand(const uint16_t* command, int length, void Debug::SendCommand(const uint16_t* command, int length,
ClientData* client_data) { ClientData* client_data) {
if (!i::V8::HasBeenSetup()) return; if (!i::V8::IsRunning()) return;
i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length), i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
client_data); client_data);
} }
@ -3370,7 +3404,7 @@ void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
Handle<Value> Debug::Call(v8::Handle<v8::Function> fun, Handle<Value> Debug::Call(v8::Handle<v8::Function> fun,
v8::Handle<v8::Value> data) { v8::Handle<v8::Value> data) {
if (!i::V8::HasBeenSetup()) return Handle<Value>(); if (!i::V8::IsRunning()) return Handle<Value>();
ON_BAILOUT("v8::Debug::Call()", return Handle<Value>()); ON_BAILOUT("v8::Debug::Call()", return Handle<Value>());
ENTER_V8; ENTER_V8;
i::Handle<i::Object> result; i::Handle<i::Object> result;

3
deps/v8/src/arguments.h

@ -28,7 +28,8 @@
#ifndef V8_ARGUMENTS_H_ #ifndef V8_ARGUMENTS_H_
#define V8_ARGUMENTS_H_ #define V8_ARGUMENTS_H_
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// Arguments provides access to runtime call parameters. // Arguments provides access to runtime call parameters.
// //

3
deps/v8/src/arm/assembler-arm-inl.h

@ -41,7 +41,8 @@
#include "cpu.h" #include "cpu.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
Condition NegateCondition(Condition cc) { Condition NegateCondition(Condition cc) {
ASSERT(cc != al); ASSERT(cc != al);

7
deps/v8/src/arm/assembler-arm.cc

@ -39,7 +39,8 @@
#include "arm/assembler-arm-inl.h" #include "arm/assembler-arm-inl.h"
#include "serialize.h" #include "serialize.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Implementation of Register and CRegister // Implementation of Register and CRegister
@ -211,6 +212,7 @@ enum {
// Instruction bit masks // Instruction bit masks
RdMask = 15 << 12, // in str instruction RdMask = 15 << 12, // in str instruction
CondMask = 15 << 28, CondMask = 15 << 28,
CoprocessorMask = 15 << 8,
OpCodeMask = 15 << 21, // in data-processing instructions OpCodeMask = 15 << 21, // in data-processing instructions
Imm24Mask = (1 << 24) - 1, Imm24Mask = (1 << 24) - 1,
Off12Mask = (1 << 12) - 1, Off12Mask = (1 << 12) - 1,
@ -616,7 +618,8 @@ void Assembler::addrmod4(Instr instr, Register rn, RegList rl) {
void Assembler::addrmod5(Instr instr, CRegister crd, const MemOperand& x) { void Assembler::addrmod5(Instr instr, CRegister crd, const MemOperand& x) {
// unindexed addressing is not encoded by this function // unindexed addressing is not encoded by this function
ASSERT((instr & ~(CondMask | P | U | N | W | L)) == (B27 | B26)); ASSERT_EQ((B27 | B26),
(instr & ~(CondMask | CoprocessorMask | P | U | N | W | L)));
ASSERT(x.rn_.is_valid() && !x.rm_.is_valid()); ASSERT(x.rn_.is_valid() && !x.rm_.is_valid());
int am = x.am_; int am = x.am_;
int offset_8 = x.offset_; int offset_8 = x.offset_;

9
deps/v8/src/arm/assembler-arm.h

@ -42,7 +42,8 @@
#include "assembler.h" #include "assembler.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// CPU Registers. // CPU Registers.
// //
@ -83,8 +84,6 @@ struct Register {
}; };
const int kNumRegisters = 16;
extern Register no_reg; extern Register no_reg;
extern Register r0; extern Register r0;
extern Register r1; extern Register r1;
@ -622,8 +621,8 @@ class Assembler : public Malloced {
// Pseudo instructions // Pseudo instructions
void nop() { mov(r0, Operand(r0)); } void nop() { mov(r0, Operand(r0)); }
void push(Register src) { void push(Register src, Condition cond = al) {
str(src, MemOperand(sp, 4, NegPreIndex), al); str(src, MemOperand(sp, 4, NegPreIndex), cond);
} }
void pop(Register dst) { void pop(Register dst) {

5
deps/v8/src/arm/builtins-arm.cc

@ -31,7 +31,8 @@
#include "debug.h" #include "debug.h"
#include "runtime.h" #include "runtime.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
#define __ ACCESS_MASM(masm) #define __ ACCESS_MASM(masm)
@ -187,7 +188,7 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
// Set expected number of arguments to zero (not changing r0). // Set expected number of arguments to zero (not changing r0).
__ mov(r2, Operand(0)); __ mov(r2, Operand(0));
__ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
__ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
} }

46
deps/v8/src/arm/codegen-arm-inl.h

@ -0,0 +1,46 @@
// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_ARM_CODEGEN_ARM_INL_H_
#define V8_ARM_CODEGEN_ARM_INL_H_
namespace v8 {
namespace internal {
#define __ ACCESS_MASM(masm_)
// Platform-specific inline functions.
void DeferredCode::Jump() { __ jmp(&entry_label_); }
void DeferredCode::Branch(Condition cc) { __ b(cc, &entry_label_); }
#undef __
} } // namespace v8::internal
#endif // V8_ARM_CODEGEN_ARM_INL_H_

586
deps/v8/src/arm/codegen-arm.cc

File diff suppressed because it is too large

11
deps/v8/src/arm/codegen-arm.h

@ -28,7 +28,8 @@
#ifndef V8_ARM_CODEGEN_ARM_H_ #ifndef V8_ARM_CODEGEN_ARM_H_
#define V8_ARM_CODEGEN_ARM_H_ #define V8_ARM_CODEGEN_ARM_H_
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// Forward declarations // Forward declarations
class DeferredCode; class DeferredCode;
@ -193,8 +194,7 @@ class CodeGenerator: public AstVisitor {
// Accessors // Accessors
Scope* scope() const { return scope_; } Scope* scope() const { return scope_; }
// Clearing and generating deferred code. // Generating deferred code.
void ClearDeferred();
void ProcessDeferred(); void ProcessDeferred();
bool is_eval() { return is_eval_; } bool is_eval() { return is_eval_; }
@ -205,6 +205,8 @@ class CodeGenerator: public AstVisitor {
JumpTarget* true_target() const { return state_->true_target(); } JumpTarget* true_target() const { return state_->true_target(); }
JumpTarget* false_target() const { return state_->false_target(); } JumpTarget* false_target() const { return state_->false_target(); }
// We don't track loop nesting level on ARM yet.
int loop_nesting() const { return 0; }
// Node visitors. // Node visitors.
void VisitStatements(ZoneList<Statement*>* statements); void VisitStatements(ZoneList<Statement*>* statements);
@ -317,8 +319,7 @@ class CodeGenerator: public AstVisitor {
Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node); Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node);
void ProcessDeclarations(ZoneList<Declaration*>* declarations); void ProcessDeclarations(ZoneList<Declaration*>* declarations);
Handle<Code> ComputeCallInitialize(int argc); Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
Handle<Code> ComputeCallInitializeInLoop(int argc);
// Declare global variables and functions in the given array of // Declare global variables and functions in the given array of
// name/value pairs. // name/value pairs.

3
deps/v8/src/arm/constants-arm.h

@ -28,7 +28,8 @@
#ifndef V8_ARM_CONSTANTS_ARM_H_ #ifndef V8_ARM_CONSTANTS_ARM_H_
#define V8_ARM_CONSTANTS_ARM_H_ #define V8_ARM_CONSTANTS_ARM_H_
namespace assembler { namespace arm { namespace assembler {
namespace arm {
// Defines constants and accessor classes to assemble, disassemble and // Defines constants and accessor classes to assemble, disassemble and
// simulate ARM instructions. // simulate ARM instructions.

3
deps/v8/src/arm/cpu-arm.cc

@ -34,7 +34,8 @@
#include "cpu.h" #include "cpu.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
void CPU::Setup() { void CPU::Setup() {
// Nothing to do. // Nothing to do.

3
deps/v8/src/arm/debug-arm.cc

@ -30,7 +30,8 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "debug.h" #include "debug.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
// Currently debug break is not supported in frame exit code on ARM. // Currently debug break is not supported in frame exit code on ARM.

3
deps/v8/src/arm/disasm-arm.cc

@ -62,7 +62,8 @@
#include "platform.h" #include "platform.h"
namespace assembler { namespace arm { namespace assembler {
namespace arm {
namespace v8i = v8::internal; namespace v8i = v8::internal;

3
deps/v8/src/arm/frames-arm.cc

@ -31,7 +31,8 @@
#include "arm/assembler-arm-inl.h" #include "arm/assembler-arm-inl.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
StackFrame::Type StackFrame::ComputeType(State* state) { StackFrame::Type StackFrame::ComputeType(State* state) {

3
deps/v8/src/arm/frames-arm.h

@ -28,7 +28,8 @@
#ifndef V8_ARM_FRAMES_ARM_H_ #ifndef V8_ARM_FRAMES_ARM_H_
#define V8_ARM_FRAMES_ARM_H_ #define V8_ARM_FRAMES_ARM_H_
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// The ARM ABI does not specify the usage of register r9, which may be reserved // The ARM ABI does not specify the usage of register r9, which may be reserved

13
deps/v8/src/arm/ic-arm.cc

@ -32,7 +32,8 @@
#include "runtime.h" #include "runtime.h"
#include "stub-cache.h" #include "stub-cache.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -211,7 +212,7 @@ void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
// Probe the stub cache. // Probe the stub cache.
Code::Flags flags = Code::Flags flags =
Code::ComputeFlags(Code::CALL_IC, MONOMORPHIC, NORMAL, argc); Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc);
StubCache::GenerateProbe(masm, flags, r1, r2, r3); StubCache::GenerateProbe(masm, flags, r1, r2, r3);
// If the stub cache probing failed, the receiver might be a value. // If the stub cache probing failed, the receiver might be a value.
@ -422,7 +423,9 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
__ ldr(r0, MemOperand(sp, 0)); __ ldr(r0, MemOperand(sp, 0));
// Probe the stub cache. // Probe the stub cache.
Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, MONOMORPHIC); Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
NOT_IN_LOOP,
MONOMORPHIC);
StubCache::GenerateProbe(masm, flags, r0, r2, r3); StubCache::GenerateProbe(masm, flags, r0, r2, r3);
// Cache miss: Jump to runtime. // Cache miss: Jump to runtime.
@ -755,7 +758,9 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
// Get the receiver from the stack and probe the stub cache. // Get the receiver from the stack and probe the stub cache.
__ ldr(r1, MemOperand(sp)); __ ldr(r1, MemOperand(sp));
Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, MONOMORPHIC); Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
NOT_IN_LOOP,
MONOMORPHIC);
StubCache::GenerateProbe(masm, flags, r1, r2, r3); StubCache::GenerateProbe(masm, flags, r1, r2, r3);
// Cache miss: Jump to runtime. // Cache miss: Jump to runtime.

147
deps/v8/src/arm/jump-target-arm.cc

@ -28,46 +28,47 @@
#include "v8.h" #include "v8.h"
#include "codegen-inl.h" #include "codegen-inl.h"
#include "jump-target-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// JumpTarget implementation. // JumpTarget implementation.
#define __ ACCESS_MASM(masm_) #define __ ACCESS_MASM(cgen()->masm())
void JumpTarget::DoJump() { void JumpTarget::DoJump() {
ASSERT(cgen_ != NULL); ASSERT(cgen()->has_valid_frame());
ASSERT(cgen_->has_valid_frame());
// Live non-frame registers are not allowed at unconditional jumps // Live non-frame registers are not allowed at unconditional jumps
// because we have no way of invalidating the corresponding results // because we have no way of invalidating the corresponding results
// which are still live in the C++ code. // which are still live in the C++ code.
ASSERT(cgen_->HasValidEntryRegisters()); ASSERT(cgen()->HasValidEntryRegisters());
if (is_bound()) { if (is_bound()) {
// Backward jump. There is an expected frame to merge to. // Backward jump. There is an expected frame to merge to.
ASSERT(direction_ == BIDIRECTIONAL); ASSERT(direction_ == BIDIRECTIONAL);
cgen_->frame()->MergeTo(entry_frame_); cgen()->frame()->PrepareMergeTo(entry_frame_);
cgen_->DeleteFrame(); cgen()->frame()->MergeTo(entry_frame_);
cgen()->DeleteFrame();
__ jmp(&entry_label_); __ jmp(&entry_label_);
} else { } else {
// Preconfigured entry frame is not used on ARM.
ASSERT(entry_frame_ == NULL);
// Forward jump. The current frame is added to the end of the list // Forward jump. The current frame is added to the end of the list
// of frames reaching the target block and a jump to the merge code // of frames reaching the target block and a jump to the merge code
// is emitted. // is emitted.
AddReachingFrame(cgen_->frame()); AddReachingFrame(cgen()->frame());
RegisterFile empty; RegisterFile empty;
cgen_->SetFrame(NULL, &empty); cgen()->SetFrame(NULL, &empty);
__ jmp(&merge_labels_.last()); __ jmp(&merge_labels_.last());
} }
is_linked_ = !is_bound_;
} }
void JumpTarget::DoBranch(Condition cc, Hint ignored) { void JumpTarget::DoBranch(Condition cc, Hint ignored) {
ASSERT(cgen_ != NULL); ASSERT(cgen()->has_valid_frame());
ASSERT(cgen_->has_valid_frame());
if (is_bound()) { if (is_bound()) {
ASSERT(direction_ == BIDIRECTIONAL); ASSERT(direction_ == BIDIRECTIONAL);
@ -77,29 +78,29 @@ void JumpTarget::DoBranch(Condition cc, Hint ignored) {
// Swap the current frame for a copy (we do the swapping to get // Swap the current frame for a copy (we do the swapping to get
// the off-frame registers off the fall through) to use for the // the off-frame registers off the fall through) to use for the
// branch. // branch.
VirtualFrame* fall_through_frame = cgen_->frame(); VirtualFrame* fall_through_frame = cgen()->frame();
VirtualFrame* branch_frame = new VirtualFrame(fall_through_frame); VirtualFrame* branch_frame = new VirtualFrame(fall_through_frame);
RegisterFile non_frame_registers = RegisterAllocator::Reserved(); RegisterFile non_frame_registers;
cgen_->SetFrame(branch_frame, &non_frame_registers); cgen()->SetFrame(branch_frame, &non_frame_registers);
// Check if we can avoid merge code. // Check if we can avoid merge code.
cgen_->frame()->PrepareMergeTo(entry_frame_); cgen()->frame()->PrepareMergeTo(entry_frame_);
if (cgen_->frame()->Equals(entry_frame_)) { if (cgen()->frame()->Equals(entry_frame_)) {
// Branch right in to the block. // Branch right in to the block.
cgen_->DeleteFrame(); cgen()->DeleteFrame();
__ b(cc, &entry_label_); __ b(cc, &entry_label_);
cgen_->SetFrame(fall_through_frame, &non_frame_registers); cgen()->SetFrame(fall_through_frame, &non_frame_registers);
return; return;
} }
// Check if we can reuse existing merge code. // Check if we can reuse existing merge code.
for (int i = 0; i < reaching_frames_.length(); i++) { for (int i = 0; i < reaching_frames_.length(); i++) {
if (reaching_frames_[i] != NULL && if (reaching_frames_[i] != NULL &&
cgen_->frame()->Equals(reaching_frames_[i])) { cgen()->frame()->Equals(reaching_frames_[i])) {
// Branch to the merge code. // Branch to the merge code.
cgen_->DeleteFrame(); cgen()->DeleteFrame();
__ b(cc, &merge_labels_[i]); __ b(cc, &merge_labels_[i]);
cgen_->SetFrame(fall_through_frame, &non_frame_registers); cgen()->SetFrame(fall_through_frame, &non_frame_registers);
return; return;
} }
} }
@ -108,19 +109,20 @@ void JumpTarget::DoBranch(Condition cc, Hint ignored) {
// around the merge code on the fall through path. // around the merge code on the fall through path.
Label original_fall_through; Label original_fall_through;
__ b(NegateCondition(cc), &original_fall_through); __ b(NegateCondition(cc), &original_fall_through);
cgen_->frame()->MergeTo(entry_frame_); cgen()->frame()->MergeTo(entry_frame_);
cgen_->DeleteFrame(); cgen()->DeleteFrame();
__ b(&entry_label_); __ b(&entry_label_);
cgen_->SetFrame(fall_through_frame, &non_frame_registers); cgen()->SetFrame(fall_through_frame, &non_frame_registers);
__ bind(&original_fall_through); __ bind(&original_fall_through);
} else { } else {
// Preconfigured entry frame is not used on ARM.
ASSERT(entry_frame_ == NULL);
// Forward branch. A copy of the current frame is added to the end // Forward branch. A copy of the current frame is added to the end
// of the list of frames reaching the target block and a branch to // of the list of frames reaching the target block and a branch to
// the merge code is emitted. // the merge code is emitted.
AddReachingFrame(new VirtualFrame(cgen_->frame())); AddReachingFrame(new VirtualFrame(cgen()->frame()));
__ b(cc, &merge_labels_.last()); __ b(cc, &merge_labels_.last());
is_linked_ = true;
} }
} }
@ -132,70 +134,63 @@ void JumpTarget::Call() {
// at the label (which should be the only one) is the spilled current // at the label (which should be the only one) is the spilled current
// frame plus an in-memory return address. The "fall-through" frame // frame plus an in-memory return address. The "fall-through" frame
// at the return site is the spilled current frame. // at the return site is the spilled current frame.
ASSERT(cgen_ != NULL); ASSERT(cgen()->has_valid_frame());
ASSERT(cgen_->has_valid_frame());
// There are no non-frame references across the call. // There are no non-frame references across the call.
ASSERT(cgen_->HasValidEntryRegisters()); ASSERT(cgen()->HasValidEntryRegisters());
ASSERT(!is_linked()); ASSERT(!is_linked());
cgen_->frame()->SpillAll(); cgen()->frame()->SpillAll();
VirtualFrame* target_frame = new VirtualFrame(cgen_->frame()); VirtualFrame* target_frame = new VirtualFrame(cgen()->frame());
target_frame->Adjust(1); target_frame->Adjust(1);
// We do not expect a call with a preconfigured entry frame.
ASSERT(entry_frame_ == NULL);
AddReachingFrame(target_frame); AddReachingFrame(target_frame);
__ bl(&merge_labels_.last()); __ bl(&merge_labels_.last());
is_linked_ = !is_bound_;
} }
void JumpTarget::DoBind(int mergable_elements) { void JumpTarget::DoBind(int mergable_elements) {
ASSERT(cgen_ != NULL);
ASSERT(!is_bound()); ASSERT(!is_bound());
// Live non-frame registers are not allowed at the start of a basic // Live non-frame registers are not allowed at the start of a basic
// block. // block.
ASSERT(!cgen_->has_valid_frame() || cgen_->HasValidEntryRegisters()); ASSERT(!cgen()->has_valid_frame() || cgen()->HasValidEntryRegisters());
if (direction_ == FORWARD_ONLY) { if (direction_ == FORWARD_ONLY) {
// A simple case: no forward jumps and no possible backward jumps. // A simple case: no forward jumps and no possible backward jumps.
if (!is_linked()) { if (!is_linked()) {
// The stack pointer can be floating above the top of the // The stack pointer can be floating above the top of the
// virtual frame before the bind. Afterward, it should not. // virtual frame before the bind. Afterward, it should not.
ASSERT(cgen_->has_valid_frame()); ASSERT(cgen()->has_valid_frame());
VirtualFrame* frame = cgen_->frame(); VirtualFrame* frame = cgen()->frame();
int difference = int difference = frame->stack_pointer_ - (frame->element_count() - 1);
frame->stack_pointer_ - (frame->elements_.length() - 1);
if (difference > 0) { if (difference > 0) {
frame->stack_pointer_ -= difference; frame->stack_pointer_ -= difference;
__ add(sp, sp, Operand(difference * kPointerSize)); __ add(sp, sp, Operand(difference * kPointerSize));
} }
__ bind(&entry_label_);
is_bound_ = true;
return; return;
} }
// Another simple case: no fall through, a single forward jump, // Another simple case: no fall through, a single forward jump,
// and no possible backward jumps. // and no possible backward jumps.
if (!cgen_->has_valid_frame() && reaching_frames_.length() == 1) { if (!cgen()->has_valid_frame() && reaching_frames_.length() == 1) {
// Pick up the only reaching frame, take ownership of it, and // Pick up the only reaching frame, take ownership of it, and
// use it for the block about to be emitted. // use it for the block about to be emitted.
VirtualFrame* frame = reaching_frames_[0]; VirtualFrame* frame = reaching_frames_[0];
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile empty;
cgen_->SetFrame(frame, &reserved); cgen()->SetFrame(frame, &empty);
reaching_frames_[0] = NULL; reaching_frames_[0] = NULL;
__ bind(&merge_labels_[0]); __ bind(&merge_labels_[0]);
// The stack pointer can be floating above the top of the // The stack pointer can be floating above the top of the
// virtual frame before the bind. Afterward, it should not. // virtual frame before the bind. Afterward, it should not.
int difference = int difference = frame->stack_pointer_ - (frame->element_count() - 1);
frame->stack_pointer_ - (frame->elements_.length() - 1);
if (difference > 0) { if (difference > 0) {
frame->stack_pointer_ -= difference; frame->stack_pointer_ -= difference;
__ add(sp, sp, Operand(difference * kPointerSize)); __ add(sp, sp, Operand(difference * kPointerSize));
} }
__ bind(&entry_label_);
is_linked_ = false;
is_bound_ = true;
return; return;
} }
} }
@ -203,15 +198,17 @@ void JumpTarget::DoBind(int mergable_elements) {
// If there is a current frame, record it as the fall-through. It // If there is a current frame, record it as the fall-through. It
// is owned by the reaching frames for now. // is owned by the reaching frames for now.
bool had_fall_through = false; bool had_fall_through = false;
if (cgen_->has_valid_frame()) { if (cgen()->has_valid_frame()) {
had_fall_through = true; had_fall_through = true;
AddReachingFrame(cgen_->frame()); AddReachingFrame(cgen()->frame()); // Return value ignored.
RegisterFile empty; RegisterFile empty;
cgen_->SetFrame(NULL, &empty); cgen()->SetFrame(NULL, &empty);
} }
// Compute the frame to use for entry to the block. // Compute the frame to use for entry to the block.
ComputeEntryFrame(mergable_elements); if (entry_frame_ == NULL) {
ComputeEntryFrame(mergable_elements);
}
// Some moves required to merge to an expected frame require purely // Some moves required to merge to an expected frame require purely
// frame state changes, and do not require any code generation. // frame state changes, and do not require any code generation.
@ -242,17 +239,17 @@ void JumpTarget::DoBind(int mergable_elements) {
// binding site or as the fall through from a previous merge // binding site or as the fall through from a previous merge
// code block. Jump around the code we are about to // code block. Jump around the code we are about to
// generate. // generate.
if (cgen_->has_valid_frame()) { if (cgen()->has_valid_frame()) {
cgen_->DeleteFrame(); cgen()->DeleteFrame();
__ b(&entry_label_); __ b(&entry_label_);
} }
// Pick up the frame for this block. Assume ownership if // Pick up the frame for this block. Assume ownership if
// there cannot be backward jumps. // there cannot be backward jumps.
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile empty;
if (direction_ == BIDIRECTIONAL) { if (direction_ == BIDIRECTIONAL) {
cgen_->SetFrame(new VirtualFrame(frame), &reserved); cgen()->SetFrame(new VirtualFrame(frame), &empty);
} else { } else {
cgen_->SetFrame(frame, &reserved); cgen()->SetFrame(frame, &empty);
reaching_frames_[i] = NULL; reaching_frames_[i] = NULL;
} }
__ bind(&merge_labels_[i]); __ bind(&merge_labels_[i]);
@ -261,23 +258,22 @@ void JumpTarget::DoBind(int mergable_elements) {
// looking for any that can share merge code with this one. // looking for any that can share merge code with this one.
for (int j = 0; j < i; j++) { for (int j = 0; j < i; j++) {
VirtualFrame* other = reaching_frames_[j]; VirtualFrame* other = reaching_frames_[j];
if (other != NULL && other->Equals(cgen_->frame())) { if (other != NULL && other->Equals(cgen()->frame())) {
// Set the reaching frame element to null to avoid // Set the reaching frame element to null to avoid
// processing it later, and then bind its entry label. // processing it later, and then bind its entry label.
delete other;
reaching_frames_[j] = NULL; reaching_frames_[j] = NULL;
__ bind(&merge_labels_[j]); __ bind(&merge_labels_[j]);
} }
} }
// Emit the merge code. // Emit the merge code.
cgen_->frame()->MergeTo(entry_frame_); cgen()->frame()->MergeTo(entry_frame_);
} else if (i == reaching_frames_.length() - 1 && had_fall_through) { } else if (i == reaching_frames_.length() - 1 && had_fall_through) {
// If this is the fall through, and it didn't need merge // If this is the fall through, and it didn't need merge
// code, we need to pick up the frame so we can jump around // code, we need to pick up the frame so we can jump around
// subsequent merge blocks if necessary. // subsequent merge blocks if necessary.
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile empty;
cgen_->SetFrame(frame, &reserved); cgen()->SetFrame(frame, &empty);
reaching_frames_[i] = NULL; reaching_frames_[i] = NULL;
} }
} }
@ -286,22 +282,17 @@ void JumpTarget::DoBind(int mergable_elements) {
// The code generator may not have a current frame if there was no // The code generator may not have a current frame if there was no
// fall through and none of the reaching frames needed merging. // fall through and none of the reaching frames needed merging.
// In that case, clone the entry frame as the current frame. // In that case, clone the entry frame as the current frame.
if (!cgen_->has_valid_frame()) { if (!cgen()->has_valid_frame()) {
RegisterFile reserved_registers = RegisterAllocator::Reserved(); RegisterFile empty;
cgen_->SetFrame(new VirtualFrame(entry_frame_), &reserved_registers); cgen()->SetFrame(new VirtualFrame(entry_frame_), &empty);
} }
// There is certainly a current frame equal to the entry frame.
// Bind the entry frame label.
__ bind(&entry_label_);
// There may be unprocessed reaching frames that did not need // There may be unprocessed reaching frames that did not need
// merge code. They will have unbound merge labels. Bind their // merge code. They will have unbound merge labels. Bind their
// merge labels to be the same as the entry label and deallocate // merge labels to be the same as the entry label and deallocate
// them. // them.
for (int i = 0; i < reaching_frames_.length(); i++) { for (int i = 0; i < reaching_frames_.length(); i++) {
if (!merge_labels_[i].is_bound()) { if (!merge_labels_[i].is_bound()) {
delete reaching_frames_[i];
reaching_frames_[i] = NULL; reaching_frames_[i] = NULL;
__ bind(&merge_labels_[i]); __ bind(&merge_labels_[i]);
} }
@ -318,15 +309,13 @@ void JumpTarget::DoBind(int mergable_elements) {
// Use a copy of the reaching frame so the original can be saved // Use a copy of the reaching frame so the original can be saved
// for possible reuse as a backward merge block. // for possible reuse as a backward merge block.
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile empty;
cgen_->SetFrame(new VirtualFrame(reaching_frames_[0]), &reserved); cgen()->SetFrame(new VirtualFrame(reaching_frames_[0]), &empty);
__ bind(&merge_labels_[0]); __ bind(&merge_labels_[0]);
cgen_->frame()->MergeTo(entry_frame_); cgen()->frame()->MergeTo(entry_frame_);
__ bind(&entry_label_);
} }
is_linked_ = false; __ bind(&entry_label_);
is_bound_ = true;
} }
#undef __ #undef __

28
deps/v8/src/arm/macro-assembler-arm.cc

@ -32,7 +32,8 @@
#include "debug.h" #include "debug.h"
#include "runtime.h" #include "runtime.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// Give alias names to registers // Give alias names to registers
Register cp = { 8 }; // JavaScript context pointer Register cp = { 8 }; // JavaScript context pointer
@ -58,7 +59,10 @@ MacroAssembler::MacroAssembler(void* buffer, int size)
// We do not support thumb inter-working with an arm architecture not supporting // We do not support thumb inter-working with an arm architecture not supporting
// the blx instruction (below v5t) // the blx instruction (below v5t)
#if defined(__THUMB_INTERWORK__) #if defined(__THUMB_INTERWORK__)
#if !defined(__ARM_ARCH_5T__) && !defined(__ARM_ARCH_5TE__) #if !defined(__ARM_ARCH_5T__) && \
!defined(__ARM_ARCH_5TE__) && \
!defined(__ARM_ARCH_7A__) && \
!defined(__ARM_ARCH_7__)
// add tests for other versions above v5t as required // add tests for other versions above v5t as required
#error "for thumb inter-working we require architecture v5t or above" #error "for thumb inter-working we require architecture v5t or above"
#endif #endif
@ -291,6 +295,12 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
void MacroAssembler::EnterExitFrame(StackFrame::Type type) { void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
ASSERT(type == StackFrame::EXIT || type == StackFrame::EXIT_DEBUG); ASSERT(type == StackFrame::EXIT || type == StackFrame::EXIT_DEBUG);
// Compute the argv pointer and keep it in a callee-saved register.
// r0 is argc.
add(r6, sp, Operand(r0, LSL, kPointerSizeLog2));
sub(r6, r6, Operand(kPointerSize));
// Compute parameter pointer before making changes and save it as ip // Compute parameter pointer before making changes and save it as ip
// register so that it is restored as sp register on exit, thereby // register so that it is restored as sp register on exit, thereby
// popping the args. // popping the args.
@ -298,6 +308,17 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
// ip = sp + kPointerSize * #args; // ip = sp + kPointerSize * #args;
add(ip, sp, Operand(r0, LSL, kPointerSizeLog2)); add(ip, sp, Operand(r0, LSL, kPointerSizeLog2));
// Align the stack at this point. After this point we have 5 pushes,
// so in fact we have to unalign here! See also the assert on the
// alignment immediately below.
if (OS::ActivationFrameAlignment() != kPointerSize) {
// This code needs to be made more general if this assert doesn't hold.
ASSERT(OS::ActivationFrameAlignment() == 2 * kPointerSize);
mov(r7, Operand(Smi::FromInt(0)));
tst(sp, Operand(OS::ActivationFrameAlignment() - 1));
push(r7, eq); // Conditional push instruction.
}
// Push in reverse order: caller_fp, sp_on_exit, and caller_pc. // Push in reverse order: caller_fp, sp_on_exit, and caller_pc.
stm(db_w, sp, fp.bit() | ip.bit() | lr.bit()); stm(db_w, sp, fp.bit() | ip.bit() | lr.bit());
mov(fp, Operand(sp)); // setup new frame pointer mov(fp, Operand(sp)); // setup new frame pointer
@ -316,9 +337,6 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
mov(r4, Operand(r0)); mov(r4, Operand(r0));
mov(r5, Operand(r1)); mov(r5, Operand(r1));
// Compute the argv pointer and keep it in a callee-saved register.
add(r6, fp, Operand(r4, LSL, kPointerSizeLog2));
add(r6, r6, Operand(ExitFrameConstants::kPPDisplacement - kPointerSize));
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
// Save the state of all registers to the stack from the memory // Save the state of all registers to the stack from the memory

3
deps/v8/src/arm/macro-assembler-arm.h

@ -30,7 +30,8 @@
#include "assembler.h" #include "assembler.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// Give alias names to registers // Give alias names to registers

3
deps/v8/src/arm/regexp-macro-assembler-arm.cc

@ -30,7 +30,8 @@
#include "regexp-macro-assembler.h" #include "regexp-macro-assembler.h"
#include "arm/regexp-macro-assembler-arm.h" #include "arm/regexp-macro-assembler-arm.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
RegExpMacroAssemblerARM::RegExpMacroAssemblerARM() { RegExpMacroAssemblerARM::RegExpMacroAssemblerARM() {
UNIMPLEMENTED(); UNIMPLEMENTED();

3
deps/v8/src/arm/regexp-macro-assembler-arm.h

@ -28,7 +28,8 @@
#ifndef V8_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_ #ifndef V8_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_
#define V8_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_ #define V8_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_
namespace v8 { namespace internal { namespace v8 {
namespace internal {
class RegExpMacroAssemblerARM: public RegExpMacroAssembler { class RegExpMacroAssemblerARM: public RegExpMacroAssembler {
public: public:

103
deps/v8/src/arm/register-allocator-arm-inl.h

@ -0,0 +1,103 @@
// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_ARM_REGISTER_ALLOCATOR_ARM_INL_H_
#define V8_ARM_REGISTER_ALLOCATOR_ARM_INL_H_
#include "v8.h"
namespace v8 {
namespace internal {
// -------------------------------------------------------------------------
// RegisterAllocator implementation.
bool RegisterAllocator::IsReserved(Register reg) {
return reg.is(cp) || reg.is(fp) || reg.is(sp) || reg.is(pc);
}
// The register allocator uses small integers to represent the
// non-reserved assembler registers. The mapping is:
//
// r0 <-> 0
// r1 <-> 1
// r2 <-> 2
// r3 <-> 3
// r4 <-> 4
// r5 <-> 5
// r6 <-> 6
// r7 <-> 7
// r9 <-> 8
// r10 <-> 9
// ip <-> 10
// lr <-> 11
int RegisterAllocator::ToNumber(Register reg) {
ASSERT(reg.is_valid() && !IsReserved(reg));
static int numbers[] = {
0, // r0
1, // r1
2, // r2
3, // r3
4, // r4
5, // r5
6, // r6
7, // r7
-1, // cp
8, // r9
9, // r10
-1, // fp
10, // ip
-1, // sp
11, // lr
-1 // pc
};
return numbers[reg.code()];
}
Register RegisterAllocator::ToRegister(int num) {
ASSERT(num >= 0 && num < kNumRegisters);
static Register registers[] =
{ r0, r1, r2, r3, r4, r5, r6, r7, r9, r10, ip, lr };
return registers[num];
}
void RegisterAllocator::Initialize() {
Reset();
// The non-reserved r1 and lr registers are live on JS function entry.
Use(r1); // JS function.
Use(lr); // Return address.
}
} } // namespace v8::internal
#endif // V8_ARM_REGISTER_ALLOCATOR_ARM_INL_H_

55
deps/v8/src/arm/register-allocator-arm.cc

@ -30,7 +30,8 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Result implementation. // Result implementation.
@ -48,56 +49,10 @@ void Result::ToRegister(Register target) {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// RegisterAllocator implementation. // RegisterAllocator implementation.
RegisterFile RegisterAllocator::Reserved() {
RegisterFile reserved;
reserved.Use(sp);
reserved.Use(fp);
reserved.Use(cp);
reserved.Use(pc);
return reserved;
}
void RegisterAllocator::UnuseReserved(RegisterFile* register_file) {
register_file->ref_counts_[sp.code()] = 0;
register_file->ref_counts_[fp.code()] = 0;
register_file->ref_counts_[cp.code()] = 0;
register_file->ref_counts_[pc.code()] = 0;
}
bool RegisterAllocator::IsReserved(int reg_code) {
return (reg_code == sp.code())
|| (reg_code == fp.code())
|| (reg_code == cp.code())
|| (reg_code == pc.code());
}
void RegisterAllocator::Initialize() {
Reset();
// The following registers are live on function entry, saved in the
// frame, and available for allocation during execution.
Use(r1); // JS function.
Use(lr); // Return address.
}
void RegisterAllocator::Reset() {
registers_.Reset();
// The following registers are live on function entry and reserved
// during execution.
Use(sp); // Stack pointer.
Use(fp); // Frame pointer (caller's frame pointer on entry).
Use(cp); // Context context (callee's context on entry).
Use(pc); // Program counter.
}
Result RegisterAllocator::AllocateByteRegisterWithoutSpilling() { Result RegisterAllocator::AllocateByteRegisterWithoutSpilling() {
UNIMPLEMENTED(); // No byte registers on ARM.
Result invalid(cgen_); UNREACHABLE();
return invalid; return Result();
} }

43
deps/v8/src/arm/register-allocator-arm.h

@ -0,0 +1,43 @@
// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_ARM_REGISTER_ALLOCATOR_ARM_H_
#define V8_ARM_REGISTER_ALLOCATOR_ARM_H_
namespace v8 {
namespace internal {
class RegisterAllocatorConstants : public AllStatic {
public:
static const int kNumRegisters = 12;
static const int kInvalidRegister = -1;
};
} } // namespace v8::internal
#endif // V8_ARM_REGISTER_ALLOCATOR_ARM_H_

3
deps/v8/src/arm/simulator-arm.cc

@ -36,7 +36,8 @@
#if !defined(__arm__) #if !defined(__arm__)
// Only build the simulator if not compiling for real ARM hardware. // Only build the simulator if not compiling for real ARM hardware.
namespace assembler { namespace arm { namespace assembler {
namespace arm {
using ::v8::internal::Object; using ::v8::internal::Object;
using ::v8::internal::PrintF; using ::v8::internal::PrintF;

3
deps/v8/src/arm/simulator-arm.h

@ -66,7 +66,8 @@
#include "constants-arm.h" #include "constants-arm.h"
namespace assembler { namespace arm { namespace assembler {
namespace arm {
class Simulator { class Simulator {
public: public:

44
deps/v8/src/arm/stub-cache-arm.cc

@ -1,4 +1,4 @@
// Copyright 2006-2008 the V8 project authors. All rights reserved. // Copyright 2006-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -31,7 +31,8 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "stub-cache.h" #include "stub-cache.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
#define __ ACCESS_MASM(masm) #define __ ACCESS_MASM(masm)
@ -61,7 +62,7 @@ static void ProbeTable(MacroAssembler* masm,
// Check that the flags match what we're looking for. // Check that the flags match what we're looking for.
__ ldr(offset, FieldMemOperand(offset, Code::kFlagsOffset)); __ ldr(offset, FieldMemOperand(offset, Code::kFlagsOffset));
__ and_(offset, offset, Operand(~Code::kFlagsTypeMask)); __ and_(offset, offset, Operand(~Code::kFlagsNotUsedInLookup));
__ cmp(offset, Operand(flags)); __ cmp(offset, Operand(flags));
__ b(ne, &miss); __ b(ne, &miss);
@ -245,6 +246,7 @@ void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm, void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
JSObject* object, JSObject* object,
JSObject* holder, JSObject* holder,
Smi* lookup_hint,
Register receiver, Register receiver,
Register name, Register name,
Register scratch1, Register scratch1,
@ -262,11 +264,13 @@ void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
__ push(receiver); // receiver __ push(receiver); // receiver
__ push(reg); // holder __ push(reg); // holder
__ push(name); // name __ push(name); // name
__ mov(scratch1, Operand(lookup_hint));
__ push(scratch1);
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
ExternalReference load_ic_property = ExternalReference load_ic_property =
ExternalReference(IC_Utility(IC::kLoadInterceptorProperty)); ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
__ TailCallRuntime(load_ic_property, 3); __ TailCallRuntime(load_ic_property, 4);
} }
@ -494,7 +498,9 @@ Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
Object* CallStubCompiler::CompileCallField(Object* object, Object* CallStubCompiler::CompileCallField(Object* object,
JSObject* holder, JSObject* holder,
int index, int index,
String* name) { String* name,
Code::Flags flags) {
ASSERT_EQ(FIELD, Code::ExtractTypeFromFlags(flags));
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- lr: return address // -- lr: return address
// ----------------------------------- // -----------------------------------
@ -538,14 +544,16 @@ Object* CallStubCompiler::CompileCallField(Object* object,
__ Jump(ic, RelocInfo::CODE_TARGET); __ Jump(ic, RelocInfo::CODE_TARGET);
// Return the generated code. // Return the generated code.
return GetCode(FIELD, name); return GetCodeWithFlags(flags, name);
} }
Object* CallStubCompiler::CompileCallConstant(Object* object, Object* CallStubCompiler::CompileCallConstant(Object* object,
JSObject* holder, JSObject* holder,
JSFunction* function, JSFunction* function,
CheckType check) { CheckType check,
Code::Flags flags) {
ASSERT_EQ(CONSTANT_FUNCTION, Code::ExtractTypeFromFlags(flags));
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- lr: return address // -- lr: return address
// ----------------------------------- // -----------------------------------
@ -663,7 +671,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
if (function->shared()->name()->IsString()) { if (function->shared()->name()->IsString()) {
function_name = String::cast(function->shared()->name()); function_name = String::cast(function->shared()->name());
} }
return GetCode(CONSTANT_FUNCTION, function_name); return GetCodeWithFlags(flags, function_name);
} }
@ -904,7 +912,15 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
__ ldr(r0, MemOperand(sp, 0)); __ ldr(r0, MemOperand(sp, 0));
GenerateLoadInterceptor(masm(), object, holder, r0, r2, r3, r1, &miss); GenerateLoadInterceptor(masm(),
object,
holder,
holder->InterceptorPropertyLookupHint(name),
r0,
r2,
r3,
r1,
&miss);
__ bind(&miss); __ bind(&miss);
GenerateLoadMiss(masm(), Code::LOAD_IC); GenerateLoadMiss(masm(), Code::LOAD_IC);
@ -1010,7 +1026,15 @@ Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
__ cmp(r2, Operand(Handle<String>(name))); __ cmp(r2, Operand(Handle<String>(name)));
__ b(ne, &miss); __ b(ne, &miss);
GenerateLoadInterceptor(masm(), receiver, holder, r0, r2, r3, r1, &miss); GenerateLoadInterceptor(masm(),
receiver,
holder,
Smi::FromInt(JSObject::kLookupInHolder),
r0,
r2,
r3,
r1,
&miss);
__ bind(&miss); __ bind(&miss);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);

77
deps/v8/src/arm/virtual-frame-arm.cc

@ -31,31 +31,25 @@
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "scopes.h" #include "scopes.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// VirtualFrame implementation. // VirtualFrame implementation.
#define __ ACCESS_MASM(masm_) #define __ ACCESS_MASM(masm())
// On entry to a function, the virtual frame already contains the // On entry to a function, the virtual frame already contains the
// receiver and the parameters. All initial frame elements are in // receiver and the parameters. All initial frame elements are in
// memory. // memory.
VirtualFrame::VirtualFrame(CodeGenerator* cgen) VirtualFrame::VirtualFrame()
: cgen_(cgen), : elements_(parameter_count() + local_count() + kPreallocatedElements),
masm_(cgen->masm()), stack_pointer_(parameter_count()) { // 0-based index of TOS.
elements_(cgen->scope()->num_parameters() for (int i = 0; i <= stack_pointer_; i++) {
+ cgen->scope()->num_stack_slots()
+ kPreallocatedElements),
parameter_count_(cgen->scope()->num_parameters()),
local_count_(0),
stack_pointer_(parameter_count_), // 0-based index of TOS.
frame_pointer_(kIllegalIndex) {
for (int i = 0; i < parameter_count_ + 1; i++) {
elements_.Add(FrameElement::MemoryElement()); elements_.Add(FrameElement::MemoryElement());
} }
for (int i = 0; i < kNumRegisters; i++) { for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
register_locations_[i] = kIllegalIndex; register_locations_[i] = kIllegalIndex;
} }
} }
@ -82,10 +76,10 @@ void VirtualFrame::SyncRange(int begin, int end) {
void VirtualFrame::MergeTo(VirtualFrame* expected) { void VirtualFrame::MergeTo(VirtualFrame* expected) {
Comment cmnt(masm_, "[ Merge frame"); Comment cmnt(masm(), "[ Merge frame");
// We should always be merging the code generator's current frame to an // We should always be merging the code generator's current frame to an
// expected frame. // expected frame.
ASSERT(cgen_->frame() == this); ASSERT(cgen()->frame() == this);
// Adjust the stack pointer upward (toward the top of the virtual // Adjust the stack pointer upward (toward the top of the virtual
// frame) if necessary. // frame) if necessary.
@ -102,7 +96,7 @@ void VirtualFrame::MergeTo(VirtualFrame* expected) {
// Fix any sync bit problems from the bottom-up, stopping when we // Fix any sync bit problems from the bottom-up, stopping when we
// hit the stack pointer or the top of the frame if the stack // hit the stack pointer or the top of the frame if the stack
// pointer is floating above the frame. // pointer is floating above the frame.
int limit = Min(stack_pointer_, elements_.length() - 1); int limit = Min(static_cast<int>(stack_pointer_), element_count() - 1);
for (int i = 0; i <= limit; i++) { for (int i = 0; i <= limit; i++) {
FrameElement source = elements_[i]; FrameElement source = elements_[i];
FrameElement target = expected->elements_[i]; FrameElement target = expected->elements_[i];
@ -134,7 +128,7 @@ void VirtualFrame::MergeMoveRegistersToMemory(VirtualFrame* expected) {
// On ARM, all elements are in memory. // On ARM, all elements are in memory.
#ifdef DEBUG #ifdef DEBUG
int start = Min(stack_pointer_, elements_.length() - 1); int start = Min(static_cast<int>(stack_pointer_), element_count() - 1);
for (int i = start; i >= 0; i--) { for (int i = start; i >= 0; i--) {
ASSERT(elements_[i].is_memory()); ASSERT(elements_[i].is_memory());
ASSERT(expected->elements_[i].is_memory()); ASSERT(expected->elements_[i].is_memory());
@ -147,12 +141,12 @@ void VirtualFrame::MergeMoveRegistersToRegisters(VirtualFrame* expected) {
} }
void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame *expected) { void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame* expected) {
} }
void VirtualFrame::Enter() { void VirtualFrame::Enter() {
Comment cmnt(masm_, "[ Enter JS frame"); Comment cmnt(masm(), "[ Enter JS frame");
#ifdef DEBUG #ifdef DEBUG
// Verify that r1 contains a JS function. The following code relies // Verify that r1 contains a JS function. The following code relies
@ -175,15 +169,14 @@ void VirtualFrame::Enter() {
Adjust(4); Adjust(4);
__ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
// Adjust FP to point to saved FP. // Adjust FP to point to saved FP.
frame_pointer_ = elements_.length() - 2;
__ add(fp, sp, Operand(2 * kPointerSize)); __ add(fp, sp, Operand(2 * kPointerSize));
cgen_->allocator()->Unuse(r1); cgen()->allocator()->Unuse(r1);
cgen_->allocator()->Unuse(lr); cgen()->allocator()->Unuse(lr);
} }
void VirtualFrame::Exit() { void VirtualFrame::Exit() {
Comment cmnt(masm_, "[ Exit JS frame"); Comment cmnt(masm(), "[ Exit JS frame");
// Drop the execution stack down to the frame pointer and restore the caller // Drop the execution stack down to the frame pointer and restore the caller
// frame pointer and return address. // frame pointer and return address.
__ mov(sp, fp); __ mov(sp, fp);
@ -191,12 +184,11 @@ void VirtualFrame::Exit() {
} }
void VirtualFrame::AllocateStackSlots(int count) { void VirtualFrame::AllocateStackSlots() {
ASSERT(height() == 0); int count = local_count();
local_count_ = count;
Adjust(count);
if (count > 0) { if (count > 0) {
Comment cmnt(masm_, "[ Allocate space for locals"); Comment cmnt(masm(), "[ Allocate space for locals");
Adjust(count);
// Initialize stack slots with 'undefined' value. // Initialize stack slots with 'undefined' value.
__ mov(ip, Operand(Factory::undefined_value())); __ mov(ip, Operand(Factory::undefined_value()));
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
@ -246,9 +238,9 @@ void VirtualFrame::PushTryHandler(HandlerType type) {
Result VirtualFrame::RawCallStub(CodeStub* stub) { Result VirtualFrame::RawCallStub(CodeStub* stub) {
ASSERT(cgen_->HasValidEntryRegisters()); ASSERT(cgen()->HasValidEntryRegisters());
__ CallStub(stub); __ CallStub(stub);
Result result = cgen_->allocator()->Allocate(r0); Result result = cgen()->allocator()->Allocate(r0);
ASSERT(result.is_valid()); ASSERT(result.is_valid());
return result; return result;
} }
@ -271,9 +263,9 @@ Result VirtualFrame::CallStub(CodeStub* stub, Result* arg0, Result* arg1) {
Result VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) { Result VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) {
PrepareForCall(arg_count, arg_count); PrepareForCall(arg_count, arg_count);
ASSERT(cgen_->HasValidEntryRegisters()); ASSERT(cgen()->HasValidEntryRegisters());
__ CallRuntime(f, arg_count); __ CallRuntime(f, arg_count);
Result result = cgen_->allocator()->Allocate(r0); Result result = cgen()->allocator()->Allocate(r0);
ASSERT(result.is_valid()); ASSERT(result.is_valid());
return result; return result;
} }
@ -281,9 +273,9 @@ Result VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) {
Result VirtualFrame::CallRuntime(Runtime::FunctionId id, int arg_count) { Result VirtualFrame::CallRuntime(Runtime::FunctionId id, int arg_count) {
PrepareForCall(arg_count, arg_count); PrepareForCall(arg_count, arg_count);
ASSERT(cgen_->HasValidEntryRegisters()); ASSERT(cgen()->HasValidEntryRegisters());
__ CallRuntime(id, arg_count); __ CallRuntime(id, arg_count);
Result result = cgen_->allocator()->Allocate(r0); Result result = cgen()->allocator()->Allocate(r0);
ASSERT(result.is_valid()); ASSERT(result.is_valid());
return result; return result;
} }
@ -297,16 +289,16 @@ Result VirtualFrame::InvokeBuiltin(Builtins::JavaScript id,
PrepareForCall(arg_count, arg_count); PrepareForCall(arg_count, arg_count);
arg_count_register->Unuse(); arg_count_register->Unuse();
__ InvokeBuiltin(id, flags); __ InvokeBuiltin(id, flags);
Result result = cgen_->allocator()->Allocate(r0); Result result = cgen()->allocator()->Allocate(r0);
return result; return result;
} }
Result VirtualFrame::RawCallCodeObject(Handle<Code> code, Result VirtualFrame::RawCallCodeObject(Handle<Code> code,
RelocInfo::Mode rmode) { RelocInfo::Mode rmode) {
ASSERT(cgen_->HasValidEntryRegisters()); ASSERT(cgen()->HasValidEntryRegisters());
__ Call(code, rmode); __ Call(code, rmode);
Result result = cgen_->allocator()->Allocate(r0); Result result = cgen()->allocator()->Allocate(r0);
ASSERT(result.is_valid()); ASSERT(result.is_valid());
return result; return result;
} }
@ -401,7 +393,7 @@ Result VirtualFrame::CallCodeObject(Handle<Code> code,
void VirtualFrame::Drop(int count) { void VirtualFrame::Drop(int count) {
ASSERT(height() >= count); ASSERT(height() >= count);
int num_virtual_elements = (elements_.length() - 1) - stack_pointer_; int num_virtual_elements = (element_count() - 1) - stack_pointer_;
// Emit code to lower the stack pointer if necessary. // Emit code to lower the stack pointer if necessary.
if (num_virtual_elements < count) { if (num_virtual_elements < count) {
@ -422,13 +414,12 @@ void VirtualFrame::Drop(int count) {
Result VirtualFrame::Pop() { Result VirtualFrame::Pop() {
UNIMPLEMENTED(); UNIMPLEMENTED();
Result invalid(cgen_); return Result();
return invalid;
} }
void VirtualFrame::EmitPop(Register reg) { void VirtualFrame::EmitPop(Register reg) {
ASSERT(stack_pointer_ == elements_.length() - 1); ASSERT(stack_pointer_ == element_count() - 1);
stack_pointer_--; stack_pointer_--;
elements_.RemoveLast(); elements_.RemoveLast();
__ pop(reg); __ pop(reg);
@ -436,7 +427,7 @@ void VirtualFrame::EmitPop(Register reg) {
void VirtualFrame::EmitPush(Register reg) { void VirtualFrame::EmitPush(Register reg) {
ASSERT(stack_pointer_ == elements_.length() - 1); ASSERT(stack_pointer_ == element_count() - 1);
elements_.Add(FrameElement::MemoryElement()); elements_.Add(FrameElement::MemoryElement());
stack_pointer_++; stack_pointer_++;
__ push(reg); __ push(reg);

198
deps/v8/src/arm/virtual-frame-arm.h

@ -29,8 +29,10 @@
#define V8_ARM_VIRTUAL_FRAME_ARM_H_ #define V8_ARM_VIRTUAL_FRAME_ARM_H_
#include "register-allocator.h" #include "register-allocator.h"
#include "scopes.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Virtual frames // Virtual frames
@ -41,7 +43,7 @@ namespace v8 { namespace internal {
// as random access to the expression stack elements, locals, and // as random access to the expression stack elements, locals, and
// parameters. // parameters.
class VirtualFrame : public Malloced { class VirtualFrame : public ZoneObject {
public: public:
// A utility class to introduce a scope where the virtual frame is // A utility class to introduce a scope where the virtual frame is
// expected to remain spilled. The constructor spills the code // expected to remain spilled. The constructor spills the code
@ -50,42 +52,66 @@ class VirtualFrame : public Malloced {
// generator is being transformed. // generator is being transformed.
class SpilledScope BASE_EMBEDDED { class SpilledScope BASE_EMBEDDED {
public: public:
explicit SpilledScope(CodeGenerator* cgen); SpilledScope() : previous_state_(cgen()->in_spilled_code()) {
ASSERT(cgen()->has_valid_frame());
cgen()->frame()->SpillAll();
cgen()->set_in_spilled_code(true);
}
~SpilledScope(); ~SpilledScope() {
cgen()->set_in_spilled_code(previous_state_);
}
private: private:
CodeGenerator* cgen_;
bool previous_state_; bool previous_state_;
CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
}; };
// An illegal index into the virtual frame. // An illegal index into the virtual frame.
static const int kIllegalIndex = -1; static const int kIllegalIndex = -1;
// Construct an initial virtual frame on entry to a JS function. // Construct an initial virtual frame on entry to a JS function.
explicit VirtualFrame(CodeGenerator* cgen); VirtualFrame();
// Construct a virtual frame as a clone of an existing one. // Construct a virtual frame as a clone of an existing one.
explicit VirtualFrame(VirtualFrame* original); explicit VirtualFrame(VirtualFrame* original);
CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
MacroAssembler* masm() { return cgen()->masm(); }
// Create a duplicate of an existing valid frame element. // Create a duplicate of an existing valid frame element.
FrameElement CopyElementAt(int index); FrameElement CopyElementAt(int index);
// The number of elements on the virtual frame.
int element_count() { return elements_.length(); }
// The height of the virtual expression stack. // The height of the virtual expression stack.
int height() const { int height() {
return elements_.length() - expression_base_index(); return element_count() - expression_base_index();
}
int register_location(int num) {
ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters);
return register_locations_[num];
}
int register_location(Register reg) {
return register_locations_[RegisterAllocator::ToNumber(reg)];
} }
int register_index(Register reg) { void set_register_location(Register reg, int index) {
return register_locations_[reg.code()]; register_locations_[RegisterAllocator::ToNumber(reg)] = index;
} }
bool is_used(int reg_code) { bool is_used(int num) {
return register_locations_[reg_code] != kIllegalIndex; ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters);
return register_locations_[num] != kIllegalIndex;
} }
bool is_used(Register reg) { bool is_used(Register reg) {
return is_used(reg.code()); return register_locations_[RegisterAllocator::ToNumber(reg)]
!= kIllegalIndex;
} }
// Add extra in-memory elements to the top of the frame to match an actual // Add extra in-memory elements to the top of the frame to match an actual
@ -95,7 +121,12 @@ class VirtualFrame : public Malloced {
// Forget elements from the top of the frame to match an actual frame (eg, // Forget elements from the top of the frame to match an actual frame (eg,
// the frame after a runtime call). No code is emitted. // the frame after a runtime call). No code is emitted.
void Forget(int count); void Forget(int count) {
ASSERT(count >= 0);
ASSERT(stack_pointer_ == element_count() - 1);
stack_pointer_ -= count;
ForgetElements(count);
}
// Forget count elements from the top of the frame without adjusting // Forget count elements from the top of the frame without adjusting
// the stack pointer downward. This is used, for example, before // the stack pointer downward. This is used, for example, before
@ -106,7 +137,9 @@ class VirtualFrame : public Malloced {
void SpillAll(); void SpillAll();
// Spill all occurrences of a specific register from the frame. // Spill all occurrences of a specific register from the frame.
void Spill(Register reg); void Spill(Register reg) {
if (is_used(reg)) SpillElementAt(register_location(reg));
}
// Spill all occurrences of an arbitrary register if possible. Return the // Spill all occurrences of an arbitrary register if possible. Return the
// register spilled or no_reg if it was not possible to free any register // register spilled or no_reg if it was not possible to free any register
@ -127,13 +160,23 @@ class VirtualFrame : public Malloced {
// tells the register allocator that it is free to use frame-internal // tells the register allocator that it is free to use frame-internal
// registers. Used when the code generator's frame is switched from this // registers. Used when the code generator's frame is switched from this
// one to NULL by an unconditional jump. // one to NULL by an unconditional jump.
void DetachFromCodeGenerator(); void DetachFromCodeGenerator() {
RegisterAllocator* cgen_allocator = cgen()->allocator();
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
if (is_used(i)) cgen_allocator->Unuse(i);
}
}
// (Re)attach a frame to its code generator. This informs the register // (Re)attach a frame to its code generator. This informs the register
// allocator that the frame-internal register references are active again. // allocator that the frame-internal register references are active again.
// Used when a code generator's frame is switched from NULL to this one by // Used when a code generator's frame is switched from NULL to this one by
// binding a label. // binding a label.
void AttachToCodeGenerator(); void AttachToCodeGenerator() {
RegisterAllocator* cgen_allocator = cgen()->allocator();
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
if (is_used(i)) cgen_allocator->Unuse(i);
}
}
// Emit code for the physical JS entry and exit frame sequences. After // Emit code for the physical JS entry and exit frame sequences. After
// calling Enter, the virtual frame is ready for use; and after calling // calling Enter, the virtual frame is ready for use; and after calling
@ -149,13 +192,13 @@ class VirtualFrame : public Malloced {
void PrepareForReturn(); void PrepareForReturn();
// Allocate and initialize the frame-allocated locals. // Allocate and initialize the frame-allocated locals.
void AllocateStackSlots(int count); void AllocateStackSlots();
// The current top of the expression stack as an assembly operand. // The current top of the expression stack as an assembly operand.
MemOperand Top() const { return MemOperand(sp, 0); } MemOperand Top() { return MemOperand(sp, 0); }
// An element of the expression stack as an assembly operand. // An element of the expression stack as an assembly operand.
MemOperand ElementAt(int index) const { MemOperand ElementAt(int index) {
return MemOperand(sp, index * kPointerSize); return MemOperand(sp, index * kPointerSize);
} }
@ -165,18 +208,18 @@ class VirtualFrame : public Malloced {
// Set a frame element to a constant. The index is frame-top relative. // Set a frame element to a constant. The index is frame-top relative.
void SetElementAt(int index, Handle<Object> value) { void SetElementAt(int index, Handle<Object> value) {
Result temp(value, cgen_); Result temp(value);
SetElementAt(index, &temp); SetElementAt(index, &temp);
} }
void PushElementAt(int index) { void PushElementAt(int index) {
PushFrameSlotAt(elements_.length() - index - 1); PushFrameSlotAt(element_count() - index - 1);
} }
// A frame-allocated local as an assembly operand. // A frame-allocated local as an assembly operand.
MemOperand LocalAt(int index) const { MemOperand LocalAt(int index) {
ASSERT(0 <= index); ASSERT(0 <= index);
ASSERT(index < local_count_); ASSERT(index < local_count());
return MemOperand(fp, kLocal0Offset - index * kPointerSize); return MemOperand(fp, kLocal0Offset - index * kPointerSize);
} }
@ -202,13 +245,13 @@ class VirtualFrame : public Malloced {
void PushReceiverSlotAddress(); void PushReceiverSlotAddress();
// The function frame slot. // The function frame slot.
MemOperand Function() const { return MemOperand(fp, kFunctionOffset); } MemOperand Function() { return MemOperand(fp, kFunctionOffset); }
// Push the function on top of the frame. // Push the function on top of the frame.
void PushFunction() { PushFrameSlotAt(function_index()); } void PushFunction() { PushFrameSlotAt(function_index()); }
// The context frame slot. // The context frame slot.
MemOperand Context() const { return MemOperand(fp, kContextOffset); } MemOperand Context() { return MemOperand(fp, kContextOffset); }
// Save the value of the esi register to the context frame slot. // Save the value of the esi register to the context frame slot.
void SaveContextRegister(); void SaveContextRegister();
@ -218,10 +261,11 @@ class VirtualFrame : public Malloced {
void RestoreContextRegister(); void RestoreContextRegister();
// A parameter as an assembly operand. // A parameter as an assembly operand.
MemOperand ParameterAt(int index) const { MemOperand ParameterAt(int index) {
// Index -1 corresponds to the receiver. // Index -1 corresponds to the receiver.
ASSERT(-1 <= index && index <= parameter_count_); ASSERT(-1 <= index); // -1 is the receiver.
return MemOperand(fp, (1 + parameter_count_ - index) * kPointerSize); ASSERT(index <= parameter_count());
return MemOperand(fp, (1 + parameter_count() - index) * kPointerSize);
} }
// Push a copy of the value of a parameter frame slot on top of the frame. // Push a copy of the value of a parameter frame slot on top of the frame.
@ -243,14 +287,17 @@ class VirtualFrame : public Malloced {
} }
// The receiver frame slot. // The receiver frame slot.
MemOperand Receiver() const { return ParameterAt(-1); } MemOperand Receiver() { return ParameterAt(-1); }
// Push a try-catch or try-finally handler on top of the virtual frame. // Push a try-catch or try-finally handler on top of the virtual frame.
void PushTryHandler(HandlerType type); void PushTryHandler(HandlerType type);
// Call stub given the number of arguments it expects on (and // Call stub given the number of arguments it expects on (and
// removes from) the stack. // removes from) the stack.
Result CallStub(CodeStub* stub, int arg_count); Result CallStub(CodeStub* stub, int arg_count) {
PrepareForCall(arg_count, arg_count);
return RawCallStub(stub);
}
// Call stub that expects its argument in r0. The argument is given // Call stub that expects its argument in r0. The argument is given
// as a result which must be the register r0. // as a result which must be the register r0.
@ -297,7 +344,7 @@ class VirtualFrame : public Malloced {
void Drop() { Drop(1); } void Drop() { Drop(1); }
// Duplicate the top element of the frame. // Duplicate the top element of the frame.
void Dup() { PushFrameSlotAt(elements_.length() - 1); } void Dup() { PushFrameSlotAt(element_count() - 1); }
// Pop an element from the top of the expression stack. Returns a // Pop an element from the top of the expression stack. Returns a
// Result, which may be a constant or a register. // Result, which may be a constant or a register.
@ -317,7 +364,15 @@ class VirtualFrame : public Malloced {
void Push(Smi* value) { Push(Handle<Object>(value)); } void Push(Smi* value) { Push(Handle<Object>(value)); }
// Pushing a result invalidates it (its contents become owned by the frame). // Pushing a result invalidates it (its contents become owned by the frame).
void Push(Result* result); void Push(Result* result) {
if (result->is_register()) {
Push(result->reg(), result->static_type());
} else {
ASSERT(result->is_constant());
Push(result->handle());
}
result->Unuse();
}
// Nip removes zero or more elements from immediately below the top // Nip removes zero or more elements from immediately below the top
// of the frame, leaving the previous top-of-frame value on top of // of the frame, leaving the previous top-of-frame value on top of
@ -332,70 +387,69 @@ class VirtualFrame : public Malloced {
static const int kHandlerSize = StackHandlerConstants::kSize / kPointerSize; static const int kHandlerSize = StackHandlerConstants::kSize / kPointerSize;
static const int kPreallocatedElements = 5 + 8; // 8 expression stack slots. static const int kPreallocatedElements = 5 + 8; // 8 expression stack slots.
CodeGenerator* cgen_; ZoneList<FrameElement> elements_;
MacroAssembler* masm_;
List<FrameElement> elements_;
// The number of frame-allocated locals and parameters respectively.
int parameter_count_;
int local_count_;
// The index of the element that is at the processor's stack pointer // The index of the element that is at the processor's stack pointer
// (the sp register). // (the sp register).
int stack_pointer_; int stack_pointer_;
// The index of the element that is at the processor's frame pointer
// (the fp register).
int frame_pointer_;
// The index of the register frame element using each register, or // The index of the register frame element using each register, or
// kIllegalIndex if a register is not on the frame. // kIllegalIndex if a register is not on the frame.
int register_locations_[kNumRegisters]; int register_locations_[RegisterAllocator::kNumRegisters];
// The number of frame-allocated locals and parameters respectively.
int parameter_count() { return cgen()->scope()->num_parameters(); }
int local_count() { return cgen()->scope()->num_stack_slots(); }
// The index of the element that is at the processor's frame pointer
// (the fp register). The parameters, receiver, function, and context
// are below the frame pointer.
int frame_pointer() { return parameter_count() + 3; }
// The index of the first parameter. The receiver lies below the first // The index of the first parameter. The receiver lies below the first
// parameter. // parameter.
int param0_index() const { return 1; } int param0_index() { return 1; }
// The index of the context slot in the frame. // The index of the context slot in the frame. It is immediately
int context_index() const { // below the frame pointer.
ASSERT(frame_pointer_ != kIllegalIndex); int context_index() { return frame_pointer() - 1; }
return frame_pointer_ - 1;
}
// The index of the function slot in the frame. It lies above the context // The index of the function slot in the frame. It is below the frame
// slot. // pointer and context slot.
int function_index() const { int function_index() { return frame_pointer() - 2; }
ASSERT(frame_pointer_ != kIllegalIndex);
return frame_pointer_ - 2;
}
// The index of the first local. Between the parameters and the locals // The index of the first local. Between the frame pointer and the
// lie the return address, the saved frame pointer, the context, and the // locals lies the return address.
// function. int local0_index() { return frame_pointer() + 2; }
int local0_index() const {
ASSERT(frame_pointer_ != kIllegalIndex);
return frame_pointer_ + 2;
}
// The index of the base of the expression stack. // The index of the base of the expression stack.
int expression_base_index() const { return local0_index() + local_count_; } int expression_base_index() { return local0_index() + local_count(); }
// Convert a frame index into a frame pointer relative offset into the // Convert a frame index into a frame pointer relative offset into the
// actual stack. // actual stack.
int fp_relative(int index) const { int fp_relative(int index) {
return (frame_pointer_ - index) * kPointerSize; ASSERT(index < element_count());
ASSERT(frame_pointer() < element_count()); // FP is on the frame.
return (frame_pointer() - index) * kPointerSize;
} }
// Record an occurrence of a register in the virtual frame. This has the // Record an occurrence of a register in the virtual frame. This has the
// effect of incrementing the register's external reference count and // effect of incrementing the register's external reference count and
// of updating the index of the register's location in the frame. // of updating the index of the register's location in the frame.
void Use(Register reg, int index); void Use(Register reg, int index) {
ASSERT(!is_used(reg));
set_register_location(reg, index);
cgen()->allocator()->Use(reg);
}
// Record that a register reference has been dropped from the frame. This // Record that a register reference has been dropped from the frame. This
// decrements the register's external reference count and invalidates the // decrements the register's external reference count and invalidates the
// index of the register's location in the frame. // index of the register's location in the frame.
void Unuse(Register reg); void Unuse(Register reg) {
ASSERT(is_used(reg));
set_register_location(reg, kIllegalIndex);
cgen()->allocator()->Unuse(reg);
}
// Spill the element at a particular index---write it to memory if // Spill the element at a particular index---write it to memory if
// necessary, free any associated register, and forget its value if // necessary, free any associated register, and forget its value if
@ -407,7 +461,7 @@ class VirtualFrame : public Malloced {
// Keep the element type as register or constant, and clear the dirty bit. // Keep the element type as register or constant, and clear the dirty bit.
void SyncElementAt(int index); void SyncElementAt(int index);
// Sync the range of elements in [begin, end). // Sync the range of elements in [begin, end] with memory.
void SyncRange(int begin, int end); void SyncRange(int begin, int end);
// Sync a single unsynced element that lies beneath or at the stack pointer. // Sync a single unsynced element that lies beneath or at the stack pointer.
@ -471,6 +525,8 @@ class VirtualFrame : public Malloced {
bool Equals(VirtualFrame* other); bool Equals(VirtualFrame* other);
// Classes that need raw access to the elements_ array.
friend class DeferredCode;
friend class JumpTarget; friend class JumpTarget;
}; };

33
deps/v8/src/assembler.cc

@ -43,7 +43,8 @@
#include "stub-cache.h" #include "stub-cache.h"
#include "regexp-stack.h" #include "regexp-stack.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -90,13 +91,13 @@ int Label::pos() const {
// bits, the lowest 7 bits written first. // bits, the lowest 7 bits written first.
// //
// data-jump + pos: 00 1110 11, // data-jump + pos: 00 1110 11,
// signed int, lowest byte written first // signed intptr_t, lowest byte written first
// //
// data-jump + st.pos: 01 1110 11, // data-jump + st.pos: 01 1110 11,
// signed int, lowest byte written first // signed intptr_t, lowest byte written first
// //
// data-jump + comm.: 10 1110 11, // data-jump + comm.: 10 1110 11,
// signed int, lowest byte written first // signed intptr_t, lowest byte written first
// //
const int kMaxRelocModes = 14; const int kMaxRelocModes = 14;
@ -158,7 +159,7 @@ void RelocInfoWriter::WriteTaggedPC(uint32_t pc_delta, int tag) {
} }
void RelocInfoWriter::WriteTaggedData(int32_t data_delta, int tag) { void RelocInfoWriter::WriteTaggedData(intptr_t data_delta, int tag) {
*--pos_ = data_delta << kPositionTypeTagBits | tag; *--pos_ = data_delta << kPositionTypeTagBits | tag;
} }
@ -178,11 +179,12 @@ void RelocInfoWriter::WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag) {
} }
void RelocInfoWriter::WriteExtraTaggedData(int32_t data_delta, int top_tag) { void RelocInfoWriter::WriteExtraTaggedData(intptr_t data_delta, int top_tag) {
WriteExtraTag(kDataJumpTag, top_tag); WriteExtraTag(kDataJumpTag, top_tag);
for (int i = 0; i < kIntSize; i++) { for (int i = 0; i < kIntptrSize; i++) {
*--pos_ = data_delta; *--pos_ = data_delta;
data_delta = ArithmeticShiftRight(data_delta, kBitsPerByte); // Signed right shift is arithmetic shift. Tested in test-utils.cc.
data_delta = data_delta >> kBitsPerByte;
} }
} }
@ -205,11 +207,13 @@ void RelocInfoWriter::Write(const RelocInfo* rinfo) {
WriteTaggedPC(pc_delta, kCodeTargetTag); WriteTaggedPC(pc_delta, kCodeTargetTag);
} else if (RelocInfo::IsPosition(rmode)) { } else if (RelocInfo::IsPosition(rmode)) {
// Use signed delta-encoding for data. // Use signed delta-encoding for data.
int32_t data_delta = rinfo->data() - last_data_; intptr_t data_delta = rinfo->data() - last_data_;
int pos_type_tag = rmode == RelocInfo::POSITION ? kNonstatementPositionTag int pos_type_tag = rmode == RelocInfo::POSITION ? kNonstatementPositionTag
: kStatementPositionTag; : kStatementPositionTag;
// Check if data is small enough to fit in a tagged byte. // Check if data is small enough to fit in a tagged byte.
if (is_intn(data_delta, kSmallDataBits)) { // We cannot use is_intn because data_delta is not an int32_t.
if (data_delta >= -(1 << (kSmallDataBits-1)) &&
data_delta < 1 << (kSmallDataBits-1)) {
WriteTaggedPC(pc_delta, kPositionTag); WriteTaggedPC(pc_delta, kPositionTag);
WriteTaggedData(data_delta, pos_type_tag); WriteTaggedData(data_delta, pos_type_tag);
last_data_ = rinfo->data(); last_data_ = rinfo->data();
@ -263,9 +267,9 @@ inline void RelocIterator::AdvanceReadPC() {
void RelocIterator::AdvanceReadData() { void RelocIterator::AdvanceReadData() {
int32_t x = 0; intptr_t x = 0;
for (int i = 0; i < kIntSize; i++) { for (int i = 0; i < kIntptrSize; i++) {
x |= *--pos_ << i * kBitsPerByte; x |= static_cast<intptr_t>(*--pos_) << i * kBitsPerByte;
} }
rinfo_.data_ += x; rinfo_.data_ += x;
} }
@ -294,7 +298,8 @@ inline int RelocIterator::GetPositionTypeTag() {
inline void RelocIterator::ReadTaggedData() { inline void RelocIterator::ReadTaggedData() {
int8_t signed_b = *pos_; int8_t signed_b = *pos_;
rinfo_.data_ += ArithmeticShiftRight(signed_b, kPositionTypeTagBits); // Signed right shift is arithmetic shift. Tested in test-utils.cc.
rinfo_.data_ += signed_b >> kPositionTypeTagBits;
} }

11
deps/v8/src/assembler.h

@ -40,7 +40,8 @@
#include "zone-inl.h" #include "zone-inl.h"
#include "token.h" #include "token.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -271,8 +272,8 @@ class RelocInfoWriter BASE_EMBEDDED {
inline uint32_t WriteVariableLengthPCJump(uint32_t pc_delta); inline uint32_t WriteVariableLengthPCJump(uint32_t pc_delta);
inline void WriteTaggedPC(uint32_t pc_delta, int tag); inline void WriteTaggedPC(uint32_t pc_delta, int tag);
inline void WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag); inline void WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag);
inline void WriteExtraTaggedData(int32_t data_delta, int top_tag); inline void WriteExtraTaggedData(intptr_t data_delta, int top_tag);
inline void WriteTaggedData(int32_t data_delta, int tag); inline void WriteTaggedData(intptr_t data_delta, int tag);
inline void WriteExtraTag(int extra_tag, int top_tag); inline void WriteExtraTag(int extra_tag, int top_tag);
byte* pos_; byte* pos_;
@ -423,8 +424,6 @@ class ExternalReference BASE_EMBEDDED {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Utility functions // Utility functions
// Move these into inline file?
static inline bool is_intn(int x, int n) { static inline bool is_intn(int x, int n) {
return -(1 << (n-1)) <= x && x < (1 << (n-1)); return -(1 << (n-1)) <= x && x < (1 << (n-1));
} }
@ -436,9 +435,11 @@ static inline bool is_uintn(int x, int n) {
return (x & -(1 << n)) == 0; return (x & -(1 << n)) == 0;
} }
static inline bool is_uint2(int x) { return is_uintn(x, 2); }
static inline bool is_uint3(int x) { return is_uintn(x, 3); } static inline bool is_uint3(int x) { return is_uintn(x, 3); }
static inline bool is_uint4(int x) { return is_uintn(x, 4); } static inline bool is_uint4(int x) { return is_uintn(x, 4); }
static inline bool is_uint5(int x) { return is_uintn(x, 5); } static inline bool is_uint5(int x) { return is_uintn(x, 5); }
static inline bool is_uint6(int x) { return is_uintn(x, 6); }
static inline bool is_uint8(int x) { return is_uintn(x, 8); } static inline bool is_uint8(int x) { return is_uintn(x, 8); }
static inline bool is_uint12(int x) { return is_uintn(x, 12); } static inline bool is_uint12(int x) { return is_uintn(x, 12); }
static inline bool is_uint16(int x) { return is_uintn(x, 16); } static inline bool is_uint16(int x) { return is_uintn(x, 16); }

3
deps/v8/src/ast.cc

@ -31,7 +31,8 @@
#include "scopes.h" #include "scopes.h"
#include "string-stream.h" #include "string-stream.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
VariableProxySentinel VariableProxySentinel::this_proxy_(true); VariableProxySentinel VariableProxySentinel::this_proxy_(true);

3
deps/v8/src/ast.h

@ -37,7 +37,8 @@
#include "jsregexp.h" #include "jsregexp.h"
#include "jump-target.h" #include "jump-target.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// The abstract syntax tree is an intermediate, light-weight // The abstract syntax tree is an intermediate, light-weight
// representation of the parsed JavaScript code suitable for // representation of the parsed JavaScript code suitable for

80
deps/v8/src/bootstrapper.cc

@ -37,7 +37,8 @@
#include "macro-assembler.h" #include "macro-assembler.h"
#include "natives.h" #include "natives.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// A SourceCodeCache uses a FixedArray to store pairs of // A SourceCodeCache uses a FixedArray to store pairs of
// (AsciiString*, JSFunction*), mapping names of native code files // (AsciiString*, JSFunction*), mapping names of native code files
@ -46,7 +47,7 @@ namespace v8 { namespace internal {
// generate an index for each native JS file. // generate an index for each native JS file.
class SourceCodeCache BASE_EMBEDDED { class SourceCodeCache BASE_EMBEDDED {
public: public:
explicit SourceCodeCache(ScriptType type): type_(type) { } explicit SourceCodeCache(Script::Type type): type_(type) { }
void Initialize(bool create_heap_objects) { void Initialize(bool create_heap_objects) {
if (create_heap_objects) { if (create_heap_objects) {
@ -88,13 +89,13 @@ class SourceCodeCache BASE_EMBEDDED {
} }
private: private:
ScriptType type_; Script::Type type_;
FixedArray* cache_; FixedArray* cache_;
DISALLOW_COPY_AND_ASSIGN(SourceCodeCache); DISALLOW_COPY_AND_ASSIGN(SourceCodeCache);
}; };
static SourceCodeCache natives_cache(SCRIPT_TYPE_NATIVE); static SourceCodeCache natives_cache(Script::TYPE_NATIVE);
static SourceCodeCache extensions_cache(SCRIPT_TYPE_EXTENSION); static SourceCodeCache extensions_cache(Script::TYPE_EXTENSION);
Handle<String> Bootstrapper::NativesSourceLookup(int index) { Handle<String> Bootstrapper::NativesSourceLookup(int index) {
@ -521,7 +522,7 @@ void Genesis::CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,
empty_function->set_code(*code); empty_function->set_code(*code);
Handle<String> source = Factory::NewStringFromAscii(CStrVector("() {}")); Handle<String> source = Factory::NewStringFromAscii(CStrVector("() {}"));
Handle<Script> script = Factory::NewScript(source); Handle<Script> script = Factory::NewScript(source);
script->set_type(Smi::FromInt(SCRIPT_TYPE_NATIVE)); script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
empty_function->shared()->set_script(*script); empty_function->shared()->set_script(*script);
empty_function->shared()->set_start_position(0); empty_function->shared()->set_start_position(0);
empty_function->shared()->set_end_position(source->length()); empty_function->shared()->set_end_position(source->length());
@ -820,14 +821,28 @@ void Genesis::CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,
global_context()->set_context_extension_function(*context_extension_fun); global_context()->set_context_extension_function(*context_extension_fun);
} }
// Setup the call-as-function delegate.
Handle<Code> code = {
Handle<Code>(Builtins::builtin(Builtins::HandleApiCallAsFunction)); // Setup the call-as-function delegate.
Handle<JSFunction> delegate = Handle<Code> code =
Factory::NewFunction(Factory::empty_symbol(), JS_OBJECT_TYPE, Handle<Code>(Builtins::builtin(Builtins::HandleApiCallAsFunction));
JSObject::kHeaderSize, code, true); Handle<JSFunction> delegate =
global_context()->set_call_as_function_delegate(*delegate); Factory::NewFunction(Factory::empty_symbol(), JS_OBJECT_TYPE,
delegate->shared()->DontAdaptArguments(); JSObject::kHeaderSize, code, true);
global_context()->set_call_as_function_delegate(*delegate);
delegate->shared()->DontAdaptArguments();
}
{
// Setup the call-as-constructor delegate.
Handle<Code> code =
Handle<Code>(Builtins::builtin(Builtins::HandleApiCallAsConstructor));
Handle<JSFunction> delegate =
Factory::NewFunction(Factory::empty_symbol(), JS_OBJECT_TYPE,
JSObject::kHeaderSize, code, true);
global_context()->set_call_as_constructor_delegate(*delegate);
delegate->shared()->DontAdaptArguments();
}
global_context()->set_special_function_table(Heap::empty_fixed_array()); global_context()->set_special_function_table(Heap::empty_fixed_array());
@ -1047,6 +1062,14 @@ bool Genesis::InstallNatives() {
Factory::LookupAsciiSymbol("type"), Factory::LookupAsciiSymbol("type"),
proxy_type, proxy_type,
common_attributes); common_attributes);
Handle<Proxy> proxy_compilation_type =
Factory::NewProxy(&Accessors::ScriptCompilationType);
script_descriptors =
Factory::CopyAppendProxyDescriptor(
script_descriptors,
Factory::LookupAsciiSymbol("compilation_type"),
proxy_compilation_type,
common_attributes);
Handle<Proxy> proxy_line_ends = Handle<Proxy> proxy_line_ends =
Factory::NewProxy(&Accessors::ScriptLineEnds); Factory::NewProxy(&Accessors::ScriptLineEnds);
script_descriptors = script_descriptors =
@ -1063,16 +1086,38 @@ bool Genesis::InstallNatives() {
Factory::LookupAsciiSymbol("context_data"), Factory::LookupAsciiSymbol("context_data"),
proxy_context_data, proxy_context_data,
common_attributes); common_attributes);
Handle<Proxy> proxy_eval_from_function =
Factory::NewProxy(&Accessors::ScriptEvalFromFunction);
script_descriptors =
Factory::CopyAppendProxyDescriptor(
script_descriptors,
Factory::LookupAsciiSymbol("eval_from_function"),
proxy_eval_from_function,
common_attributes);
Handle<Proxy> proxy_eval_from_position =
Factory::NewProxy(&Accessors::ScriptEvalFromPosition);
script_descriptors =
Factory::CopyAppendProxyDescriptor(
script_descriptors,
Factory::LookupAsciiSymbol("eval_from_position"),
proxy_eval_from_position,
common_attributes);
Handle<Map> script_map = Handle<Map>(script_fun->initial_map()); Handle<Map> script_map = Handle<Map>(script_fun->initial_map());
script_map->set_instance_descriptors(*script_descriptors); script_map->set_instance_descriptors(*script_descriptors);
// Allocate the empty script. // Allocate the empty script.
Handle<Script> script = Factory::NewScript(Factory::empty_string()); Handle<Script> script = Factory::NewScript(Factory::empty_string());
script->set_type(Smi::FromInt(SCRIPT_TYPE_NATIVE)); script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
global_context()->set_empty_script(*script); global_context()->set_empty_script(*script);
} }
#ifdef V8_HOST_ARCH_64_BIT
// TODO(X64): Reenable remaining initialization when code generation works.
return true;
#endif // V8_HOST_ARCH_64_BIT
if (FLAG_natives_file == NULL) { if (FLAG_natives_file == NULL) {
// Without natives file, install default natives. // Without natives file, install default natives.
for (int i = Natives::GetDelayCount(); for (int i = Natives::GetDelayCount();
@ -1509,8 +1554,8 @@ Genesis::Genesis(Handle<Object> global_object,
current_ = this; current_ = this;
result_ = NULL; result_ = NULL;
// If V8 hasn't been and cannot be initialized, just return. // If V8 isn't running and cannot be initialized, just return.
if (!V8::HasBeenSetup() && !V8::Initialize(NULL)) return; if (!V8::IsRunning() && !V8::Initialize(NULL)) return;
// Before creating the roots we must save the context and restore it // Before creating the roots we must save the context and restore it
// on all function exits. // on all function exits.
@ -1518,6 +1563,7 @@ Genesis::Genesis(Handle<Object> global_object,
SaveContext context; SaveContext context;
CreateRoots(global_template, global_object); CreateRoots(global_template, global_object);
if (!InstallNatives()) return; if (!InstallNatives()) return;
MakeFunctionInstancePrototypeWritable(); MakeFunctionInstancePrototypeWritable();

3
deps/v8/src/bootstrapper.h

@ -29,7 +29,8 @@
#ifndef V8_BOOTSTRAPPER_H_ #ifndef V8_BOOTSTRAPPER_H_
#define V8_BOOTSTRAPPER_H_ #define V8_BOOTSTRAPPER_H_
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// The Boostrapper is the public interface for creating a JavaScript global // The Boostrapper is the public interface for creating a JavaScript global
// context. // context.

46
deps/v8/src/builtins.cc

@ -32,7 +32,8 @@
#include "builtins.h" #include "builtins.h"
#include "ic-inl.h" #include "ic-inl.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Support macros for defining builtins in C. // Support macros for defining builtins in C.
@ -394,12 +395,18 @@ BUILTIN(HandleApiCall) {
BUILTIN_END BUILTIN_END
// Handle calls to non-function objects created through the API that // Helper function to handle calls to non-function objects created through the
// support calls. // API. The object can be called as either a constructor (using new) or just as
BUILTIN(HandleApiCallAsFunction) { // a function (without new).
// Non-functions are never called as constructors. static Object* HandleApiCallAsFunctionOrConstructor(bool is_construct_call,
int __argc__,
Object** __argv__) {
// Non-functions are never called as constructors. Even if this is an object
// called as a constructor the delegate call is not a construct call.
ASSERT(!CalledAsConstructor()); ASSERT(!CalledAsConstructor());
Handle<Object> receiver(&__argv__[0]);
// Get the object called. // Get the object called.
JSObject* obj = JSObject::cast(*receiver); JSObject* obj = JSObject::cast(*receiver);
@ -431,7 +438,7 @@ BUILTIN(HandleApiCallAsFunction) {
data, data,
self, self,
callee, callee,
false, is_construct_call,
reinterpret_cast<void**>(__argv__ - 1), reinterpret_cast<void**>(__argv__ - 1),
__argc__ - 1); __argc__ - 1);
v8::Handle<v8::Value> value; v8::Handle<v8::Value> value;
@ -450,6 +457,21 @@ BUILTIN(HandleApiCallAsFunction) {
RETURN_IF_SCHEDULED_EXCEPTION(); RETURN_IF_SCHEDULED_EXCEPTION();
return result; return result;
} }
// Handle calls to non-function objects created through the API. This delegate
// function is used when the call is a normal function call.
BUILTIN(HandleApiCallAsFunction) {
return HandleApiCallAsFunctionOrConstructor(false, __argc__, __argv__);
}
BUILTIN_END
// Handle calls to non-function objects created through the API. This delegate
// function is used when the call is a construct call.
BUILTIN(HandleApiCallAsConstructor) {
return HandleApiCallAsFunctionOrConstructor(true, __argc__, __argv__);
}
BUILTIN_END BUILTIN_END
@ -644,12 +666,12 @@ void Builtins::Setup(bool create_heap_objects) {
Code::ComputeFlags(Code::BUILTIN) \ Code::ComputeFlags(Code::BUILTIN) \
}, },
#define DEF_FUNCTION_PTR_A(name, kind, state) \ #define DEF_FUNCTION_PTR_A(name, kind, state) \
{ FUNCTION_ADDR(Generate_##name), \ { FUNCTION_ADDR(Generate_##name), \
NULL, \ NULL, \
#name, \ #name, \
name, \ name, \
Code::ComputeFlags(Code::kind, state) \ Code::ComputeFlags(Code::kind, NOT_IN_LOOP, state) \
}, },
// Define array of pointers to generators and C builtin functions. // Define array of pointers to generators and C builtin functions.

65
deps/v8/src/builtins.h

@ -28,7 +28,8 @@
#ifndef V8_BUILTINS_H_ #ifndef V8_BUILTINS_H_
#define V8_BUILTINS_H_ #define V8_BUILTINS_H_
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// Define list of builtins implemented in C. // Define list of builtins implemented in C.
#define BUILTIN_LIST_C(V) \ #define BUILTIN_LIST_C(V) \
@ -42,7 +43,8 @@ namespace v8 { namespace internal {
V(ArrayPop) \ V(ArrayPop) \
\ \
V(HandleApiCall) \ V(HandleApiCall) \
V(HandleApiCallAsFunction) V(HandleApiCallAsFunction) \
V(HandleApiCallAsConstructor)
// Define list of builtins implemented in assembly. // Define list of builtins implemented in assembly.
@ -99,35 +101,36 @@ namespace v8 { namespace internal {
#endif #endif
// Define list of builtins implemented in JavaScript. // Define list of builtins implemented in JavaScript.
#define BUILTINS_LIST_JS(V) \ #define BUILTINS_LIST_JS(V) \
V(EQUALS, 1) \ V(EQUALS, 1) \
V(STRICT_EQUALS, 1) \ V(STRICT_EQUALS, 1) \
V(COMPARE, 2) \ V(COMPARE, 2) \
V(ADD, 1) \ V(ADD, 1) \
V(SUB, 1) \ V(SUB, 1) \
V(MUL, 1) \ V(MUL, 1) \
V(DIV, 1) \ V(DIV, 1) \
V(MOD, 1) \ V(MOD, 1) \
V(BIT_OR, 1) \ V(BIT_OR, 1) \
V(BIT_AND, 1) \ V(BIT_AND, 1) \
V(BIT_XOR, 1) \ V(BIT_XOR, 1) \
V(UNARY_MINUS, 0) \ V(UNARY_MINUS, 0) \
V(BIT_NOT, 0) \ V(BIT_NOT, 0) \
V(SHL, 1) \ V(SHL, 1) \
V(SAR, 1) \ V(SAR, 1) \
V(SHR, 1) \ V(SHR, 1) \
V(DELETE, 1) \ V(DELETE, 1) \
V(IN, 1) \ V(IN, 1) \
V(INSTANCE_OF, 1) \ V(INSTANCE_OF, 1) \
V(GET_KEYS, 0) \ V(GET_KEYS, 0) \
V(FILTER_KEY, 1) \ V(FILTER_KEY, 1) \
V(CALL_NON_FUNCTION, 0) \ V(CALL_NON_FUNCTION, 0) \
V(TO_OBJECT, 0) \ V(CALL_NON_FUNCTION_AS_CONSTRUCTOR, 0) \
V(TO_NUMBER, 0) \ V(TO_OBJECT, 0) \
V(TO_STRING, 0) \ V(TO_NUMBER, 0) \
V(STRING_ADD_LEFT, 1) \ V(TO_STRING, 0) \
V(STRING_ADD_RIGHT, 1) \ V(STRING_ADD_LEFT, 1) \
V(APPLY_PREPARE, 1) \ V(STRING_ADD_RIGHT, 1) \
V(APPLY_PREPARE, 1) \
V(APPLY_OVERFLOW, 1) V(APPLY_OVERFLOW, 1)

3
deps/v8/src/bytecodes-irregexp.h

@ -29,7 +29,8 @@
#ifndef V8_BYTECODES_IRREGEXP_H_ #ifndef V8_BYTECODES_IRREGEXP_H_
#define V8_BYTECODES_IRREGEXP_H_ #define V8_BYTECODES_IRREGEXP_H_
namespace v8 { namespace internal { namespace v8 {
namespace internal {
static const int BYTECODE_MASK = 0xff; static const int BYTECODE_MASK = 0xff;

3
deps/v8/src/char-predicates-inl.h

@ -30,7 +30,8 @@
#include "char-predicates.h" #include "char-predicates.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
inline bool IsCarriageReturn(uc32 c) { inline bool IsCarriageReturn(uc32 c) {

3
deps/v8/src/char-predicates.h

@ -28,7 +28,8 @@
#ifndef V8_CHAR_PREDICATES_H_ #ifndef V8_CHAR_PREDICATES_H_
#define V8_CHAR_PREDICATES_H_ #define V8_CHAR_PREDICATES_H_
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// Unicode character predicates as defined by ECMA-262, 3rd, // Unicode character predicates as defined by ECMA-262, 3rd,
// used for lexical analysis. // used for lexical analysis.

5
deps/v8/src/code-stubs.cc

@ -32,7 +32,8 @@
#include "factory.h" #include "factory.h"
#include "macro-assembler.h" #include "macro-assembler.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
Handle<Code> CodeStub::GetCode() { Handle<Code> CodeStub::GetCode() {
uint32_t key = GetKey(); uint32_t key = GetKey();
@ -58,7 +59,7 @@ Handle<Code> CodeStub::GetCode() {
masm.GetCode(&desc); masm.GetCode(&desc);
// Copy the generated code into a heap object, and store the major key. // Copy the generated code into a heap object, and store the major key.
Code::Flags flags = Code::ComputeFlags(Code::STUB); Code::Flags flags = Code::ComputeFlags(Code::STUB, InLoop());
Handle<Code> code = Factory::NewCode(desc, NULL, flags, masm.CodeObject()); Handle<Code> code = Factory::NewCode(desc, NULL, flags, masm.CodeObject());
code->set_major_key(MajorKey()); code->set_major_key(MajorKey());

7
deps/v8/src/code-stubs.h

@ -28,7 +28,8 @@
#ifndef V8_CODE_STUBS_H_ #ifndef V8_CODE_STUBS_H_
#define V8_CODE_STUBS_H_ #define V8_CODE_STUBS_H_
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// Stub is base classes of all stubs. // Stub is base classes of all stubs.
@ -82,6 +83,10 @@ class CodeStub BASE_EMBEDDED {
virtual Major MajorKey() = 0; virtual Major MajorKey() = 0;
virtual int MinorKey() = 0; virtual int MinorKey() = 0;
// The CallFunctionStub needs to override this so it can encode whether a
// lazily generated function should be fully optimized or not.
virtual InLoopFlag InLoop() { return NOT_IN_LOOP; }
// Returns a name for logging/debugging purposes. // Returns a name for logging/debugging purposes.
virtual const char* GetName() { return MajorName(MajorKey()); } virtual const char* GetName() { return MajorName(MajorKey()); }

3
deps/v8/src/code.h

@ -28,7 +28,8 @@
#ifndef V8_CODE_H_ #ifndef V8_CODE_H_
#define V8_CODE_H_ #define V8_CODE_H_
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// Wrapper class for passing expected and actual parameter counts as // Wrapper class for passing expected and actual parameter counts as

27
deps/v8/src/codegen-inl.h

@ -30,9 +30,23 @@
#define V8_CODEGEN_INL_H_ #define V8_CODEGEN_INL_H_
#include "codegen.h" #include "codegen.h"
#include "register-allocator-inl.h"
#if V8_TARGET_ARCH_IA32
#include "ia32/codegen-ia32-inl.h"
#elif V8_TARGET_ARCH_X64
#include "x64/codegen-x64-inl.h"
#elif V8_TARGET_ARCH_ARM
#include "arm/codegen-arm-inl.h"
#else
#error Unsupported target architecture.
#endif
namespace v8 { namespace internal { namespace v8 {
namespace internal {
#define __ ACCESS_MASM(masm_)
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Support for "structured" code comments. // Support for "structured" code comments.
@ -44,15 +58,12 @@ namespace v8 { namespace internal {
class Comment BASE_EMBEDDED { class Comment BASE_EMBEDDED {
public: public:
Comment(MacroAssembler* masm, const char* msg) Comment(MacroAssembler* masm, const char* msg) : masm_(masm), msg_(msg) {
: masm_(masm), __ RecordComment(msg);
msg_(msg) {
masm_->RecordComment(msg);
} }
~Comment() { ~Comment() {
if (msg_[0] == '[') if (msg_[0] == '[') __ RecordComment("]");
masm_->RecordComment("]");
} }
private: private:
@ -69,6 +80,8 @@ class Comment BASE_EMBEDDED {
#endif // DEBUG #endif // DEBUG
#undef __
} } // namespace v8::internal } } // namespace v8::internal

98
deps/v8/src/codegen.cc

@ -38,27 +38,41 @@
#include "scopeinfo.h" #include "scopeinfo.h"
#include "stub-cache.h" #include "stub-cache.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
DeferredCode::DeferredCode(CodeGenerator* generator)
: generator_(generator),
masm_(generator->masm()), CodeGenerator* CodeGeneratorScope::top_ = NULL;
enter_(generator),
exit_(generator, JumpTarget::BIDIRECTIONAL),
statement_position_(masm_->current_statement_position()), DeferredCode::DeferredCode()
position_(masm_->current_position()) { : masm_(CodeGeneratorScope::Current()->masm()),
generator->AddDeferred(this); statement_position_(masm_->current_statement_position()),
position_(masm_->current_position()) {
ASSERT(statement_position_ != RelocInfo::kNoPosition); ASSERT(statement_position_ != RelocInfo::kNoPosition);
ASSERT(position_ != RelocInfo::kNoPosition); ASSERT(position_ != RelocInfo::kNoPosition);
CodeGeneratorScope::Current()->AddDeferred(this);
#ifdef DEBUG #ifdef DEBUG
comment_ = ""; comment_ = "";
#endif #endif
}
void CodeGenerator::ClearDeferred() { // Copy the register locations from the code generator's frame.
for (int i = 0; i < deferred_.length(); i++) { // These are the registers that will be spilled on entry to the
deferred_[i]->Clear(); // deferred code and restored on exit.
VirtualFrame* frame = CodeGeneratorScope::Current()->frame();
int sp_offset = frame->fp_relative(frame->stack_pointer_);
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
int loc = frame->register_location(i);
if (loc == VirtualFrame::kIllegalIndex) {
registers_[i] = kIgnore;
} else if (frame->elements_[loc].is_synced()) {
// Needs to be restored on exit but not saved on entry.
registers_[i] = frame->fp_relative(loc) | kSyncedFlag;
} else {
int offset = frame->fp_relative(loc);
registers_[i] = (offset < sp_offset) ? kPush : offset;
}
} }
} }
@ -66,17 +80,19 @@ void CodeGenerator::ClearDeferred() {
void CodeGenerator::ProcessDeferred() { void CodeGenerator::ProcessDeferred() {
while (!deferred_.is_empty()) { while (!deferred_.is_empty()) {
DeferredCode* code = deferred_.RemoveLast(); DeferredCode* code = deferred_.RemoveLast();
MacroAssembler* masm = code->masm(); ASSERT(masm_ == code->masm());
// Record position of deferred code stub. // Record position of deferred code stub.
masm->RecordStatementPosition(code->statement_position()); masm_->RecordStatementPosition(code->statement_position());
if (code->position() != RelocInfo::kNoPosition) { if (code->position() != RelocInfo::kNoPosition) {
masm->RecordPosition(code->position()); masm_->RecordPosition(code->position());
} }
// Generate the code. // Generate the code.
Comment cmnt(masm, code->comment()); Comment cmnt(masm_, code->comment());
masm_->bind(code->entry_label());
code->SaveRegisters();
code->Generate(); code->Generate();
ASSERT(code->enter()->is_bound()); code->RestoreRegisters();
code->Clear(); masm_->jmp(code->exit_label());
} }
} }
@ -104,7 +120,6 @@ void CodeGenerator::SetFrame(VirtualFrame* new_frame,
void CodeGenerator::DeleteFrame() { void CodeGenerator::DeleteFrame() {
if (has_valid_frame()) { if (has_valid_frame()) {
frame_->DetachFromCodeGenerator(); frame_->DetachFromCodeGenerator();
delete frame_;
frame_ = NULL; frame_ = NULL;
} }
} }
@ -155,17 +170,21 @@ Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* flit,
// Generate code. // Generate code.
const int initial_buffer_size = 4 * KB; const int initial_buffer_size = 4 * KB;
CodeGenerator cgen(initial_buffer_size, script, is_eval); CodeGenerator cgen(initial_buffer_size, script, is_eval);
CodeGeneratorScope scope(&cgen);
cgen.GenCode(flit); cgen.GenCode(flit);
if (cgen.HasStackOverflow()) { if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception()); ASSERT(!Top::has_pending_exception());
return Handle<Code>::null(); return Handle<Code>::null();
} }
// Allocate and install the code. // Allocate and install the code. Time the rest of this function as
// code creation.
HistogramTimerScope timer(&Counters::code_creation);
CodeDesc desc; CodeDesc desc;
cgen.masm()->GetCode(&desc); cgen.masm()->GetCode(&desc);
ScopeInfo<> sinfo(flit->scope()); ZoneScopeInfo sinfo(flit->scope());
Code::Flags flags = Code::ComputeFlags(Code::FUNCTION); InLoopFlag in_loop = (cgen.loop_nesting() != 0) ? IN_LOOP : NOT_IN_LOOP;
Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop);
Handle<Code> code = Factory::NewCode(desc, Handle<Code> code = Factory::NewCode(desc,
&sinfo, &sinfo,
flags, flags,
@ -206,7 +225,7 @@ Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* flit,
bool CodeGenerator::ShouldGenerateLog(Expression* type) { bool CodeGenerator::ShouldGenerateLog(Expression* type) {
ASSERT(type != NULL); ASSERT(type != NULL);
if (!Logger::is_enabled()) return false; if (!Logger::IsEnabled()) return false;
Handle<String> name = Handle<String>::cast(type->AsLiteral()->handle()); Handle<String> name = Handle<String>::cast(type->AsLiteral()->handle());
if (FLAG_log_regexp) { if (FLAG_log_regexp) {
static Vector<const char> kRegexp = CStrVector("regexp"); static Vector<const char> kRegexp = CStrVector("regexp");
@ -317,17 +336,18 @@ Handle<JSFunction> CodeGenerator::BuildBoilerplate(FunctionLiteral* node) {
} }
Handle<Code> CodeGenerator::ComputeCallInitialize(int argc) { Handle<Code> CodeGenerator::ComputeCallInitialize(
CALL_HEAP_FUNCTION(StubCache::ComputeCallInitialize(argc), Code); int argc,
} InLoopFlag in_loop) {
if (in_loop == IN_LOOP) {
// Force the creation of the corresponding stub outside loops,
Handle<Code> CodeGenerator::ComputeCallInitializeInLoop(int argc) { // because it may be used when clearing the ICs later - it is
// Force the creation of the corresponding stub outside loops, // possible for a series of IC transitions to lose the in-loop
// because it will be used when clearing the ICs later - when we // information, and the IC clearing code can't generate a stub
// don't know if we're inside a loop or not. // that it needs so we need to ensure it is generated already.
ComputeCallInitialize(argc); ComputeCallInitialize(argc, NOT_IN_LOOP);
CALL_HEAP_FUNCTION(StubCache::ComputeCallInitializeInLoop(argc), Code); }
CALL_HEAP_FUNCTION(StubCache::ComputeCallInitialize(argc, in_loop), Code);
} }
@ -507,8 +527,8 @@ void CodeGenerator::GenerateFastCaseSwitchCases(
// frame. Otherwise, we have to merge the existing one to the // frame. Otherwise, we have to merge the existing one to the
// start frame as part of the previous case. // start frame as part of the previous case.
if (!has_valid_frame()) { if (!has_valid_frame()) {
RegisterFile non_frame_registers = RegisterAllocator::Reserved(); RegisterFile empty;
SetFrame(new VirtualFrame(start_frame), &non_frame_registers); SetFrame(new VirtualFrame(start_frame), &empty);
} else { } else {
frame_->MergeTo(start_frame); frame_->MergeTo(start_frame);
} }

89
deps/v8/src/codegen.h

@ -52,7 +52,6 @@
// CodeGenerator // CodeGenerator
// ~CodeGenerator // ~CodeGenerator
// ProcessDeferred // ProcessDeferred
// ClearDeferred
// GenCode // GenCode
// BuildBoilerplate // BuildBoilerplate
// ComputeCallInitialize // ComputeCallInitialize
@ -86,14 +85,34 @@ enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
#include "arm/codegen-arm.h" #include "arm/codegen-arm.h"
#endif #endif
namespace v8 { namespace internal { #include "register-allocator.h"
namespace v8 {
namespace internal {
// Use lazy compilation; defaults to true.
// NOTE: Do not remove non-lazy compilation until we can properly // Code generation can be nested. Code generation scopes form a stack
// install extensions with lazy compilation enabled. At the // of active code generators.
// moment, this doesn't work for the extensions in Google3, class CodeGeneratorScope BASE_EMBEDDED {
// and we can only run the tests with --nolazy. public:
explicit CodeGeneratorScope(CodeGenerator* cgen) {
previous_ = top_;
top_ = cgen;
}
~CodeGeneratorScope() {
top_ = previous_;
}
static CodeGenerator* Current() {
ASSERT(top_ != NULL);
return top_;
}
private:
static CodeGenerator* top_;
CodeGenerator* previous_;
};
// Deferred code objects are small pieces of code that are compiled // Deferred code objects are small pieces of code that are compiled
@ -101,52 +120,56 @@ namespace v8 { namespace internal {
// paths thereby avoiding expensive jumps around uncommon code parts. // paths thereby avoiding expensive jumps around uncommon code parts.
class DeferredCode: public ZoneObject { class DeferredCode: public ZoneObject {
public: public:
explicit DeferredCode(CodeGenerator* generator); DeferredCode();
virtual ~DeferredCode() { } virtual ~DeferredCode() { }
virtual void Generate() = 0; virtual void Generate() = 0;
// Unuse the entry and exit targets, deallocating all virtual frames MacroAssembler* masm() { return masm_; }
// held by them. It will be impossible to emit a (correct) jump
// into or out of the deferred code after clearing.
void Clear() {
enter_.Unuse();
exit_.Unuse();
}
MacroAssembler* masm() const { return masm_; }
CodeGenerator* generator() const { return generator_; }
JumpTarget* enter() { return &enter_; }
void BindExit() { exit_.Bind(0); }
void BindExit(Result* result) { exit_.Bind(result, 1); }
void BindExit(Result* result0, Result* result1) {
exit_.Bind(result0, result1, 2);
}
void BindExit(Result* result0, Result* result1, Result* result2) {
exit_.Bind(result0, result1, result2, 3);
}
int statement_position() const { return statement_position_; } int statement_position() const { return statement_position_; }
int position() const { return position_; } int position() const { return position_; }
Label* entry_label() { return &entry_label_; }
Label* exit_label() { return &exit_label_; }
#ifdef DEBUG #ifdef DEBUG
void set_comment(const char* comment) { comment_ = comment; } void set_comment(const char* comment) { comment_ = comment; }
const char* comment() const { return comment_; } const char* comment() const { return comment_; }
#else #else
inline void set_comment(const char* comment) { } void set_comment(const char* comment) { }
const char* comment() const { return ""; } const char* comment() const { return ""; }
#endif #endif
inline void Jump();
inline void Branch(Condition cc);
void BindExit() { masm_->bind(&exit_label_); }
void SaveRegisters();
void RestoreRegisters();
protected: protected:
CodeGenerator* const generator_; MacroAssembler* masm_;
MacroAssembler* const masm_;
JumpTarget enter_;
JumpTarget exit_;
private: private:
// Constants indicating special actions. They should not be multiples
// of kPointerSize so they will not collide with valid offsets from
// the frame pointer.
static const int kIgnore = -1;
static const int kPush = 1;
// This flag is ored with a valid offset from the frame pointer, so
// it should fit in the low zero bits of a valid offset.
static const int kSyncedFlag = 2;
int statement_position_; int statement_position_;
int position_; int position_;
Label entry_label_;
Label exit_label_;
int registers_[RegisterAllocator::kNumRegisters];
#ifdef DEBUG #ifdef DEBUG
const char* comment_; const char* comment_;
#endif #endif

159
deps/v8/src/compilation-cache.cc

@ -29,15 +29,30 @@
#include "compilation-cache.h" #include "compilation-cache.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
enum { enum {
NUMBER_OF_ENTRY_KINDS = CompilationCache::LAST_ENTRY + 1 // The number of script generations tell how many GCs a script can
// survive in the compilation cache, before it will be flushed if it
// hasn't been used.
NUMBER_OF_SCRIPT_GENERATIONS = 5,
// The compilation cache consists of tables - one for each entry
// kind plus extras for the script generations.
NUMBER_OF_TABLE_ENTRIES =
CompilationCache::LAST_ENTRY + NUMBER_OF_SCRIPT_GENERATIONS
}; };
// Current enable state of the compilation cache.
static bool enabled = true;
static inline bool IsEnabled() {
return FLAG_compilation_cache && enabled;
}
// Keep separate tables for the different entry kinds. // Keep separate tables for the different entry kinds.
static Object* tables[NUMBER_OF_ENTRY_KINDS] = { 0, }; static Object* tables[NUMBER_OF_TABLE_ENTRIES] = { 0, };
static Handle<CompilationCacheTable> AllocateTable(int size) { static Handle<CompilationCacheTable> AllocateTable(int size) {
@ -46,14 +61,15 @@ static Handle<CompilationCacheTable> AllocateTable(int size) {
} }
static Handle<CompilationCacheTable> GetTable(CompilationCache::Entry entry) { static Handle<CompilationCacheTable> GetTable(int index) {
ASSERT(index >= 0 && index < NUMBER_OF_TABLE_ENTRIES);
Handle<CompilationCacheTable> result; Handle<CompilationCacheTable> result;
if (tables[entry]->IsUndefined()) { if (tables[index]->IsUndefined()) {
static const int kInitialCacheSize = 64; static const int kInitialCacheSize = 64;
result = AllocateTable(kInitialCacheSize); result = AllocateTable(kInitialCacheSize);
tables[entry] = *result; tables[index] = *result;
} else { } else {
CompilationCacheTable* table = CompilationCacheTable::cast(tables[entry]); CompilationCacheTable* table = CompilationCacheTable::cast(tables[index]);
result = Handle<CompilationCacheTable>(table); result = Handle<CompilationCacheTable>(table);
} }
return result; return result;
@ -121,47 +137,80 @@ static bool HasOrigin(Handle<JSFunction> boilerplate,
} }
static Handle<JSFunction> Lookup(Handle<String> source, // TODO(245): Need to allow identical code from different contexts to
CompilationCache::Entry entry) { // be cached in the same script generation. Currently the first use
// Make sure not to leak the table into the surrounding handle // will be cached, but subsequent code from different source / line
// scope. Otherwise, we risk keeping old tables around even after // won't.
// having cleared the cache.
Object* result;
{ HandleScope scope;
Handle<CompilationCacheTable> table = GetTable(entry);
result = table->Lookup(*source);
}
if (result->IsJSFunction()) {
return Handle<JSFunction>(JSFunction::cast(result));
} else {
return Handle<JSFunction>::null();
}
}
// TODO(245): Need to allow identical code from different contexts to be
// cached. Currently the first use will be cached, but subsequent code
// from different source / line won't.
Handle<JSFunction> CompilationCache::LookupScript(Handle<String> source, Handle<JSFunction> CompilationCache::LookupScript(Handle<String> source,
Handle<Object> name, Handle<Object> name,
int line_offset, int line_offset,
int column_offset) { int column_offset) {
Handle<JSFunction> result = Lookup(source, SCRIPT); if (!IsEnabled()) {
if (result.is_null()) { return Handle<JSFunction>::null();
Counters::compilation_cache_misses.Increment(); }
} else if (HasOrigin(result, name, line_offset, column_offset)) {
// Use an int for the generation index, so value range propagation
// in gcc 4.3+ won't assume it can only go up to LAST_ENTRY when in
// fact it can go up to SCRIPT + NUMBER_OF_SCRIPT_GENERATIONS.
int generation = SCRIPT;
Object* result = NULL;
// Probe the script generation tables. Make sure not to leak handles
// into the caller's handle scope.
{ HandleScope scope;
while (generation < SCRIPT + NUMBER_OF_SCRIPT_GENERATIONS) {
Handle<CompilationCacheTable> table = GetTable(generation);
Handle<Object> probe(table->Lookup(*source));
if (probe->IsJSFunction()) {
Handle<JSFunction> boilerplate = Handle<JSFunction>::cast(probe);
// Break when we've found a suitable boilerplate function that
// matches the origin.
if (HasOrigin(boilerplate, name, line_offset, column_offset)) {
result = *boilerplate;
break;
}
}
// Go to the next generation.
generation++;
}
}
static void* script_histogram = StatsTable::CreateHistogram(
"V8.ScriptCache",
0,
NUMBER_OF_SCRIPT_GENERATIONS,
NUMBER_OF_SCRIPT_GENERATIONS + 1);
if (script_histogram != NULL) {
// The level NUMBER_OF_SCRIPT_GENERATIONS is equivalent to a cache miss.
StatsTable::AddHistogramSample(script_histogram, generation - SCRIPT);
}
// Once outside the manacles of the handle scope, we need to recheck
// to see if we actually found a cached script. If so, we return a
// handle created in the caller's handle scope.
if (result != NULL) {
Handle<JSFunction> boilerplate(JSFunction::cast(result));
ASSERT(HasOrigin(boilerplate, name, line_offset, column_offset));
// If the script was found in a later generation, we promote it to
// the first generation to let it survive longer in the cache.
if (generation != SCRIPT) PutScript(source, boilerplate);
Counters::compilation_cache_hits.Increment(); Counters::compilation_cache_hits.Increment();
return boilerplate;
} else { } else {
result = Handle<JSFunction>::null();
Counters::compilation_cache_misses.Increment(); Counters::compilation_cache_misses.Increment();
return Handle<JSFunction>::null();
} }
return result;
} }
Handle<JSFunction> CompilationCache::LookupEval(Handle<String> source, Handle<JSFunction> CompilationCache::LookupEval(Handle<String> source,
Handle<Context> context, Handle<Context> context,
Entry entry) { Entry entry) {
if (!IsEnabled()) {
return Handle<JSFunction>::null();
}
ASSERT(entry == EVAL_GLOBAL || entry == EVAL_CONTEXTUAL); ASSERT(entry == EVAL_GLOBAL || entry == EVAL_CONTEXTUAL);
Handle<JSFunction> result = Lookup(source, context, entry); Handle<JSFunction> result = Lookup(source, context, entry);
if (result.is_null()) { if (result.is_null()) {
@ -175,6 +224,10 @@ Handle<JSFunction> CompilationCache::LookupEval(Handle<String> source,
Handle<FixedArray> CompilationCache::LookupRegExp(Handle<String> source, Handle<FixedArray> CompilationCache::LookupRegExp(Handle<String> source,
JSRegExp::Flags flags) { JSRegExp::Flags flags) {
if (!IsEnabled()) {
return Handle<FixedArray>::null();
}
Handle<FixedArray> result = Lookup(source, flags); Handle<FixedArray> result = Lookup(source, flags);
if (result.is_null()) { if (result.is_null()) {
Counters::compilation_cache_misses.Increment(); Counters::compilation_cache_misses.Increment();
@ -187,6 +240,10 @@ Handle<FixedArray> CompilationCache::LookupRegExp(Handle<String> source,
void CompilationCache::PutScript(Handle<String> source, void CompilationCache::PutScript(Handle<String> source,
Handle<JSFunction> boilerplate) { Handle<JSFunction> boilerplate) {
if (!IsEnabled()) {
return;
}
HandleScope scope; HandleScope scope;
ASSERT(boilerplate->IsBoilerplate()); ASSERT(boilerplate->IsBoilerplate());
Handle<CompilationCacheTable> table = GetTable(SCRIPT); Handle<CompilationCacheTable> table = GetTable(SCRIPT);
@ -198,6 +255,10 @@ void CompilationCache::PutEval(Handle<String> source,
Handle<Context> context, Handle<Context> context,
Entry entry, Entry entry,
Handle<JSFunction> boilerplate) { Handle<JSFunction> boilerplate) {
if (!IsEnabled()) {
return;
}
HandleScope scope; HandleScope scope;
ASSERT(boilerplate->IsBoilerplate()); ASSERT(boilerplate->IsBoilerplate());
Handle<CompilationCacheTable> table = GetTable(entry); Handle<CompilationCacheTable> table = GetTable(entry);
@ -209,6 +270,10 @@ void CompilationCache::PutEval(Handle<String> source,
void CompilationCache::PutRegExp(Handle<String> source, void CompilationCache::PutRegExp(Handle<String> source,
JSRegExp::Flags flags, JSRegExp::Flags flags,
Handle<FixedArray> data) { Handle<FixedArray> data) {
if (!IsEnabled()) {
return;
}
HandleScope scope; HandleScope scope;
Handle<CompilationCacheTable> table = GetTable(REGEXP); Handle<CompilationCacheTable> table = GetTable(REGEXP);
CALL_HEAP_FUNCTION_VOID(table->PutRegExp(*source, flags, *data)); CALL_HEAP_FUNCTION_VOID(table->PutRegExp(*source, flags, *data));
@ -216,14 +281,36 @@ void CompilationCache::PutRegExp(Handle<String> source,
void CompilationCache::Clear() { void CompilationCache::Clear() {
for (int i = 0; i < NUMBER_OF_ENTRY_KINDS; i++) { for (int i = 0; i < NUMBER_OF_TABLE_ENTRIES; i++) {
tables[i] = Heap::undefined_value(); tables[i] = Heap::undefined_value();
} }
} }
void CompilationCache::Iterate(ObjectVisitor* v) { void CompilationCache::Iterate(ObjectVisitor* v) {
v->VisitPointers(&tables[0], &tables[NUMBER_OF_ENTRY_KINDS]); v->VisitPointers(&tables[0], &tables[NUMBER_OF_TABLE_ENTRIES]);
}
void CompilationCache::MarkCompactPrologue() {
ASSERT(LAST_ENTRY == SCRIPT);
for (int i = NUMBER_OF_TABLE_ENTRIES - 1; i > SCRIPT; i--) {
tables[i] = tables[i - 1];
}
for (int j = 0; j <= LAST_ENTRY; j++) {
tables[j] = Heap::undefined_value();
}
}
void CompilationCache::Enable() {
enabled = true;
}
void CompilationCache::Disable() {
enabled = false;
Clear();
} }

18
deps/v8/src/compilation-cache.h

@ -28,7 +28,8 @@
#ifndef V8_COMPILATION_CACHE_H_ #ifndef V8_COMPILATION_CACHE_H_
#define V8_COMPILATION_CACHE_H_ #define V8_COMPILATION_CACHE_H_
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// The compilation cache keeps function boilerplates for compiled // The compilation cache keeps function boilerplates for compiled
@ -40,11 +41,11 @@ class CompilationCache {
// scripts and evals. Internally, we use separate caches to avoid // scripts and evals. Internally, we use separate caches to avoid
// getting the wrong kind of entry when looking up. // getting the wrong kind of entry when looking up.
enum Entry { enum Entry {
SCRIPT,
EVAL_GLOBAL, EVAL_GLOBAL,
EVAL_CONTEXTUAL, EVAL_CONTEXTUAL,
REGEXP, REGEXP,
LAST_ENTRY = REGEXP SCRIPT,
LAST_ENTRY = SCRIPT
}; };
// Finds the script function boilerplate for a source // Finds the script function boilerplate for a source
@ -93,10 +94,13 @@ class CompilationCache {
// Notify the cache that a mark-sweep garbage collection is about to // Notify the cache that a mark-sweep garbage collection is about to
// take place. This is used to retire entries from the cache to // take place. This is used to retire entries from the cache to
// avoid keeping them alive too long without using them. For now, we // avoid keeping them alive too long without using them.
// just clear the cache but we should consider are more static void MarkCompactPrologue();
// sophisticated LRU scheme.
static void MarkCompactPrologue() { Clear(); } // Enable/disable compilation cache. Used by debugger to disable compilation
// cache during debugging to make sure new scripts are always compiled.
static void Enable();
static void Disable();
}; };

49
deps/v8/src/compiler.cc

@ -37,7 +37,8 @@
#include "scopes.h" #include "scopes.h"
#include "usage-analyzer.h" #include "usage-analyzer.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
static Handle<Code> MakeCode(FunctionLiteral* literal, static Handle<Code> MakeCode(FunctionLiteral* literal,
Handle<Script> script, Handle<Script> script,
@ -52,12 +53,15 @@ static Handle<Code> MakeCode(FunctionLiteral* literal,
return Handle<Code>::null(); return Handle<Code>::null();
} }
// Compute top scope and allocate variables. For lazy compilation {
// the top scope only contains the single lazily compiled function, // Compute top scope and allocate variables. For lazy compilation
// so this doesn't re-allocate variables repeatedly. // the top scope only contains the single lazily compiled function,
Scope* top = literal->scope(); // so this doesn't re-allocate variables repeatedly.
while (top->outer_scope() != NULL) top = top->outer_scope(); HistogramTimerScope timer(&Counters::variable_allocation);
top->AllocateVariables(context); Scope* top = literal->scope();
while (top->outer_scope() != NULL) top = top->outer_scope();
top->AllocateVariables(context);
}
#ifdef DEBUG #ifdef DEBUG
if (Bootstrapper::IsActive() ? if (Bootstrapper::IsActive() ?
@ -86,7 +90,7 @@ static bool IsValidJSON(FunctionLiteral* lit) {
Statement* stmt = lit->body()->at(0); Statement* stmt = lit->body()->at(0);
if (stmt->AsExpressionStatement() == NULL) if (stmt->AsExpressionStatement() == NULL)
return false; return false;
Expression *expr = stmt->AsExpressionStatement()->expression(); Expression* expr = stmt->AsExpressionStatement()->expression();
return expr->IsValidJSON(); return expr->IsValidJSON();
} }
@ -98,7 +102,7 @@ static Handle<JSFunction> MakeFunction(bool is_global,
Handle<Context> context, Handle<Context> context,
v8::Extension* extension, v8::Extension* extension,
ScriptDataImpl* pre_data) { ScriptDataImpl* pre_data) {
ZoneScope zone_scope(DELETE_ON_EXIT); CompilationZoneScope zone_scope(DELETE_ON_EXIT);
// Make sure we have an initial stack limit. // Make sure we have an initial stack limit.
StackGuard guard; StackGuard guard;
@ -106,7 +110,22 @@ static Handle<JSFunction> MakeFunction(bool is_global,
ASSERT(!i::Top::global_context().is_null()); ASSERT(!i::Top::global_context().is_null());
script->set_context_data((*i::Top::global_context())->data()); script->set_context_data((*i::Top::global_context())->data());
#ifdef ENABLE_DEBUGGER_SUPPORT #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));
// For eval scripts add information on the function from which eval was
// called.
if (is_eval) {
JavaScriptFrameIterator it;
script->set_eval_from_function(it.frame()->function());
int offset = it.frame()->pc() - it.frame()->code()->instruction_start();
script->set_eval_from_instructions_offset(Smi::FromInt(offset));
}
}
// Notify debugger // Notify debugger
Debugger::OnBeforeCompile(script); Debugger::OnBeforeCompile(script);
#endif #endif
@ -156,7 +175,7 @@ static Handle<JSFunction> MakeFunction(bool is_global,
#if defined ENABLE_LOGGING_AND_PROFILING || defined ENABLE_OPROFILE_AGENT #if defined ENABLE_LOGGING_AND_PROFILING || defined ENABLE_OPROFILE_AGENT
// Log the code generation for the script. Check explicit whether logging is // Log the code generation for the script. Check explicit whether logging is
// to avoid allocating when not required. // to avoid allocating when not required.
if (Logger::is_enabled() || OProfileAgent::is_enabled()) { if (Logger::IsEnabled() || OProfileAgent::is_enabled()) {
if (script->name()->IsString()) { if (script->name()->IsString()) {
SmartPointer<char> data = SmartPointer<char> data =
String::cast(script->name())->ToCString(DISALLOW_NULLS); String::cast(script->name())->ToCString(DISALLOW_NULLS);
@ -264,7 +283,6 @@ Handle<JSFunction> Compiler::Compile(Handle<String> source,
Handle<JSFunction> Compiler::CompileEval(Handle<String> source, Handle<JSFunction> Compiler::CompileEval(Handle<String> source,
Handle<Context> context, Handle<Context> context,
int line_offset,
bool is_global, bool is_global,
bool is_json) { bool is_json) {
int source_length = source->length(); int source_length = source->length();
@ -284,7 +302,6 @@ Handle<JSFunction> Compiler::CompileEval(Handle<String> source,
if (result.is_null()) { if (result.is_null()) {
// Create a script object describing the script to be compiled. // Create a script object describing the script to be compiled.
Handle<Script> script = Factory::NewScript(source); Handle<Script> script = Factory::NewScript(source);
script->set_line_offset(Smi::FromInt(line_offset));
result = MakeFunction(is_global, result = MakeFunction(is_global,
true, true,
is_json, is_json,
@ -303,7 +320,7 @@ Handle<JSFunction> Compiler::CompileEval(Handle<String> source,
bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared, bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
int loop_nesting) { int loop_nesting) {
ZoneScope zone_scope(DELETE_ON_EXIT); CompilationZoneScope zone_scope(DELETE_ON_EXIT);
// The VM is in the COMPILER state until exiting this function. // The VM is in the COMPILER state until exiting this function.
VMState state(COMPILER); VMState state(COMPILER);
@ -355,9 +372,9 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
// Log the code generation. If source information is available include script // Log the code generation. If source information is available include script
// name and line number. Check explicit whether logging is enabled as finding // name and line number. Check explicit whether logging is enabled as finding
// the line number is not for free. // the line number is not for free.
if (Logger::is_enabled() || OProfileAgent::is_enabled()) { if (Logger::IsEnabled() || OProfileAgent::is_enabled()) {
Handle<String> func_name(lit->name()->length() > 0 ? Handle<String> func_name(name->length() > 0 ?
*lit->name() : shared->inferred_name()); *name : shared->inferred_name());
if (script->name()->IsString()) { if (script->name()->IsString()) {
int line_num = GetScriptLineNumber(script, start_position); int line_num = GetScriptLineNumber(script, start_position);
if (line_num > 0) { if (line_num > 0) {

22
deps/v8/src/compiler.h

@ -28,9 +28,12 @@
#ifndef V8_COMPILER_H_ #ifndef V8_COMPILER_H_
#define V8_COMPILER_H_ #define V8_COMPILER_H_
#include "frame-element.h"
#include "parser.h" #include "parser.h"
#include "zone.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// The V8 compiler // The V8 compiler
// //
@ -59,7 +62,6 @@ class Compiler : public AllStatic {
// Compile a String source within a context for Eval. // Compile a String source within a context for Eval.
static Handle<JSFunction> CompileEval(Handle<String> source, static Handle<JSFunction> CompileEval(Handle<String> source,
Handle<Context> context, Handle<Context> context,
int line_offset,
bool is_global, bool is_global,
bool is_json); bool is_json);
@ -69,6 +71,22 @@ class Compiler : public AllStatic {
static bool CompileLazy(Handle<SharedFunctionInfo> shared, int loop_nesting); static bool CompileLazy(Handle<SharedFunctionInfo> shared, int loop_nesting);
}; };
// During compilation we need a global list of handles to constants
// for frame elements. When the zone gets deleted, we make sure to
// clear this list of handles as well.
class CompilationZoneScope : public ZoneScope {
public:
explicit CompilationZoneScope(ZoneScopeMode mode) : ZoneScope(mode) { }
virtual ~CompilationZoneScope() {
if (ShouldDeleteOnExit()) {
FrameElement::ClearConstantList();
Result::ClearConstantList();
}
}
};
} } // namespace v8::internal } } // namespace v8::internal
#endif // V8_COMPILER_H_ #endif // V8_COMPILER_H_

3
deps/v8/src/contexts.cc

@ -31,7 +31,8 @@
#include "debug.h" #include "debug.h"
#include "scopeinfo.h" #include "scopeinfo.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
JSBuiltinsObject* Context::builtins() { JSBuiltinsObject* Context::builtins() {
GlobalObject* object = global(); GlobalObject* object = global();

6
deps/v8/src/contexts.h

@ -28,7 +28,8 @@
#ifndef V8_CONTEXTS_H_ #ifndef V8_CONTEXTS_H_
#define V8_CONTEXTS_H_ #define V8_CONTEXTS_H_
namespace v8 { namespace internal { namespace v8 {
namespace internal {
enum ContextLookupFlags { enum ContextLookupFlags {
@ -90,6 +91,8 @@ enum ContextLookupFlags {
V(FUNCTION_CACHE_INDEX, JSObject, function_cache) \ V(FUNCTION_CACHE_INDEX, JSObject, function_cache) \
V(RUNTIME_CONTEXT_INDEX, Context, runtime_context) \ V(RUNTIME_CONTEXT_INDEX, Context, runtime_context) \
V(CALL_AS_FUNCTION_DELEGATE_INDEX, JSFunction, call_as_function_delegate) \ V(CALL_AS_FUNCTION_DELEGATE_INDEX, JSFunction, call_as_function_delegate) \
V(CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, JSFunction, \
call_as_constructor_delegate) \
V(EMPTY_SCRIPT_INDEX, Script, empty_script) \ V(EMPTY_SCRIPT_INDEX, Script, empty_script) \
V(SCRIPT_FUNCTION_INDEX, JSFunction, script_function) \ V(SCRIPT_FUNCTION_INDEX, JSFunction, script_function) \
V(CONTEXT_EXTENSION_FUNCTION_INDEX, JSFunction, context_extension_function) \ V(CONTEXT_EXTENSION_FUNCTION_INDEX, JSFunction, context_extension_function) \
@ -209,6 +212,7 @@ class Context: public FixedArray {
FUNCTION_CACHE_INDEX, FUNCTION_CACHE_INDEX,
RUNTIME_CONTEXT_INDEX, RUNTIME_CONTEXT_INDEX,
CALL_AS_FUNCTION_DELEGATE_INDEX, CALL_AS_FUNCTION_DELEGATE_INDEX,
CALL_AS_CONSTRUCTOR_DELEGATE_INDEX,
EMPTY_SCRIPT_INDEX, EMPTY_SCRIPT_INDEX,
SCRIPT_FUNCTION_INDEX, SCRIPT_FUNCTION_INDEX,
CONTEXT_EXTENSION_FUNCTION_INDEX, CONTEXT_EXTENSION_FUNCTION_INDEX,

3
deps/v8/src/conversions-inl.h

@ -38,7 +38,8 @@
#include "conversions.h" #include "conversions.h"
#include "platform.h" #include "platform.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// The fast double-to-int conversion routine does not guarantee // The fast double-to-int conversion routine does not guarantee
// rounding towards zero. // rounding towards zero.

3
deps/v8/src/conversions.cc

@ -33,7 +33,8 @@
#include "factory.h" #include "factory.h"
#include "scanner.h" #include "scanner.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
int HexValue(uc32 c) { int HexValue(uc32 c) {
if ('0' <= c && c <= '9') if ('0' <= c && c <= '9')

3
deps/v8/src/conversions.h

@ -28,7 +28,8 @@
#ifndef V8_CONVERSIONS_H_ #ifndef V8_CONVERSIONS_H_
#define V8_CONVERSIONS_H_ #define V8_CONVERSIONS_H_
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// The fast double-to-int conversion routine does not guarantee // The fast double-to-int conversion routine does not guarantee
// rounding towards zero. // rounding towards zero.

3
deps/v8/src/counters.cc

@ -30,7 +30,8 @@
#include "counters.h" #include "counters.h"
#include "platform.h" #include "platform.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
CounterLookupCallback StatsTable::lookup_function_ = NULL; CounterLookupCallback StatsTable::lookup_function_ = NULL;
CreateHistogramCallback StatsTable::create_histogram_function_ = NULL; CreateHistogramCallback StatsTable::create_histogram_function_ = NULL;

5
deps/v8/src/counters.h

@ -28,7 +28,8 @@
#ifndef V8_COUNTERS_H_ #ifndef V8_COUNTERS_H_
#define V8_COUNTERS_H_ #define V8_COUNTERS_H_
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// StatsCounters is an interface for plugging into external // StatsCounters is an interface for plugging into external
// counters for monitoring. Counters can be looked up and // counters for monitoring. Counters can be looked up and
@ -74,7 +75,7 @@ class StatsTable : public AllStatic {
// function. min and max define the expected minimum and maximum // function. min and max define the expected minimum and maximum
// sample values. buckets is the maximum number of buckets // sample values. buckets is the maximum number of buckets
// that the samples will be grouped into. // that the samples will be grouped into.
static void *CreateHistogram(const char* name, static void* CreateHistogram(const char* name,
int min, int min,
int max, int max,
size_t buckets) { size_t buckets) {

3
deps/v8/src/cpu.h

@ -36,7 +36,8 @@
#ifndef V8_CPU_H_ #ifndef V8_CPU_H_
#define V8_CPU_H_ #define V8_CPU_H_
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// CPU // CPU

5
deps/v8/src/d8-posix.cc

@ -280,7 +280,10 @@ static void ExecSubprocess(int* exec_error_fds,
// Only get here if the exec failed. Write errno to the parent to tell // Only get here if the exec failed. Write errno to the parent to tell
// them it went wrong. If it went well the pipe is closed. // them it went wrong. If it went well the pipe is closed.
int err = errno; int err = errno;
write(exec_error_fds[kWriteFD], &err, sizeof(err)); int bytes_written;
do {
bytes_written = write(exec_error_fds[kWriteFD], &err, sizeof(err));
} while (bytes_written == -1 && errno == EINTR);
// Return (and exit child process). // Return (and exit child process).
} }

12
deps/v8/src/d8.cc

@ -451,7 +451,7 @@ void Shell::Initialize() {
i::Handle<i::JSFunction> script_fun = Utils::OpenHandle(*script); i::Handle<i::JSFunction> script_fun = Utils::OpenHandle(*script);
i::Handle<i::Script> script_object = i::Handle<i::Script> script_object =
i::Handle<i::Script>(i::Script::cast(script_fun->shared()->script())); i::Handle<i::Script>(i::Script::cast(script_fun->shared()->script()));
script_object->set_type(i::Smi::FromInt(i::SCRIPT_TYPE_NATIVE)); script_object->set_type(i::Smi::FromInt(i::Script::TYPE_NATIVE));
// Create the evaluation context // Create the evaluation context
evaluation_context_ = Context::New(NULL, global_template); evaluation_context_ = Context::New(NULL, global_template);
@ -487,7 +487,7 @@ void Shell::OnExit() {
} }
static char* ReadChars(const char *name, int* size_out) { static char* ReadChars(const char* name, int* size_out) {
v8::Unlocker unlocker; // Release the V8 lock while reading files. v8::Unlocker unlocker; // Release the V8 lock while reading files.
FILE* file = i::OS::FOpen(name, "rb"); FILE* file = i::OS::FOpen(name, "rb");
if (file == NULL) return NULL; if (file == NULL) return NULL;
@ -659,7 +659,7 @@ int Shell::Main(int argc, char* argv[]) {
use_preemption = false; use_preemption = false;
} else if (strcmp(str, "--preemption-interval") == 0) { } else if (strcmp(str, "--preemption-interval") == 0) {
if (i + 1 < argc) { if (i + 1 < argc) {
char *end = NULL; char* end = NULL;
preemption_interval = strtol(argv[++i], &end, 10); // NOLINT preemption_interval = strtol(argv[++i], &end, 10); // NOLINT
if (preemption_interval <= 0 || *end != '\0' || errno == ERANGE) { if (preemption_interval <= 0 || *end != '\0' || errno == ERANGE) {
printf("Invalid value for --preemption-interval '%s'\n", argv[i]); printf("Invalid value for --preemption-interval '%s'\n", argv[i]);
@ -687,9 +687,9 @@ int Shell::Main(int argc, char* argv[]) {
i++; i++;
} else if (strcmp(str, "-p") == 0 && i + 1 < argc) { } else if (strcmp(str, "-p") == 0 && i + 1 < argc) {
int size = 0; int size = 0;
const char *files = ReadChars(argv[++i], &size); const char* files = ReadChars(argv[++i], &size);
if (files == NULL) return 1; if (files == NULL) return 1;
ShellThread *thread = ShellThread* thread =
new ShellThread(threads.length(), new ShellThread(threads.length(),
i::Vector<const char>(files, size)); i::Vector<const char>(files, size));
thread->Start(); thread->Start();
@ -736,7 +736,7 @@ int Shell::Main(int argc, char* argv[]) {
if (run_shell) if (run_shell)
RunShell(); RunShell();
for (int i = 0; i < threads.length(); i++) { for (int i = 0; i < threads.length(); i++) {
i::Thread *thread = threads[i]; i::Thread* thread = threads[i];
thread->Join(); thread->Join();
delete thread; delete thread;
} }

56
deps/v8/src/d8.js

@ -93,6 +93,13 @@ Debug.ScriptType = { Native: 0,
Normal: 2 }; Normal: 2 };
// The different types of script compilations matching enum
// Script::CompilationType in objects.h.
Debug.ScriptCompilationType = { Host: 0,
Eval: 1,
JSON: 2 };
// Current debug state. // Current debug state.
const kNoFrame = -1; const kNoFrame = -1;
Debug.State = { Debug.State = {
@ -498,9 +505,26 @@ DebugRequest.prototype.stepCommandToJSONRequest_ = function(args) {
DebugRequest.prototype.backtraceCommandToJSONRequest_ = function(args) { DebugRequest.prototype.backtraceCommandToJSONRequest_ = function(args) {
// Build a backtrace request from the text command. // Build a backtrace request from the text command.
var request = this.createRequest('backtrace'); var request = this.createRequest('backtrace');
// Default is to show top 10 frames.
request.arguments = {};
request.arguments.fromFrame = 0;
request.arguments.toFrame = 10;
args = args.split(/\s*[ ]+\s*/g); args = args.split(/\s*[ ]+\s*/g);
if (args.length == 2) { if (args.length == 1 && args[0].length > 0) {
request.arguments = {}; var frameCount = parseInt(args[0]);
if (frameCount > 0) {
// Show top frames.
request.arguments.fromFrame = 0;
request.arguments.toFrame = frameCount;
} else {
// Show bottom frames.
request.arguments.fromFrame = 0;
request.arguments.toFrame = -frameCount;
request.arguments.bottom = true;
}
} else if (args.length == 2) {
var fromFrame = parseInt(args[0]); var fromFrame = parseInt(args[0]);
var toFrame = parseInt(args[1]); var toFrame = parseInt(args[1]);
if (isNaN(fromFrame) || fromFrame < 0) { if (isNaN(fromFrame) || fromFrame < 0) {
@ -513,9 +537,13 @@ DebugRequest.prototype.backtraceCommandToJSONRequest_ = function(args) {
throw new Error('Invalid arguments start frame cannot be larger ' + throw new Error('Invalid arguments start frame cannot be larger ' +
'than end frame.'); 'than end frame.');
} }
// Show frame range.
request.arguments.fromFrame = fromFrame; request.arguments.fromFrame = fromFrame;
request.arguments.toFrame = toFrame + 1; request.arguments.toFrame = toFrame + 1;
} else if (args.length > 2) {
throw new Error('Invalid backtrace arguments.');
} }
return request.toJSONProtocol(); return request.toJSONProtocol();
}; };
@ -755,7 +783,7 @@ DebugRequest.prototype.helpCommand_ = function(args) {
print(' break on function: location is #<id>#'); print(' break on function: location is #<id>#');
print(' break on script position: location is name:line[:column]'); print(' break on script position: location is name:line[:column]');
print('clear <breakpoint #>'); print('clear <breakpoint #>');
print('backtrace [from frame #] [to frame #]]'); print('backtrace [n] | [-n] | [from to]');
print('frame <frame #>'); print('frame <frame #>');
print('step [in | next | out| min [step count]]'); print('step [in | next | out| min [step count]]');
print('print <expression>'); print('print <expression>');
@ -942,7 +970,18 @@ function DebugResponseDetails(response) {
if (body[i].name) { if (body[i].name) {
result += body[i].name; result += body[i].name;
} else { } else {
result += '[unnamed] '; if (body[i].compilationType == Debug.ScriptCompilationType.Eval) {
result += 'eval from ';
var script_value = response.lookup(body[i].evalFromScript.ref);
result += ' ' + script_value.field('name');
result += ':' + (body[i].evalFromLocation.line + 1);
result += ':' + body[i].evalFromLocation.column;
} else if (body[i].compilationType ==
Debug.ScriptCompilationType.JSON) {
result += 'JSON ';
} else { // body[i].compilation == Debug.ScriptCompilationType.Host
result += '[unnamed] ';
}
} }
result += ' (lines: '; result += ' (lines: ';
result += body[i].lineCount; result += body[i].lineCount;
@ -1104,6 +1143,15 @@ ProtocolValue.prototype.type = function() {
} }
/**
* Get a metadata field from a protocol value.
* @return {Object} the metadata field value
*/
ProtocolValue.prototype.field = function(name) {
return this.value_[name];
}
/** /**
* Check is the value is a primitive value. * Check is the value is a primitive value.
* @return {boolean} true if the value is primitive * @return {boolean} true if the value is primitive

3
deps/v8/src/dateparser-inl.h

@ -28,7 +28,8 @@
#ifndef V8_DATEPARSER_INL_H_ #ifndef V8_DATEPARSER_INL_H_
#define V8_DATEPARSER_INL_H_ #define V8_DATEPARSER_INL_H_
namespace v8 { namespace internal { namespace v8 {
namespace internal {
template <typename Char> template <typename Char>
bool DateParser::Parse(Vector<Char> str, FixedArray* out) { bool DateParser::Parse(Vector<Char> str, FixedArray* out) {

3
deps/v8/src/dateparser.cc

@ -29,7 +29,8 @@
#include "dateparser.h" #include "dateparser.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
bool DateParser::DayComposer::Write(FixedArray* output) { bool DateParser::DayComposer::Write(FixedArray* output) {
int year = 0; // Default year is 0 (=> 2000) for KJS compatibility. int year = 0; // Default year is 0 (=> 2000) for KJS compatibility.

3
deps/v8/src/dateparser.h

@ -30,7 +30,8 @@
#include "scanner.h" #include "scanner.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
class DateParser : public AllStatic { class DateParser : public AllStatic {
public: public:

3
deps/v8/src/debug-agent.cc

@ -30,7 +30,8 @@
#include "debug-agent.h" #include "debug-agent.h"
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// Public V8 debugger API message handler function. This function just delegates // Public V8 debugger API message handler function. This function just delegates
// to the debugger agent through it's data parameter. // to the debugger agent through it's data parameter.

3
deps/v8/src/debug-agent.h

@ -32,7 +32,8 @@
#include "../include/v8-debug.h" #include "../include/v8-debug.h"
#include "platform.h" #include "platform.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// Forward decelrations. // Forward decelrations.
class DebuggerAgentSession; class DebuggerAgentSession;

267
deps/v8/src/debug-delay.js

@ -43,7 +43,8 @@ Debug.DebugEvent = { Break: 1,
Exception: 2, Exception: 2,
NewFunction: 3, NewFunction: 3,
BeforeCompile: 4, BeforeCompile: 4,
AfterCompile: 5 }; AfterCompile: 5,
ScriptCollected: 6 };
// Types of exceptions that can be broken upon. // Types of exceptions that can be broken upon.
Debug.ExceptionBreak = { All : 0, Debug.ExceptionBreak = { All : 0,
@ -61,6 +62,12 @@ Debug.ScriptType = { Native: 0,
Extension: 1, Extension: 1,
Normal: 2 }; Normal: 2 };
// The different types of script compilations matching enum
// Script::CompilationType in objects.h.
Debug.ScriptCompilationType = { Host: 0,
Eval: 1,
JSON: 2 };
// The different script break point types. // The different script break point types.
Debug.ScriptBreakPointType = { ScriptId: 0, Debug.ScriptBreakPointType = { ScriptId: 0,
ScriptName: 1 }; ScriptName: 1 };
@ -833,7 +840,7 @@ BreakEvent.prototype.toJSONProtocol = function() {
event: "break", event: "break",
body: { invocationText: this.exec_state_.frame(0).invocationText(), body: { invocationText: this.exec_state_.frame(0).invocationText(),
} }
} };
// Add script related information to the event if available. // Add script related information to the event if available.
var script = this.func().script(); var script = this.func().script();
@ -861,8 +868,7 @@ BreakEvent.prototype.toJSONProtocol = function() {
o.body.breakpoints.push(number); o.body.breakpoints.push(number);
} }
} }
return JSON.stringify(ObjectToProtocolObject_(o));
return SimpleObjectToJSON_(o);
}; };
@ -923,7 +929,7 @@ ExceptionEvent.prototype.toJSONProtocol = function() {
o.event = "exception"; o.event = "exception";
o.body = { uncaught: this.uncaught_, o.body = { uncaught: this.uncaught_,
exception: MakeMirror(this.exception_) exception: MakeMirror(this.exception_)
} };
// Exceptions might happen whithout any JavaScript frames. // Exceptions might happen whithout any JavaScript frames.
if (this.exec_state_.frameCount() > 0) { if (this.exec_state_.frameCount() > 0) {
@ -984,7 +990,8 @@ CompileEvent.prototype.toJSONProtocol = function() {
o.event = "afterCompile"; o.event = "afterCompile";
} }
o.body = {}; o.body = {};
o.body.script = MakeScriptObject_(this.script_, true); o.body.script = this.script_;
o.setOption('includeSource', true);
return o.toJSONProtocol(); return o.toJSONProtocol();
} }
@ -1015,6 +1022,37 @@ NewFunctionEvent.prototype.setBreakPoint = function(p) {
}; };
function MakeScriptCollectedEvent(exec_state, id) {
return new ScriptCollectedEvent(exec_state, id);
}
function ScriptCollectedEvent(exec_state, id) {
this.exec_state_ = exec_state;
this.id_ = id;
}
ScriptCollectedEvent.prototype.id = function() {
return this.id_;
};
ScriptCollectedEvent.prototype.executionState = function() {
return this.exec_state_;
};
ScriptCollectedEvent.prototype.toJSONProtocol = function() {
var o = new ProtocolMessage();
o.running = true;
o.event = "scriptCollected";
o.body = {};
o.body.script = { id: this.id() };
return o.toJSONProtocol();
}
function MakeScriptObject_(script, include_source) { function MakeScriptObject_(script, include_source) {
var o = { id: script.id(), var o = { id: script.id(),
name: script.name(), name: script.name(),
@ -1078,56 +1116,53 @@ ProtocolMessage.prototype.failed = function(message) {
ProtocolMessage.prototype.toJSONProtocol = function() { ProtocolMessage.prototype.toJSONProtocol = function() {
// Encode the protocol header. // Encode the protocol header.
var json = '{'; var json = {};
json += '"seq":' + this.seq; json.seq= this.seq;
if (this.request_seq) { if (this.request_seq) {
json += ',"request_seq":' + this.request_seq; json.request_seq = this.request_seq;
} }
json += ',"type":"' + this.type + '"'; json.type = this.type;
if (this.event) { if (this.event) {
json += ',"event":' + StringToJSON_(this.event); json.event = this.event;
} }
if (this.command) { if (this.command) {
json += ',"command":' + StringToJSON_(this.command); json.command = this.command;
} }
if (this.success) { if (this.success) {
json += ',"success":' + this.success; json.success = this.success;
} else { } else {
json += ',"success":false'; json.success = false;
} }
if (this.body) { if (this.body) {
json += ',"body":';
// Encode the body part. // Encode the body part.
var bodyJson;
var serializer = MakeMirrorSerializer(true, this.options_); var serializer = MakeMirrorSerializer(true, this.options_);
if (this.body instanceof Mirror) { if (this.body instanceof Mirror) {
json += serializer.serializeValue(this.body); bodyJson = serializer.serializeValue(this.body);
} else if (this.body instanceof Array) { } else if (this.body instanceof Array) {
json += '['; bodyJson = [];
for (var i = 0; i < this.body.length; i++) { for (var i = 0; i < this.body.length; i++) {
if (i != 0) json += ',';
if (this.body[i] instanceof Mirror) { if (this.body[i] instanceof Mirror) {
json += serializer.serializeValue(this.body[i]); bodyJson.push(serializer.serializeValue(this.body[i]));
} else { } else {
json += SimpleObjectToJSON_(this.body[i], serializer); bodyJson.push(ObjectToProtocolObject_(this.body[i], serializer));
} }
} }
json += ']';
} else { } else {
json += SimpleObjectToJSON_(this.body, serializer); bodyJson = ObjectToProtocolObject_(this.body, serializer);
} }
json += ',"refs":'; json.body = bodyJson;
json += serializer.serializeReferencedObjects(); json.refs = serializer.serializeReferencedObjects();
} }
if (this.message) { if (this.message) {
json += ',"message":' + StringToJSON_(this.message) ; json.message = this.message;
} }
if (this.running) { if (this.running) {
json += ',"running":true'; json.running = true;
} else { } else {
json += ',"running":false'; json.running = false;
} }
json += '}'; return JSON.stringify(json);
return json;
} }
@ -1142,7 +1177,7 @@ DebugCommandProcessor.prototype.processDebugJSONRequest = function(json_request)
try { try {
try { try {
// Convert the JSON string to an object. // Convert the JSON string to an object.
request = %CompileString('(' + json_request + ')', 0, false)(); request = %CompileString('(' + json_request + ')', false)();
// Create an initial response. // Create an initial response.
response = this.createResponse(request); response = this.createResponse(request);
@ -1451,14 +1486,23 @@ DebugCommandProcessor.prototype.backtraceRequest_ = function(request, response)
// Get the range from the arguments. // Get the range from the arguments.
if (request.arguments) { if (request.arguments) {
from_index = request.arguments.fromFrame; if (request.arguments.fromFrame) {
if (from_index < 0) { from_index = request.arguments.fromFrame;
return response.failed('Invalid frame number'); }
if (request.arguments.toFrame) {
to_index = request.arguments.toFrame;
} }
to_index = request.arguments.toFrame; if (request.arguments.bottom) {
if (to_index < 0) { var tmp_index = total_frames - from_index;
from_index = total_frames - to_index
to_index = tmp_index;
}
if (from_index < 0 || to_index < 0) {
return response.failed('Invalid frame number'); return response.failed('Invalid frame number');
} }
if (request.arguments.compactFormat) {
response.setOption('compactFormat', true);
}
} }
// Adjust the index. // Adjust the index.
@ -1581,6 +1625,16 @@ DebugCommandProcessor.prototype.lookupRequest_ = function(request, response) {
return response.failed('Argument "handles" missing'); return response.failed('Argument "handles" missing');
} }
// Set 'includeSource' option for script lookup.
if (!IS_UNDEFINED(request.arguments.includeSource)) {
includeSource = %ToBoolean(request.arguments.includeSource);
response.setOption('includeSource', includeSource);
}
if (request.arguments.compactFormat) {
response.setOption('compactFormat', true);
}
// Lookup handles. // Lookup handles.
var mirrors = {}; var mirrors = {};
for (var i = 0; i < handles.length; i++) { for (var i = 0; i < handles.length; i++) {
@ -1677,6 +1731,7 @@ DebugCommandProcessor.prototype.sourceRequest_ = function(request, response) {
DebugCommandProcessor.prototype.scriptsRequest_ = function(request, response) { DebugCommandProcessor.prototype.scriptsRequest_ = function(request, response) {
var types = ScriptTypeFlag(Debug.ScriptType.Normal); var types = ScriptTypeFlag(Debug.ScriptType.Normal);
var includeSource = false; var includeSource = false;
var idsToInclude = null;
if (request.arguments) { if (request.arguments) {
// Pull out arguments. // Pull out arguments.
if (!IS_UNDEFINED(request.arguments.types)) { if (!IS_UNDEFINED(request.arguments.types)) {
@ -1690,6 +1745,14 @@ DebugCommandProcessor.prototype.scriptsRequest_ = function(request, response) {
includeSource = %ToBoolean(request.arguments.includeSource); includeSource = %ToBoolean(request.arguments.includeSource);
response.setOption('includeSource', includeSource); response.setOption('includeSource', includeSource);
} }
if (IS_ARRAY(request.arguments.ids)) {
idsToInclude = {};
var ids = request.arguments.ids;
for (var i = 0; i < ids.length; i++) {
idsToInclude[ids[i]] = true;
}
}
} }
// Collect all scripts in the heap. // Collect all scripts in the heap.
@ -1698,6 +1761,9 @@ DebugCommandProcessor.prototype.scriptsRequest_ = function(request, response) {
response.body = []; response.body = [];
for (var i = 0; i < scripts.length; i++) { for (var i = 0; i < scripts.length; i++) {
if (idsToInclude && !idsToInclude[scripts[i].id]) {
continue;
}
if (types & ScriptTypeFlag(scripts[i].type)) { if (types & ScriptTypeFlag(scripts[i].type)) {
response.body.push(MakeMirror(scripts[i])); response.body.push(MakeMirror(scripts[i]));
} }
@ -1774,97 +1840,82 @@ DebugCommandProcessor.prototype.formatCFrame = function(cframe_value) {
/** /**
* Convert an Object to its JSON representation (see http://www.json.org/). * Convert an Object to its debugger protocol representation. The representation
* This implementation simply runs through all string property names and adds * may be serilized to a JSON object using JSON.stringify().
* each property to the JSON representation for some predefined types. For type * This implementation simply runs through all string property names, converts
* "object" the function calls itself recursively unless the object has the * each property value to a protocol value and adds the property to the result
* function property "toJSONProtocol" in which case that is used. This is not * object. For type "object" the function will be called recursively. Note that
* a general implementation but sufficient for the debugger. Note that circular * circular structures will cause infinite recursion.
* structures will cause infinite recursion. * @param {Object} object The object to format as protocol object.
* @param {Object} object The object to format as JSON
* @param {MirrorSerializer} mirror_serializer The serializer to use if any * @param {MirrorSerializer} mirror_serializer The serializer to use if any
* mirror objects are encountered. * mirror objects are encountered.
* @return {string} JSON formatted object value * @return {Object} Protocol object value.
*/ */
function SimpleObjectToJSON_(object, mirror_serializer) { function ObjectToProtocolObject_(object, mirror_serializer) {
var content = []; var content = {};
for (var key in object) { for (var key in object) {
// Only consider string keys. // Only consider string keys.
if (typeof key == 'string') { if (typeof key == 'string') {
var property_value = object[key];
// Format the value based on its type. // Format the value based on its type.
var property_value_json; var property_value_json = ValueToProtocolValue_(object[key],
switch (typeof property_value) { mirror_serializer);
case 'object':
if (property_value instanceof Mirror) {
property_value_json = mirror_serializer.serializeValue(property_value);
} else if (typeof property_value.toJSONProtocol == 'function') {
property_value_json = property_value.toJSONProtocol(true)
} else if (IS_ARRAY(property_value)){
property_value_json = SimpleArrayToJSON_(property_value, mirror_serializer);
} else {
property_value_json = SimpleObjectToJSON_(property_value, mirror_serializer);
}
break;
case 'boolean':
property_value_json = BooleanToJSON_(property_value);
break;
case 'number':
property_value_json = NumberToJSON_(property_value);
break;
case 'string':
property_value_json = StringToJSON_(property_value);
break;
default:
property_value_json = null;
}
// Add the property if relevant. // Add the property if relevant.
if (property_value_json) { if (!IS_UNDEFINED(property_value_json)) {
content.push(StringToJSON_(key) + ':' + property_value_json); content[key] = property_value_json;
} }
} }
} }
// Make JSON object representation. return content;
return '{' + content.join(',') + '}';
} }
/** /**
* Convert an array to its JSON representation. This is a VERY simple * Convert an array to its debugger protocol representation. It will convert
* implementation just to support what is needed for the debugger. * each array element to a protocol value.
* @param {Array} array The array to format as JSON * @param {Array} array The array to format as protocol array.
* @param {MirrorSerializer} mirror_serializer The serializer to use if any * @param {MirrorSerializer} mirror_serializer The serializer to use if any
* mirror objects are encountered. * mirror objects are encountered.
* @return {string} JSON formatted array value * @return {Array} Protocol array value.
*/ */
function SimpleArrayToJSON_(array, mirror_serializer) { function ArrayToProtocolArray_(array, mirror_serializer) {
// Make JSON array representation. var json = [];
var json = '[';
for (var i = 0; i < array.length; i++) { for (var i = 0; i < array.length; i++) {
if (i != 0) { json.push(ValueToProtocolValue_(array[i], mirror_serializer));
json += ','; }
} return json;
var elem = array[i]; }
if (elem instanceof Mirror) {
json += mirror_serializer.serializeValue(elem);
} else if (IS_OBJECT(elem)) { /**
json += SimpleObjectToJSON_(elem); * Convert a value to its debugger protocol representation.
} else if (IS_BOOLEAN(elem)) { * @param {*} value The value to format as protocol value.
json += BooleanToJSON_(elem); * @param {MirrorSerializer} mirror_serializer The serializer to use if any
} else if (IS_NUMBER(elem)) { * mirror objects are encountered.
json += NumberToJSON_(elem); * @return {*} Protocol value.
} else if (IS_STRING(elem)) { */
json += StringToJSON_(elem); function ValueToProtocolValue_(value, mirror_serializer) {
} else { // Format the value based on its type.
json += elem; var json;
} switch (typeof value) {
case 'object':
if (value instanceof Mirror) {
json = mirror_serializer.serializeValue(value);
} else if (IS_ARRAY(value)){
json = ArrayToProtocolArray_(value, mirror_serializer);
} else {
json = ObjectToProtocolObject_(value, mirror_serializer);
}
break;
case 'boolean':
case 'string':
case 'number':
json = value;
break
default:
json = null;
} }
json += ']';
return json; return json;
} }

319
deps/v8/src/debug.cc

@ -31,6 +31,7 @@
#include "arguments.h" #include "arguments.h"
#include "bootstrapper.h" #include "bootstrapper.h"
#include "code-stubs.h" #include "code-stubs.h"
#include "compilation-cache.h"
#include "compiler.h" #include "compiler.h"
#include "debug.h" #include "debug.h"
#include "execution.h" #include "execution.h"
@ -43,7 +44,8 @@
#include "../include/v8-debug.h" #include "../include/v8-debug.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
static void PrintLn(v8::Local<v8::Value> value) { static void PrintLn(v8::Local<v8::Value> value) {
@ -425,6 +427,7 @@ void BreakLocationIterator::RinfoNext() {
bool Debug::has_break_points_ = false; bool Debug::has_break_points_ = false;
ScriptCache* Debug::script_cache_ = NULL;
DebugInfoListNode* Debug::debug_info_list_ = NULL; DebugInfoListNode* Debug::debug_info_list_ = NULL;
@ -440,7 +443,7 @@ void Debug::ThreadInit() {
thread_local_.step_into_fp_ = 0; thread_local_.step_into_fp_ = 0;
thread_local_.after_break_target_ = 0; thread_local_.after_break_target_ = 0;
thread_local_.debugger_entry_ = NULL; thread_local_.debugger_entry_ = NULL;
thread_local_.preemption_pending_ = false; thread_local_.pending_interrupts_ = 0;
} }
@ -486,29 +489,77 @@ Code* Debug::debug_break_return_entry_ = NULL;
Code* Debug::debug_break_return_ = NULL; Code* Debug::debug_break_return_ = NULL;
void Debug::HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data) { void ScriptCache::Add(Handle<Script> script) {
DebugInfoListNode* node = reinterpret_cast<DebugInfoListNode*>(data); // Create an entry in the hash map for the script.
RemoveDebugInfo(node->debug_info()); int id = Smi::cast(script->id())->value();
#ifdef DEBUG HashMap::Entry* entry =
node = Debug::debug_info_list_; HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true);
while (node != NULL) { if (entry->value != NULL) {
ASSERT(node != reinterpret_cast<DebugInfoListNode*>(data)); ASSERT(*script == *reinterpret_cast<Script**>(entry->value));
node = node->next(); return;
} }
#endif
// Globalize the script object, make it weak and use the location of the
// global handle as the value in the hash map.
Handle<Script> script_ =
Handle<Script>::cast((GlobalHandles::Create(*script)));
GlobalHandles::MakeWeak(reinterpret_cast<Object**>(script_.location()),
this, ScriptCache::HandleWeakScript);
entry->value = script_.location();
} }
DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) { Handle<FixedArray> ScriptCache::GetScripts() {
// Globalize the request debug info object and make it weak. Handle<FixedArray> instances = Factory::NewFixedArray(occupancy());
debug_info_ = Handle<DebugInfo>::cast((GlobalHandles::Create(debug_info))); int count = 0;
GlobalHandles::MakeWeak(reinterpret_cast<Object**>(debug_info_.location()), for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
this, Debug::HandleWeakDebugInfo); ASSERT(entry->value != NULL);
if (entry->value != NULL) {
instances->set(count, *reinterpret_cast<Script**>(entry->value));
count++;
}
}
return instances;
} }
DebugInfoListNode::~DebugInfoListNode() { void ScriptCache::ProcessCollectedScripts() {
GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location())); for (int i = 0; i < collected_scripts_.length(); i++) {
Debugger::OnScriptCollected(collected_scripts_[i]);
}
collected_scripts_.Clear();
}
void ScriptCache::Clear() {
// Iterate the script cache to get rid of all the weak handles.
for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
ASSERT(entry != NULL);
Object** location = reinterpret_cast<Object**>(entry->value);
ASSERT((*location)->IsScript());
GlobalHandles::ClearWeakness(location);
GlobalHandles::Destroy(location);
}
// Clear the content of the hash map.
HashMap::Clear();
}
void ScriptCache::HandleWeakScript(v8::Persistent<v8::Value> obj, void* data) {
ScriptCache* script_cache = reinterpret_cast<ScriptCache*>(data);
// Find the location of the global handle.
Script** location =
reinterpret_cast<Script**>(Utils::OpenHandle(*obj).location());
ASSERT((*location)->IsScript());
// Remove the entry from the cache.
int id = Smi::cast((*location)->id())->value();
script_cache->Remove(reinterpret_cast<void*>(id), Hash(id));
script_cache->collected_scripts_.Add(id);
// Clear the weak handle.
obj.Dispose();
obj.Clear();
} }
@ -528,6 +579,32 @@ void Debug::Setup(bool create_heap_objects) {
} }
void Debug::HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data) {
DebugInfoListNode* node = reinterpret_cast<DebugInfoListNode*>(data);
RemoveDebugInfo(node->debug_info());
#ifdef DEBUG
node = Debug::debug_info_list_;
while (node != NULL) {
ASSERT(node != reinterpret_cast<DebugInfoListNode*>(data));
node = node->next();
}
#endif
}
DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
// Globalize the request debug info object and make it weak.
debug_info_ = Handle<DebugInfo>::cast((GlobalHandles::Create(debug_info)));
GlobalHandles::MakeWeak(reinterpret_cast<Object**>(debug_info_.location()),
this, Debug::HandleWeakDebugInfo);
}
DebugInfoListNode::~DebugInfoListNode() {
GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location()));
}
bool Debug::CompileDebuggerScript(int index) { bool Debug::CompileDebuggerScript(int index) {
HandleScope scope; HandleScope scope;
@ -575,7 +652,7 @@ bool Debug::CompileDebuggerScript(int index) {
// Mark this script as native and return successfully. // Mark this script as native and return successfully.
Handle<Script> script(Script::cast(function->shared()->script())); Handle<Script> script(Script::cast(function->shared()->script()));
script->set_type(Smi::FromInt(SCRIPT_TYPE_NATIVE)); script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
return true; return true;
} }
@ -627,6 +704,7 @@ bool Debug::Load() {
// Debugger loaded. // Debugger loaded.
debug_context_ = Handle<Context>::cast(GlobalHandles::Create(*context)); debug_context_ = Handle<Context>::cast(GlobalHandles::Create(*context));
return true; return true;
} }
@ -637,6 +715,9 @@ void Debug::Unload() {
return; return;
} }
// Clear the script cache.
DestroyScriptCache();
// Clear debugger context global handle. // Clear debugger context global handle.
GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location())); GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location()));
debug_context_ = Handle<Context>(); debug_context_ = Handle<Context>();
@ -646,7 +727,7 @@ void Debug::Unload() {
// Set the flag indicating that preemption happened during debugging. // Set the flag indicating that preemption happened during debugging.
void Debug::PreemptionWhileInDebugger() { void Debug::PreemptionWhileInDebugger() {
ASSERT(InDebugger()); ASSERT(InDebugger());
Debug::set_preemption_pending(true); Debug::set_interrupts_pending(PREEMPT);
} }
@ -1414,6 +1495,94 @@ void Debug::ClearMirrorCache() {
} }
// If an object given is an external string, check that the underlying
// resource is accessible. For other kinds of objects, always return true.
static bool IsExternalStringValid(Object* str) {
if (!str->IsString() || !StringShape(String::cast(str)).IsExternal()) {
return true;
}
if (String::cast(str)->IsAsciiRepresentation()) {
return ExternalAsciiString::cast(str)->resource() != NULL;
} else if (String::cast(str)->IsTwoByteRepresentation()) {
return ExternalTwoByteString::cast(str)->resource() != NULL;
} else {
return true;
}
}
void Debug::CreateScriptCache() {
HandleScope scope;
// Perform two GCs to get rid of all unreferenced scripts. The first GC gets
// rid of all the cached script wrappers and the second gets rid of the
// scripts which is no longer referenced.
Heap::CollectAllGarbage();
Heap::CollectAllGarbage();
ASSERT(script_cache_ == NULL);
script_cache_ = new ScriptCache();
// Scan heap for Script objects.
int count = 0;
HeapIterator iterator;
while (iterator.has_next()) {
HeapObject* obj = iterator.next();
ASSERT(obj != NULL);
if (obj->IsScript() && IsExternalStringValid(Script::cast(obj)->source())) {
script_cache_->Add(Handle<Script>(Script::cast(obj)));
count++;
}
}
}
void Debug::DestroyScriptCache() {
// Get rid of the script cache if it was created.
if (script_cache_ != NULL) {
delete script_cache_;
script_cache_ = NULL;
}
}
void Debug::AddScriptToScriptCache(Handle<Script> script) {
if (script_cache_ != NULL) {
script_cache_->Add(script);
}
}
Handle<FixedArray> Debug::GetLoadedScripts() {
// Create and fill the script cache when the loaded scripts is requested for
// the first time.
if (script_cache_ == NULL) {
CreateScriptCache();
}
// If the script cache is not active just return an empty array.
ASSERT(script_cache_ != NULL);
if (script_cache_ == NULL) {
Factory::NewFixedArray(0);
}
// Perform GC to get unreferenced scripts evicted from the cache before
// returning the content.
Heap::CollectAllGarbage();
// Get the scripts from the cache.
return script_cache_->GetScripts();
}
void Debug::AfterGarbageCollection() {
// Generate events for collected scripts.
if (script_cache_ != NULL) {
script_cache_->ProcessCollectedScripts();
}
}
Mutex* Debugger::debugger_access_ = OS::CreateMutex(); Mutex* Debugger::debugger_access_ = OS::CreateMutex();
Handle<Object> Debugger::event_listener_ = Handle<Object>(); Handle<Object> Debugger::event_listener_ = Handle<Object>();
Handle<Object> Debugger::event_listener_data_ = Handle<Object>(); Handle<Object> Debugger::event_listener_data_ = Handle<Object>();
@ -1421,7 +1590,7 @@ bool Debugger::compiling_natives_ = false;
bool Debugger::is_loading_debugger_ = false; bool Debugger::is_loading_debugger_ = false;
bool Debugger::never_unload_debugger_ = false; bool Debugger::never_unload_debugger_ = false;
v8::Debug::MessageHandler2 Debugger::message_handler_ = NULL; v8::Debug::MessageHandler2 Debugger::message_handler_ = NULL;
bool Debugger::message_handler_cleared_ = false; bool Debugger::debugger_unload_pending_ = false;
v8::Debug::HostDispatchHandler Debugger::host_dispatch_handler_ = NULL; v8::Debug::HostDispatchHandler Debugger::host_dispatch_handler_ = NULL;
int Debugger::host_dispatch_micros_ = 100 * 1000; int Debugger::host_dispatch_micros_ = 100 * 1000;
DebuggerAgent* Debugger::agent_ = NULL; DebuggerAgent* Debugger::agent_ = NULL;
@ -1518,6 +1687,21 @@ Handle<Object> Debugger::MakeCompileEvent(Handle<Script> script,
} }
Handle<Object> Debugger::MakeScriptCollectedEvent(int id,
bool* caught_exception) {
// Create the script collected event object.
Handle<Object> exec_state = MakeExecutionState(caught_exception);
Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id));
const int argc = 2;
Object** argv[argc] = { exec_state.location(), id_object.location() };
return MakeJSObject(CStrVector("MakeScriptCollectedEvent"),
argc,
argv,
caught_exception);
}
void Debugger::OnException(Handle<Object> exception, bool uncaught) { void Debugger::OnException(Handle<Object> exception, bool uncaught) {
HandleScope scope; HandleScope scope;
@ -1624,12 +1808,15 @@ void Debugger::OnBeforeCompile(Handle<Script> script) {
void Debugger::OnAfterCompile(Handle<Script> script, Handle<JSFunction> fun) { void Debugger::OnAfterCompile(Handle<Script> script, Handle<JSFunction> fun) {
HandleScope scope; HandleScope scope;
// No compile events while compiling natives. // Add the newly compiled script to the script cache.
if (compiling_natives()) return; Debug::AddScriptToScriptCache(script);
// No more to do if not debugging. // No more to do if not debugging.
if (!IsDebuggerActive()) return; if (!IsDebuggerActive()) return;
// No compile events while compiling natives.
if (compiling_natives()) return;
// Store whether in debugger before entering debugger. // Store whether in debugger before entering debugger.
bool in_debugger = Debug::InDebugger(); bool in_debugger = Debug::InDebugger();
@ -1708,11 +1895,43 @@ void Debugger::OnNewFunction(Handle<JSFunction> function) {
} }
void Debugger::OnScriptCollected(int id) {
HandleScope scope;
// No more to do if not debugging.
if (!IsDebuggerActive()) return;
if (!Debugger::EventActive(v8::ScriptCollected)) return;
// Enter the debugger.
EnterDebugger debugger;
if (debugger.FailedToEnter()) return;
// Create the script collected state object.
bool caught_exception = false;
Handle<Object> event_data = MakeScriptCollectedEvent(id,
&caught_exception);
// Bail out and don't call debugger if exception.
if (caught_exception) {
return;
}
// Process debug event.
ProcessDebugEvent(v8::ScriptCollected,
Handle<JSObject>::cast(event_data),
true);
}
void Debugger::ProcessDebugEvent(v8::DebugEvent event, void Debugger::ProcessDebugEvent(v8::DebugEvent event,
Handle<JSObject> event_data, Handle<JSObject> event_data,
bool auto_continue) { bool auto_continue) {
HandleScope scope; HandleScope scope;
// Clear any pending debug break if this is a real break.
if (!auto_continue) {
Debug::clear_interrupt_pending(DEBUGBREAK);
}
// Create the execution state. // Create the execution state.
bool caught_exception = false; bool caught_exception = false;
Handle<Object> exec_state = MakeExecutionState(&caught_exception); Handle<Object> exec_state = MakeExecutionState(&caught_exception);
@ -1756,9 +1975,6 @@ void Debugger::ProcessDebugEvent(v8::DebugEvent event,
} }
} }
} }
// Clear the mirror cache.
Debug::ClearMirrorCache();
} }
@ -1771,8 +1987,8 @@ void Debugger::UnloadDebugger() {
Debug::Unload(); Debug::Unload();
} }
// Clear the flag indicating that the message handler was recently cleared. // Clear the flag indicating that the debugger should be unloaded.
message_handler_cleared_ = false; debugger_unload_pending_ = false;
} }
@ -1798,6 +2014,9 @@ void Debugger::NotifyMessageHandler(v8::DebugEvent event,
case v8::AfterCompile: case v8::AfterCompile:
sendEventMessage = true; sendEventMessage = true;
break; break;
case v8::ScriptCollected:
sendEventMessage = true;
break;
case v8::NewFunction: case v8::NewFunction:
break; break;
default: default:
@ -1820,7 +2039,12 @@ void Debugger::NotifyMessageHandler(v8::DebugEvent event,
Handle<JSObject>::cast(event_data)); Handle<JSObject>::cast(event_data));
InvokeMessageHandler(message); InvokeMessageHandler(message);
} }
if (auto_continue && !HasCommands()) {
// If auto continue don't make the event cause a break, but process messages
// in the queue if any. For script collected events don't even process
// messages in the queue as the execution state might not be what is expected
// by the client.
if ((auto_continue && !HasCommands()) || event == v8::ScriptCollected) {
return; return;
} }
@ -1956,10 +2180,7 @@ void Debugger::SetEventListener(Handle<Object> callback,
event_listener_data_ = Handle<Object>::cast(GlobalHandles::Create(*data)); event_listener_data_ = Handle<Object>::cast(GlobalHandles::Create(*data));
} }
// Unload the debugger if event listener cleared. ListenersChanged();
if (callback->IsUndefined()) {
UnloadDebugger();
}
} }
@ -1967,10 +2188,8 @@ void Debugger::SetMessageHandler(v8::Debug::MessageHandler2 handler) {
ScopedLock with(debugger_access_); ScopedLock with(debugger_access_);
message_handler_ = handler; message_handler_ = handler;
ListenersChanged();
if (handler == NULL) { if (handler == NULL) {
// Indicate that the message handler was recently cleared.
message_handler_cleared_ = true;
// Send an empty command to the debugger if in a break to make JavaScript // Send an empty command to the debugger if in a break to make JavaScript
// run again if the debugger is closed. // run again if the debugger is closed.
if (Debug::InDebugger()) { if (Debug::InDebugger()) {
@ -1980,6 +2199,25 @@ void Debugger::SetMessageHandler(v8::Debug::MessageHandler2 handler) {
} }
void Debugger::ListenersChanged() {
if (IsDebuggerActive()) {
// Disable the compilation cache when the debugger is active.
CompilationCache::Disable();
} else {
CompilationCache::Enable();
// Unload the debugger if event listener and message handler cleared.
if (Debug::InDebugger()) {
// If we are in debugger set the flag to unload the debugger when last
// EnterDebugger on the current stack is destroyed.
debugger_unload_pending_ = true;
} else {
UnloadDebugger();
}
}
}
void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler, void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
int period) { int period) {
host_dispatch_handler_ = handler; host_dispatch_handler_ = handler;
@ -2172,7 +2410,14 @@ v8::Handle<v8::String> MessageImpl::GetJSON() const {
v8::Handle<v8::Context> MessageImpl::GetEventContext() const { v8::Handle<v8::Context> MessageImpl::GetEventContext() const {
return v8::Utils::ToLocal(Debug::debugger_entry()->GetContext()); Handle<Context> context = Debug::debugger_entry()->GetContext();
// Top::context() may have been NULL when "script collected" event occured.
if (*context == NULL) {
ASSERT(event_ == v8::ScriptCollected);
return v8::Local<v8::Context>();
}
Handle<Context> global_context(context->global_context());
return v8::Utils::ToLocal(global_context);
} }

136
deps/v8/src/debug.h

@ -33,6 +33,7 @@
#include "debug-agent.h" #include "debug-agent.h"
#include "execution.h" #include "execution.h"
#include "factory.h" #include "factory.h"
#include "hashmap.h"
#include "platform.h" #include "platform.h"
#include "string-stream.h" #include "string-stream.h"
#include "v8threads.h" #include "v8threads.h"
@ -40,7 +41,8 @@
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
#include "../include/v8-debug.h" #include "../include/v8-debug.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// Forward declarations. // Forward declarations.
@ -144,6 +146,42 @@ class BreakLocationIterator {
}; };
// Cache of all script objects in the heap. When a script is added a weak handle
// to it is created and that weak handle is stored in the cache. The weak handle
// callback takes care of removing the script from the cache. The key used in
// the cache is the script id.
class ScriptCache : private HashMap {
public:
ScriptCache() : HashMap(ScriptMatch), collected_scripts_(10) {}
virtual ~ScriptCache() { Clear(); }
// Add script to the cache.
void Add(Handle<Script> script);
// Return the scripts in the cache.
Handle<FixedArray> GetScripts();
// Generate debugger events for collected scripts.
void ProcessCollectedScripts();
private:
// Calculate the hash value from the key (script id).
static uint32_t Hash(int key) { return ComputeIntegerHash(key); }
// Scripts match if their keys (script id) match.
static bool ScriptMatch(void* key1, void* key2) { return key1 == key2; }
// Clear the cache releasing all the weak handles.
void Clear();
// Weak handle callback for scripts in the cache.
static void HandleWeakScript(v8::Persistent<v8::Value> obj, void* data);
// List used during GC to temporarily store id's of collected scripts.
List<int> collected_scripts_;
};
// Linked list holding debug info objects. The debug info objects are kept as // Linked list holding debug info objects. The debug info objects are kept as
// weak handles to avoid a debug info object to keep a function alive. // weak handles to avoid a debug info object to keep a function alive.
class DebugInfoListNode { class DebugInfoListNode {
@ -230,9 +268,6 @@ class Debug {
} }
static int break_id() { return thread_local_.break_id_; } static int break_id() { return thread_local_.break_id_; }
static bool StepInActive() { return thread_local_.step_into_fp_ != 0; } static bool StepInActive() { return thread_local_.step_into_fp_ != 0; }
static void HandleStepIn(Handle<JSFunction> function, static void HandleStepIn(Handle<JSFunction> function,
Address fp, Address fp,
@ -247,11 +282,19 @@ class Debug {
thread_local_.debugger_entry_ = entry; thread_local_.debugger_entry_ = entry;
} }
static bool preemption_pending() { // Check whether any of the specified interrupts are pending.
return thread_local_.preemption_pending_; static bool is_interrupt_pending(InterruptFlag what) {
return (thread_local_.pending_interrupts_ & what) != 0;
} }
static void set_preemption_pending(bool preemption_pending) {
thread_local_.preemption_pending_ = preemption_pending; // Set specified interrupts as pending.
static void set_interrupts_pending(InterruptFlag what) {
thread_local_.pending_interrupts_ |= what;
}
// Clear specified interrupts from pending.
static void clear_interrupt_pending(InterruptFlag what) {
thread_local_.pending_interrupts_ &= ~static_cast<int>(what);
} }
// Getter and setter for the disable break state. // Getter and setter for the disable break state.
@ -307,6 +350,15 @@ class Debug {
// Mirror cache handling. // Mirror cache handling.
static void ClearMirrorCache(); static void ClearMirrorCache();
// Script cache handling.
static void CreateScriptCache();
static void DestroyScriptCache();
static void AddScriptToScriptCache(Handle<Script> script);
static Handle<FixedArray> GetLoadedScripts();
// Garbage collection notifications.
static void AfterGarbageCollection();
// Code generation assumptions. // Code generation assumptions.
static const int kIa32CallInstructionLength = 5; static const int kIa32CallInstructionLength = 5;
static const int kIa32JSReturnSequenceLength = 6; static const int kIa32JSReturnSequenceLength = 6;
@ -343,6 +395,11 @@ class Debug {
// Boolean state indicating whether any break points are set. // Boolean state indicating whether any break points are set.
static bool has_break_points_; static bool has_break_points_;
// Cache of all scripts in the heap.
static ScriptCache* script_cache_;
// List of active debug info objects.
static DebugInfoListNode* debug_info_list_; static DebugInfoListNode* debug_info_list_;
static bool disable_break_; static bool disable_break_;
@ -382,8 +439,8 @@ class Debug {
// Top debugger entry. // Top debugger entry.
EnterDebugger* debugger_entry_; EnterDebugger* debugger_entry_;
// Preemption happened while debugging. // Pending interrupts scheduled while debugging.
bool preemption_pending_; int pending_interrupts_;
}; };
// Storage location for registers when handling debug break calls // Storage location for registers when handling debug break calls
@ -532,12 +589,15 @@ class Debugger {
static Handle<Object> MakeCompileEvent(Handle<Script> script, static Handle<Object> MakeCompileEvent(Handle<Script> script,
bool before, bool before,
bool* caught_exception); bool* caught_exception);
static Handle<Object> MakeScriptCollectedEvent(int id,
bool* caught_exception);
static void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue); static void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue);
static void OnException(Handle<Object> exception, bool uncaught); static void OnException(Handle<Object> exception, bool uncaught);
static void OnBeforeCompile(Handle<Script> script); static void OnBeforeCompile(Handle<Script> script);
static void OnAfterCompile(Handle<Script> script, static void OnAfterCompile(Handle<Script> script,
Handle<JSFunction> fun); Handle<JSFunction> fun);
static void OnNewFunction(Handle<JSFunction> fun); static void OnNewFunction(Handle<JSFunction> fun);
static void OnScriptCollected(int id);
static void ProcessDebugEvent(v8::DebugEvent event, static void ProcessDebugEvent(v8::DebugEvent event,
Handle<JSObject> event_data, Handle<JSObject> event_data,
bool auto_continue); bool auto_continue);
@ -578,7 +638,7 @@ class Debugger {
ScopedLock with(debugger_access_); ScopedLock with(debugger_access_);
// Check whether the message handler was been cleared. // Check whether the message handler was been cleared.
if (message_handler_cleared_) { if (debugger_unload_pending_) {
UnloadDebugger(); UnloadDebugger();
} }
@ -595,6 +655,7 @@ class Debugger {
private: private:
static bool IsDebuggerActive(); static bool IsDebuggerActive();
static void ListenersChanged();
static Mutex* debugger_access_; // Mutex guarding debugger variables. static Mutex* debugger_access_; // Mutex guarding debugger variables.
static Handle<Object> event_listener_; // Global handle to listener. static Handle<Object> event_listener_; // Global handle to listener.
@ -603,7 +664,7 @@ class Debugger {
static bool is_loading_debugger_; // Are we loading the debugger? static bool is_loading_debugger_; // Are we loading the debugger?
static bool never_unload_debugger_; // Can we unload the debugger? static bool never_unload_debugger_; // Can we unload the debugger?
static v8::Debug::MessageHandler2 message_handler_; static v8::Debug::MessageHandler2 message_handler_;
static bool message_handler_cleared_; // Was message handler cleared? static bool debugger_unload_pending_; // Was message handler cleared?
static v8::Debug::HostDispatchHandler host_dispatch_handler_; static v8::Debug::HostDispatchHandler host_dispatch_handler_;
static int host_dispatch_micros_; static int host_dispatch_micros_;
@ -626,7 +687,8 @@ class EnterDebugger BASE_EMBEDDED {
EnterDebugger() EnterDebugger()
: prev_(Debug::debugger_entry()), : prev_(Debug::debugger_entry()),
has_js_frames_(!it_.done()) { has_js_frames_(!it_.done()) {
ASSERT(prev_ == NULL ? !Debug::preemption_pending() : true); ASSERT(prev_ != NULL || !Debug::is_interrupt_pending(PREEMPT));
ASSERT(prev_ != NULL || !Debug::is_interrupt_pending(DEBUGBREAK));
// Link recursive debugger entry. // Link recursive debugger entry.
Debug::set_debugger_entry(this); Debug::set_debugger_entry(this);
@ -656,22 +718,42 @@ class EnterDebugger BASE_EMBEDDED {
// Restore to the previous break state. // Restore to the previous break state.
Debug::SetBreak(break_frame_id_, break_id_); Debug::SetBreak(break_frame_id_, break_id_);
// Request preemption when leaving the last debugger entry and a preemption // Check for leaving the debugger.
// had been recorded while debugging. This is to avoid starvation in some if (prev_ == NULL) {
// debugging scenarios. // Clear mirror cache when leaving the debugger. Skip this if there is a
if (prev_ == NULL && Debug::preemption_pending()) { // pending exception as clearing the mirror cache calls back into
StackGuard::Preempt(); // JavaScript. This can happen if the v8::Debug::Call is used in which
Debug::set_preemption_pending(false); // case the exception should end up in the calling code.
} if (!Top::has_pending_exception()) {
// Try to avoid any pending debug break breaking in the clear mirror
// cache JavaScript code.
if (StackGuard::IsDebugBreak()) {
Debug::set_interrupts_pending(DEBUGBREAK);
StackGuard::Continue(DEBUGBREAK);
}
Debug::ClearMirrorCache();
}
// If there are commands in the queue when leaving the debugger request that // Request preemption and debug break when leaving the last debugger entry
// these commands are processed. // if any of these where recorded while debugging.
if (prev_ == NULL && Debugger::HasCommands()) { if (Debug::is_interrupt_pending(PREEMPT)) {
StackGuard::DebugCommand(); // This re-scheduling of preemption is to avoid starvation in some
} // debugging scenarios.
Debug::clear_interrupt_pending(PREEMPT);
StackGuard::Preempt();
}
if (Debug::is_interrupt_pending(DEBUGBREAK)) {
Debug::clear_interrupt_pending(DEBUGBREAK);
StackGuard::DebugBreak();
}
// If leaving the debugger with the debugger no longer active unload it. // If there are commands in the queue when leaving the debugger request
if (prev_ == NULL) { // that these commands are processed.
if (Debugger::HasCommands()) {
StackGuard::DebugCommand();
}
// If leaving the debugger with the debugger no longer active unload it.
if (!Debugger::IsDebuggerActive()) { if (!Debugger::IsDebuggerActive()) {
Debugger::UnloadDebugger(); Debugger::UnloadDebugger();
} }

12
deps/v8/src/disassembler.cc

@ -36,16 +36,18 @@
#include "serialize.h" #include "serialize.h"
#include "string-stream.h" #include "string-stream.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
#ifdef ENABLE_DISASSEMBLER #ifdef ENABLE_DISASSEMBLER
void Disassembler::Dump(FILE* f, byte* begin, byte* end) { void Disassembler::Dump(FILE* f, byte* begin, byte* end) {
for (byte* pc = begin; pc < end; pc++) { for (byte* pc = begin; pc < end; pc++) {
if (f == NULL) { if (f == NULL) {
PrintF("%p %4d %02x\n", pc, pc - begin, *pc); PrintF("%" V8PRIxPTR " %4" V8PRIdPTR " %02x\n", pc, pc - begin, *pc);
} else { } else {
fprintf(f, "%p %4d %02x\n", pc, pc - begin, *pc); fprintf(f, "%" V8PRIxPTR " %4" V8PRIdPTR " %02x\n",
reinterpret_cast<uintptr_t>(pc), pc - begin, *pc);
} }
} }
} }
@ -144,8 +146,8 @@ static int DecodeIt(FILE* f,
// raw pointer embedded in code stream, e.g., jump table // raw pointer embedded in code stream, e.g., jump table
byte* ptr = *reinterpret_cast<byte**>(pc); byte* ptr = *reinterpret_cast<byte**>(pc);
OS::SNPrintF(decode_buffer, OS::SNPrintF(decode_buffer,
"%08x jump table entry %4d", "%08" V8PRIxPTR " jump table entry %4" V8PRIdPTR,
reinterpret_cast<int32_t>(ptr), ptr,
ptr - begin); ptr - begin);
pc += 4; pc += 4;
} else { } else {

3
deps/v8/src/disassembler.h

@ -28,7 +28,8 @@
#ifndef V8_DISASSEMBLER_H_ #ifndef V8_DISASSEMBLER_H_
#define V8_DISASSEMBLER_H_ #define V8_DISASSEMBLER_H_
namespace v8 { namespace internal { namespace v8 {
namespace internal {
class Disassembler : public AllStatic { class Disassembler : public AllStatic {
public: public:

44
deps/v8/src/execution.cc

@ -43,7 +43,8 @@
#include "debug.h" #include "debug.h"
#include "v8threads.h" #include "v8threads.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
static Handle<Object> Invoke(bool construct, static Handle<Object> Invoke(bool construct,
@ -188,6 +189,24 @@ Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) {
} }
Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) {
ASSERT(!object->IsJSFunction());
// If you return a function from here, it will be called when an
// attempt is made to call the given object as a constructor.
// Objects created through the API can have an instance-call handler
// that should be used when calling the object as a function.
if (object->IsHeapObject() &&
HeapObject::cast(*object)->map()->has_instance_call_handler()) {
return Handle<JSFunction>(
Top::global_context()->call_as_constructor_delegate());
}
return Factory::undefined_value();
}
// Static state for stack guards. // Static state for stack guards.
StackGuard::ThreadLocal StackGuard::thread_local_; StackGuard::ThreadLocal StackGuard::thread_local_;
@ -569,20 +588,7 @@ Object* Execution::DebugBreakHelper() {
return Heap::undefined_value(); return Heap::undefined_value();
} }
// Don't break in system functions. If the current function is // Collect the break state before clearing the flags.
// either in the builtins object of some context or is in the debug
// context just return with the debug break stack guard active.
JavaScriptFrameIterator it;
JavaScriptFrame* frame = it.frame();
Object* fun = frame->function();
if (fun->IsJSFunction()) {
GlobalObject* global = JSFunction::cast(fun)->context()->global();
if (global->IsJSBuiltinsObject() || Debug::IsDebugGlobal(global)) {
return Heap::undefined_value();
}
}
// Check for debug command break only.
bool debug_command_only = bool debug_command_only =
StackGuard::IsDebugCommand() && !StackGuard::IsDebugBreak(); StackGuard::IsDebugCommand() && !StackGuard::IsDebugBreak();
@ -590,11 +596,6 @@ Object* Execution::DebugBreakHelper() {
StackGuard::Continue(DEBUGBREAK); StackGuard::Continue(DEBUGBREAK);
StackGuard::Continue(DEBUGCOMMAND); StackGuard::Continue(DEBUGCOMMAND);
// If debug command only and already in debugger ignore it.
if (debug_command_only && Debug::InDebugger()) {
return Heap::undefined_value();
}
HandleScope scope; HandleScope scope;
// Enter the debugger. Just continue if we fail to enter the debugger. // Enter the debugger. Just continue if we fail to enter the debugger.
EnterDebugger debugger; EnterDebugger debugger;
@ -602,7 +603,8 @@ Object* Execution::DebugBreakHelper() {
return Heap::undefined_value(); return Heap::undefined_value();
} }
// Notify the debug event listeners. // Notify the debug event listeners. Indicate auto continue if the break was
// a debug command break.
Debugger::OnDebugBreak(Factory::undefined_value(), debug_command_only); Debugger::OnDebugBreak(Factory::undefined_value(), debug_command_only);
// Return to continue execution. // Return to continue execution.

7
deps/v8/src/execution.h

@ -28,7 +28,8 @@
#ifndef V8_EXECUTION_H_ #ifndef V8_EXECUTION_H_
#define V8_EXECUTION_H_ #define V8_EXECUTION_H_
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// Flag used to set the interrupt causes. // Flag used to set the interrupt causes.
@ -129,6 +130,10 @@ class Execution : public AllStatic {
// Get a function delegate (or undefined) for the given non-function // Get a function delegate (or undefined) for the given non-function
// object. Used for support calling objects as functions. // object. Used for support calling objects as functions.
static Handle<Object> GetFunctionDelegate(Handle<Object> object); static Handle<Object> GetFunctionDelegate(Handle<Object> object);
// Get a function delegate (or undefined) for the given non-function
// object. Used for support calling objects as constructors.
static Handle<Object> GetConstructorDelegate(Handle<Object> object);
}; };

14
deps/v8/src/factory.cc

@ -33,7 +33,8 @@
#include "factory.h" #include "factory.h"
#include "macro-assembler.h" #include "macro-assembler.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
Handle<FixedArray> Factory::NewFixedArray(int size, PretenureFlag pretenure) { Handle<FixedArray> Factory::NewFixedArray(int size, PretenureFlag pretenure) {
@ -176,9 +177,12 @@ Handle<Script> Factory::NewScript(Handle<String> source) {
script->set_column_offset(Smi::FromInt(0)); script->set_column_offset(Smi::FromInt(0));
script->set_data(Heap::undefined_value()); script->set_data(Heap::undefined_value());
script->set_context_data(Heap::undefined_value()); script->set_context_data(Heap::undefined_value());
script->set_type(Smi::FromInt(SCRIPT_TYPE_NORMAL)); script->set_type(Smi::FromInt(Script::TYPE_NORMAL));
script->set_compilation_type(Smi::FromInt(Script::COMPILATION_TYPE_HOST));
script->set_wrapper(*wrapper); script->set_wrapper(*wrapper);
script->set_line_ends(Heap::undefined_value()); script->set_line_ends(Heap::undefined_value());
script->set_eval_from_function(Heap::undefined_value());
script->set_eval_from_instructions_offset(Smi::FromInt(0));
return script; return script;
} }
@ -509,8 +513,10 @@ Handle<JSFunction> Factory::NewFunctionWithPrototype(Handle<String> name,
} }
Handle<Code> Factory::NewCode(const CodeDesc& desc, ScopeInfo<>* sinfo, Handle<Code> Factory::NewCode(const CodeDesc& desc,
Code::Flags flags, Handle<Object> self_ref) { ZoneScopeInfo* sinfo,
Code::Flags flags,
Handle<Object> self_ref) {
CALL_HEAP_FUNCTION(Heap::CreateCode(desc, sinfo, flags, self_ref), Code); CALL_HEAP_FUNCTION(Heap::CreateCode(desc, sinfo, flags, self_ref), Code);
} }

10
deps/v8/src/factory.h

@ -29,8 +29,10 @@
#define V8_FACTORY_H_ #define V8_FACTORY_H_
#include "heap.h" #include "heap.h"
#include "zone-inl.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// Interface for handle based allocation. // Interface for handle based allocation.
@ -202,8 +204,10 @@ class Factory : public AllStatic {
Handle<JSFunction> boilerplate, Handle<JSFunction> boilerplate,
Handle<Context> context); Handle<Context> context);
static Handle<Code> NewCode(const CodeDesc& desc, ScopeInfo<>* sinfo, static Handle<Code> NewCode(const CodeDesc& desc,
Code::Flags flags, Handle<Object> self_reference); ZoneScopeInfo* sinfo,
Code::Flags flags,
Handle<Object> self_reference);
static Handle<Code> CopyCode(Handle<Code> code); static Handle<Code> CopyCode(Handle<Code> code);

6
deps/v8/src/flag-definitions.h

@ -133,6 +133,9 @@ DEFINE_bool(strict, false, "strict error checking")
DEFINE_int(min_preparse_length, 1024, DEFINE_int(min_preparse_length, 1024,
"Minimum length for automatic enable preparsing") "Minimum length for automatic enable preparsing")
// compilation-cache.cc
DEFINE_bool(compilation_cache, true, "enable compilation cache")
// debug.cc // debug.cc
DEFINE_bool(remote_debugging, false, "enable remote debugging") DEFINE_bool(remote_debugging, false, "enable remote debugging")
DEFINE_bool(trace_debug_json, false, "trace debugging JSON request/response") DEFINE_bool(trace_debug_json, false, "trace debugging JSON request/response")
@ -333,6 +336,9 @@ DEFINE_bool(prof, false,
"Log statistical profiling information (implies --log-code).") "Log statistical profiling information (implies --log-code).")
DEFINE_bool(prof_auto, true, DEFINE_bool(prof_auto, true,
"Used with --prof, starts profiling automatically") "Used with --prof, starts profiling automatically")
DEFINE_bool(prof_lazy, false,
"Used with --prof, only does sampling and logging"
" when profiler is active (implies --noprof_auto).")
DEFINE_bool(log_regexp, false, "Log regular expression execution.") DEFINE_bool(log_regexp, false, "Log regular expression execution.")
DEFINE_bool(sliding_state_window, false, DEFINE_bool(sliding_state_window, false,
"Update sliding state window counters.") "Update sliding state window counters.")

7
deps/v8/src/flags.cc

@ -35,7 +35,8 @@
#include "string-stream.h" #include "string-stream.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// Define all of our flags. // Define all of our flags.
#define FLAG_MODE_DEFINE #define FLAG_MODE_DEFINE
@ -86,9 +87,9 @@ struct Flag {
return *reinterpret_cast<const char**>(valptr_); return *reinterpret_cast<const char**>(valptr_);
} }
void set_string_value(const char *value, bool owns_ptr) { void set_string_value(const char* value, bool owns_ptr) {
ASSERT(type_ == TYPE_STRING); ASSERT(type_ == TYPE_STRING);
const char **ptr = reinterpret_cast<const char **>(valptr_); const char** ptr = reinterpret_cast<const char**>(valptr_);
if (owns_ptr_ && *ptr != NULL) DeleteArray(*ptr); if (owns_ptr_ && *ptr != NULL) DeleteArray(*ptr);
*ptr = value; *ptr = value;
owns_ptr_ = owns_ptr; owns_ptr_ = owns_ptr;

3
deps/v8/src/flags.h

@ -29,7 +29,8 @@
#include "checks.h" #include "checks.h"
namespace v8 { namespace internal { namespace v8 {
namespace internal {
// Declare all of our flags. // Declare all of our flags.
#define FLAG_MODE_DECLARE #define FLAG_MODE_DECLARE

265
deps/v8/src/frame-element.h

@ -0,0 +1,265 @@
// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_FRAME_ELEMENT_H_
#define V8_FRAME_ELEMENT_H_
#include "register-allocator-inl.h"
namespace v8 {
namespace internal {
// -------------------------------------------------------------------------
// Virtual frame elements
//
// The internal elements of the virtual frames. There are several kinds of
// elements:
// * Invalid: elements that are uninitialized or not actually part
// of the virtual frame. They should not be read.
// * Memory: an element that resides in the actual frame. Its address is
// given by its position in the virtual frame.
// * Register: an element that resides in a register.
// * Constant: an element whose value is known at compile time.
class FrameElement BASE_EMBEDDED {
public:
enum SyncFlag {
NOT_SYNCED,
SYNCED
};
// The default constructor creates an invalid frame element.
FrameElement() {
value_ = StaticTypeField::encode(StaticType::UNKNOWN_TYPE)
| TypeField::encode(INVALID)
| CopiedField::encode(false)
| SyncedField::encode(false)
| DataField::encode(0);
}
// Factory function to construct an invalid frame element.
static FrameElement InvalidElement() {
FrameElement result;
return result;
}
// Factory function to construct an in-memory frame element.
static FrameElement MemoryElement() {
FrameElement result(MEMORY, no_reg, SYNCED);
return result;
}
// Factory function to construct an in-register frame element.
static FrameElement RegisterElement(Register reg,
SyncFlag is_synced,
StaticType static_type = StaticType()) {
return FrameElement(REGISTER, reg, is_synced, static_type);
}
// Factory function to construct a frame element whose value is known at
// compile time.
static FrameElement ConstantElement(Handle<Object> value,
SyncFlag is_synced) {
FrameElement result(value, is_synced);
return result;
}
// Static indirection table for handles to constants. If a frame
// element represents a constant, the data contains an index into
// this table of handles to the actual constants.
typedef ZoneList<Handle<Object> > ZoneObjectList;
static ZoneObjectList* ConstantList() {
static ZoneObjectList list(10);
return &list;
}
// Clear the constants indirection table.
static void ClearConstantList() {
ConstantList()->Clear();
}
bool is_synced() const { return SyncedField::decode(value_); }
void set_sync() {
ASSERT(type() != MEMORY);
value_ = value_ | SyncedField::encode(true);
}
void clear_sync() {
ASSERT(type() != MEMORY);
value_ = value_ & ~SyncedField::mask();
}
bool is_valid() const { return type() != INVALID; }
bool is_memory() const { return type() == MEMORY; }
bool is_register() const { return type() == REGISTER; }
bool is_constant() const { return type() == CONSTANT; }
bool is_copy() const { return type() == COPY; }
bool is_copied() const { return CopiedField::decode(value_); }
void set_copied() { value_ = value_ | CopiedField::encode(true); }
void clear_copied() { value_ = value_ & ~CopiedField::mask(); }
Register reg() const {
ASSERT(is_register());
uint32_t reg = DataField::decode(value_);
Register result;
result.code_ = reg;
return result;
}
Handle<Object> handle() const {
ASSERT(is_constant());
return ConstantList()->at(DataField::decode(value_));
}
int index() const {
ASSERT(is_copy());
return DataField::decode(value_);
}
StaticType static_type() {
return StaticType(StaticTypeField::decode(value_));
}
void set_static_type(StaticType static_type) {
value_ = value_ & ~StaticTypeField::mask();
value_ = value_ | StaticTypeField::encode(static_type.static_type_);
}
bool Equals(FrameElement other) {
uint32_t masked_difference = (value_ ^ other.value_) & ~CopiedField::mask();
if (!masked_difference) {
// The elements are equal if they agree exactly except on copied field.
return true;
} else {
// If two constants have the same value, and agree otherwise, return true.
return !(masked_difference & ~DataField::mask()) &&
is_constant() &&
handle().is_identical_to(other.handle());
}
}
// Test if two FrameElements refer to the same memory or register location.
bool SameLocation(FrameElement* other) {
if (type() == other->type()) {
if (value_ == other->value_) return true;
if (is_constant() && handle().is_identical_to(other->handle())) {
return true;
}
}
return false;
}
// Given a pair of non-null frame element pointers, return one of them
// as an entry frame candidate or null if they are incompatible.
FrameElement* Combine(FrameElement* other) {
// If either is invalid, the result is.
if (!is_valid()) return this;
if (!other->is_valid()) return other;
if (!SameLocation(other)) return NULL;
// If either is unsynced, the result is. The result static type is
// the merge of the static types. It's safe to set it on one of the
// frame elements, and harmless too (because we are only going to
// merge the reaching frames and will ensure that the types are
// coherent, and changing the static type does not emit code).
FrameElement* result = is_synced() ? other : this;
result->set_static_type(static_type().merge(other->static_type()));
return result;
}
private:
enum Type {
INVALID,
MEMORY,
REGISTER,
CONSTANT,
COPY
};
// Used to construct memory and register elements.
FrameElement(Type type, Register reg, SyncFlag is_synced) {
value_ = StaticTypeField::encode(StaticType::UNKNOWN_TYPE)
| TypeField::encode(type)
| CopiedField::encode(false)
| SyncedField::encode(is_synced != NOT_SYNCED)
| DataField::encode(reg.code_ > 0 ? reg.code_ : 0);
}
FrameElement(Type type, Register reg, SyncFlag is_synced, StaticType stype) {
value_ = StaticTypeField::encode(stype.static_type_)
| TypeField::encode(type)
| CopiedField::encode(false)
| SyncedField::encode(is_synced != NOT_SYNCED)
| DataField::encode(reg.code_ > 0 ? reg.code_ : 0);
}
// Used to construct constant elements.
FrameElement(Handle<Object> value, SyncFlag is_synced) {
value_ = StaticTypeField::encode(StaticType::TypeOf(*value).static_type_)
| TypeField::encode(CONSTANT)
| CopiedField::encode(false)
| SyncedField::encode(is_synced != NOT_SYNCED)
| DataField::encode(ConstantList()->length());
ConstantList()->Add(value);
}
Type type() const { return TypeField::decode(value_); }
void set_type(Type type) {
value_ = value_ & ~TypeField::mask();
value_ = value_ | TypeField::encode(type);
}
void set_index(int new_index) {
ASSERT(is_copy());
value_ = value_ & ~DataField::mask();
value_ = value_ | DataField::encode(new_index);
}
void set_reg(Register new_reg) {
ASSERT(is_register());
value_ = value_ & ~DataField::mask();
value_ = value_ | DataField::encode(new_reg.code_);
}
// Encode static type, type, copied, synced and data in one 32 bit integer.
uint32_t value_;
class StaticTypeField: public BitField<StaticType::StaticTypeEnum, 0, 3> {};
class TypeField: public BitField<Type, 3, 3> {};
class CopiedField: public BitField<uint32_t, 6, 1> {};
class SyncedField: public BitField<uint32_t, 7, 1> {};
class DataField: public BitField<uint32_t, 8, 32 - 9> {};
friend class VirtualFrame;
};
} } // namespace v8::internal
#endif // V8_FRAME_ELEMENT_H_

3
deps/v8/src/frames-inl.h

@ -38,7 +38,8 @@
#include "arm/frames-arm.h" #include "arm/frames-arm.h"
#endif #endif
namespace v8 { namespace internal { namespace v8 {
namespace internal {
inline Address StackHandler::address() const { inline Address StackHandler::address() const {

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save