summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--deps/v8/ChangeLog43
-rw-r--r--deps/v8/Makefile5
-rw-r--r--deps/v8/benchmarks/crypto.js2
-rw-r--r--deps/v8/benchmarks/earley-boyer.js50
-rw-r--r--deps/v8/benchmarks/regexp.js6
-rw-r--r--deps/v8/build/all.gyp10
-rw-r--r--deps/v8/build/common.gypi10
-rw-r--r--deps/v8/build/standalone.gypi7
-rw-r--r--deps/v8/include/v8.h4
-rw-r--r--deps/v8/samples/shell.cc6
-rw-r--r--deps/v8/src/accessors.cc2
-rw-r--r--deps/v8/src/arm/assembler-arm.cc8
-rw-r--r--deps/v8/src/arm/builtins-arm.cc16
-rw-r--r--deps/v8/src/arm/code-stubs-arm.cc225
-rw-r--r--deps/v8/src/arm/full-codegen-arm.cc619
-rw-r--r--deps/v8/src/arm/ic-arm.cc6
-rw-r--r--deps/v8/src/arm/lithium-codegen-arm.cc15
-rw-r--r--deps/v8/src/arm/macro-assembler-arm.cc40
-rw-r--r--deps/v8/src/arm/macro-assembler-arm.h10
-rw-r--r--deps/v8/src/arm/regexp-macro-assembler-arm.cc2
-rw-r--r--deps/v8/src/arm/stub-cache-arm.cc6
-rw-r--r--deps/v8/src/array.js63
-rw-r--r--deps/v8/src/ast.cc34
-rw-r--r--deps/v8/src/ast.h134
-rw-r--r--deps/v8/src/bootstrapper.cc20
-rw-r--r--deps/v8/src/checks.h6
-rw-r--r--deps/v8/src/contexts.cc11
-rw-r--r--deps/v8/src/contexts.h31
-rw-r--r--deps/v8/src/conversions.h4
-rw-r--r--deps/v8/src/d8.cc14
-rw-r--r--deps/v8/src/d8.js2
-rw-r--r--deps/v8/src/date.js11
-rw-r--r--deps/v8/src/elements.cc1
-rw-r--r--deps/v8/src/extensions/externalize-string-extension.cc6
-rw-r--r--deps/v8/src/full-codegen.cc92
-rw-r--r--deps/v8/src/full-codegen.h89
-rw-r--r--deps/v8/src/heap.cc84
-rw-r--r--deps/v8/src/heap.h25
-rw-r--r--deps/v8/src/hydrogen-instructions.cc18
-rw-r--r--deps/v8/src/hydrogen-instructions.h27
-rw-r--r--deps/v8/src/hydrogen.cc450
-rw-r--r--deps/v8/src/hydrogen.h12
-rw-r--r--deps/v8/src/ia32/builtins-ia32.cc14
-rw-r--r--deps/v8/src/ia32/code-stubs-ia32.cc109
-rw-r--r--deps/v8/src/ia32/full-codegen-ia32.cc671
-rw-r--r--deps/v8/src/ia32/ic-ia32.cc4
-rw-r--r--deps/v8/src/ia32/lithium-codegen-ia32.cc12
-rw-r--r--deps/v8/src/ia32/macro-assembler-ia32.cc50
-rw-r--r--deps/v8/src/ia32/macro-assembler-ia32.h21
-rw-r--r--deps/v8/src/ia32/regexp-macro-assembler-ia32.cc2
-rw-r--r--deps/v8/src/ia32/stub-cache-ia32.cc2
-rw-r--r--deps/v8/src/isolate.cc5
-rw-r--r--deps/v8/src/isolate.h4
-rw-r--r--deps/v8/src/json.js5
-rw-r--r--deps/v8/src/jsregexp.cc8
-rw-r--r--deps/v8/src/jsregexp.h2
-rw-r--r--deps/v8/src/liveedit.cc7
-rw-r--r--deps/v8/src/macros.py18
-rw-r--r--deps/v8/src/math.js14
-rw-r--r--deps/v8/src/messages.js570
-rw-r--r--deps/v8/src/mips/assembler-mips.cc46
-rw-r--r--deps/v8/src/mips/builtins-mips.cc12
-rw-r--r--deps/v8/src/mips/code-stubs-mips.cc238
-rw-r--r--deps/v8/src/mips/constants-mips.h6
-rw-r--r--deps/v8/src/mips/frames-mips.h113
-rw-r--r--deps/v8/src/mips/full-codegen-mips.cc206
-rw-r--r--deps/v8/src/mips/ic-mips.cc6
-rw-r--r--deps/v8/src/mips/macro-assembler-mips.cc148
-rw-r--r--deps/v8/src/mips/macro-assembler-mips.h21
-rw-r--r--deps/v8/src/mips/regexp-macro-assembler-mips.cc2
-rw-r--r--deps/v8/src/mips/simulator-mips.cc17
-rw-r--r--deps/v8/src/mips/stub-cache-mips.cc6
-rw-r--r--deps/v8/src/mksnapshot.cc12
-rw-r--r--deps/v8/src/objects-inl.h16
-rw-r--r--deps/v8/src/objects.cc2
-rw-r--r--deps/v8/src/objects.h5
-rw-r--r--deps/v8/src/parser.cc120
-rw-r--r--deps/v8/src/parser.h11
-rw-r--r--deps/v8/src/platform-linux.cc6
-rw-r--r--deps/v8/src/prettyprinter.cc98
-rw-r--r--deps/v8/src/prettyprinter.h3
-rw-r--r--deps/v8/src/profile-generator.cc34
-rw-r--r--deps/v8/src/profile-generator.h6
-rw-r--r--deps/v8/src/regexp.js6
-rw-r--r--deps/v8/src/runtime-profiler.cc6
-rw-r--r--deps/v8/src/runtime.cc125
-rw-r--r--deps/v8/src/runtime.h13
-rw-r--r--deps/v8/src/runtime.js1
-rw-r--r--deps/v8/src/scanner-base.h2
-rw-r--r--deps/v8/src/scanner.h2
-rw-r--r--deps/v8/src/scopeinfo.cc65
-rw-r--r--deps/v8/src/scopes.cc151
-rw-r--r--deps/v8/src/scopes.h19
-rw-r--r--deps/v8/src/spaces-inl.h3
-rw-r--r--deps/v8/src/string.js60
-rw-r--r--deps/v8/src/stub-cache.h2
-rw-r--r--deps/v8/src/token.h1
-rw-r--r--deps/v8/src/uri.js7
-rw-r--r--deps/v8/src/v8natives.js261
-rw-r--r--deps/v8/src/variables.cc31
-rw-r--r--deps/v8/src/variables.h55
-rw-r--r--deps/v8/src/version.cc6
-rw-r--r--deps/v8/src/weakmap.js17
-rw-r--r--deps/v8/src/x64/builtins-x64.cc6
-rw-r--r--deps/v8/src/x64/code-stubs-x64.cc109
-rw-r--r--deps/v8/src/x64/full-codegen-x64.cc663
-rw-r--r--deps/v8/src/x64/ic-x64.cc2
-rw-r--r--deps/v8/src/x64/lithium-codegen-x64.cc11
-rw-r--r--deps/v8/src/x64/macro-assembler-x64.cc58
-rw-r--r--deps/v8/src/x64/macro-assembler-x64.h13
-rw-r--r--deps/v8/src/x64/regexp-macro-assembler-x64.cc2
-rw-r--r--deps/v8/src/x64/stub-cache-x64.cc4
-rw-r--r--deps/v8/test/cctest/cctest.gyp15
-rw-r--r--deps/v8/test/cctest/cctest.status4
-rw-r--r--deps/v8/test/cctest/test-api.cc26
-rw-r--r--deps/v8/test/cctest/test-assembler-arm.cc14
-rw-r--r--deps/v8/test/cctest/test-assembler-ia32.cc14
-rw-r--r--deps/v8/test/cctest/test-assembler-mips.cc18
-rw-r--r--deps/v8/test/cctest/test-assembler-x64.cc14
-rw-r--r--deps/v8/test/cctest/test-compiler.cc4
-rw-r--r--deps/v8/test/cctest/test-disasm-mips.cc63
-rw-r--r--deps/v8/test/cctest/test-regexp.cc9
-rw-r--r--deps/v8/test/cctest/test-strings.cc29
-rw-r--r--deps/v8/test/es5conform/es5conform.status6
-rw-r--r--deps/v8/test/mjsunit/array-constructor.js8
-rw-r--r--deps/v8/test/mjsunit/array-iteration.js12
-rw-r--r--deps/v8/test/mjsunit/array-sort.js2
-rw-r--r--deps/v8/test/mjsunit/bugs/618.js4
-rw-r--r--deps/v8/test/mjsunit/bugs/bug-618.js6
-rw-r--r--deps/v8/test/mjsunit/builtins.js82
-rw-r--r--deps/v8/test/mjsunit/compiler/delete.js7
-rw-r--r--deps/v8/test/mjsunit/compiler/global-accessors.js2
-rw-r--r--deps/v8/test/mjsunit/const-redecl.js4
-rw-r--r--deps/v8/test/mjsunit/d8-os.js5
-rw-r--r--deps/v8/test/mjsunit/date-parse.js2
-rw-r--r--deps/v8/test/mjsunit/debug-compile-event.js2
-rw-r--r--deps/v8/test/mjsunit/debug-evaluate-recursive.js2
-rw-r--r--deps/v8/test/mjsunit/debug-handle.js4
-rw-r--r--deps/v8/test/mjsunit/debug-listbreakpoints.js2
-rw-r--r--deps/v8/test/mjsunit/debug-references.js4
-rw-r--r--deps/v8/test/mjsunit/debug-return-value.js8
-rw-r--r--deps/v8/test/mjsunit/debug-stepin-call-function-stub.js4
-rw-r--r--deps/v8/test/mjsunit/debug-stepin-constructor.js2
-rw-r--r--deps/v8/test/mjsunit/delete-in-with.js2
-rw-r--r--deps/v8/test/mjsunit/function-source.js2
-rw-r--r--deps/v8/test/mjsunit/get-own-property-descriptor.js2
-rw-r--r--deps/v8/test/mjsunit/global-deleted-property-keyed.js2
-rw-r--r--deps/v8/test/mjsunit/harmony/block-conflicts.js126
-rw-r--r--deps/v8/test/mjsunit/harmony/block-leave.js225
-rw-r--r--deps/v8/test/mjsunit/harmony/block-let-crankshaft.js63
-rw-r--r--deps/v8/test/mjsunit/harmony/block-let-declaration.js2
-rw-r--r--deps/v8/test/mjsunit/harmony/block-let-semantics.js138
-rw-r--r--deps/v8/test/mjsunit/harmony/debug-blockscopes.js121
-rw-r--r--deps/v8/test/mjsunit/harmony/weakmaps.js1
-rw-r--r--deps/v8/test/mjsunit/html-string-funcs.js2
-rw-r--r--deps/v8/test/mjsunit/in.js2
-rw-r--r--deps/v8/test/mjsunit/instanceof.js6
-rw-r--r--deps/v8/test/mjsunit/keyed-storage-extend.js2
-rw-r--r--deps/v8/test/mjsunit/mirror-array.js4
-rw-r--r--deps/v8/test/mjsunit/mirror-function.js2
-rw-r--r--deps/v8/test/mjsunit/mirror-script.js2
-rw-r--r--deps/v8/test/mjsunit/mirror-unresolved-function.js2
-rw-r--r--deps/v8/test/mjsunit/mjsunit.status8
-rw-r--r--deps/v8/test/mjsunit/no-semicolon.js4
-rw-r--r--deps/v8/test/mjsunit/object-define-properties.js2
-rw-r--r--deps/v8/test/mjsunit/object-literal-conversions.js2
-rw-r--r--deps/v8/test/mjsunit/object-literal-overwrite.js4
-rw-r--r--deps/v8/test/mjsunit/object-prevent-extensions.js2
-rw-r--r--deps/v8/test/mjsunit/parse-int-float.js13
-rw-r--r--deps/v8/test/mjsunit/regress/regress-1081309.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-1092.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-1110.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-1213575.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-1215.js36
-rw-r--r--deps/v8/test/mjsunit/regress/regress-1447.js8
-rw-r--r--deps/v8/test/mjsunit/regress/regress-1548.js48
-rw-r--r--deps/v8/test/mjsunit/regress/regress-1647.js43
-rw-r--r--deps/v8/test/mjsunit/regress/regress-1650.js60
-rw-r--r--deps/v8/test/mjsunit/regress/regress-1919169.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-20070207.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-269.js4
-rw-r--r--deps/v8/test/mjsunit/regress/regress-619.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-678525.js8
-rw-r--r--deps/v8/test/mjsunit/regress/regress-696.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-720.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-747.js4
-rw-r--r--deps/v8/test/mjsunit/regress/regress-760-1.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-760-2.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-798.js14
-rw-r--r--deps/v8/test/mjsunit/regress/regress-918.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-925537.js4
-rw-r--r--deps/v8/test/mjsunit/regress/regress-937896.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-94425.js46
-rw-r--r--deps/v8/test/mjsunit/regress/regress-95113.js48
-rw-r--r--deps/v8/test/mjsunit/regress/regress-95485.js42
-rw-r--r--deps/v8/test/mjsunit/regress/regress-fundecl.js44
-rw-r--r--deps/v8/test/mjsunit/setter-on-constructor-prototype.js26
-rw-r--r--deps/v8/test/mjsunit/string-compare-alignment.js5
-rw-r--r--deps/v8/test/mjsunit/string-indexof-1.js4
-rw-r--r--deps/v8/test/mjsunit/string-indexof-2.js6
-rwxr-xr-xdeps/v8/test/mjsunit/string-slices.js11
-rw-r--r--deps/v8/test/mjsunit/string-split.js4
-rwxr-xr-xdeps/v8/test/mjsunit/substr.js2
-rw-r--r--deps/v8/test/mjsunit/this-property-assignment.js2
-rw-r--r--deps/v8/test/mjsunit/try.js4
-rw-r--r--deps/v8/test/mjsunit/unicode-test.js4
-rw-r--r--deps/v8/test/mjsunit/value-wrapper.js14
-rw-r--r--deps/v8/test/mozilla/mozilla.status8
-rw-r--r--deps/v8/tools/gdb-v8-support.py2
-rwxr-xr-xdeps/v8/tools/presubmit.py42
-rwxr-xr-xdeps/v8/tools/process-heap-prof.py6
-rwxr-xr-xdeps/v8/tools/test-wrapper-gypbuild.py16
-rwxr-xr-xdeps/v8/tools/test.py9
213 files changed, 5390 insertions, 2908 deletions
diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog
index 2deff90808..d3e0dc642a 100644
--- a/deps/v8/ChangeLog
+++ b/deps/v8/ChangeLog
@@ -1,3 +1,46 @@
+2011-09-07: Version 3.6.1
+
+ Fixed a bug in abrupt exit from with or catch inside finally.
+
+ Fixed possible crash in FixedDoubleArray::Initialize() (Chromium
+ issue 95113).
+
+ Fixed a bug in Page::GetRegionMaskForSpan (Chromium issue 94425).
+
+ Fixed a few clang warnings (which -Werror treated as errors).
+
+ Performance improvements on all platforms.
+
+
+2011-09-05: Version 3.6.0
+
+ Fixed a bug when optimizing named function expression (issue 1647).
+
+ Fixed a bug when optimizing f.call.apply (issue 1650).
+
+ Made arguments and caller always be null on native functions
+ (issues 1548 and 1643).
+
+ Fixed issue 1648 (cross-compiling x64 targeting ia32).
+
+ Fixed issue 371 (d8 printing of strings containing \0).
+
+ Fixed order of evaluation in arguments to parseInt (issue 1649).
+
+ Fixed a problem with large heap snapshots in Chrome DevTools
+ (issue 1658, chromium issue 89268).
+
+ Upped default maximum heap size from 512M to 700M.
+
+
+2011-08-31: Version 3.5.10
+
+ Added dependency of v8_base on WinSocket2 Windows library in
+ the GYP-build.
+
+ Various bugfixes.
+
+
2011-08-29: Version 3.5.9
Made FromPropertyDescriptor not trigger inherited setters.
diff --git a/deps/v8/Makefile b/deps/v8/Makefile
index 3008779bb3..618bbef1d0 100644
--- a/deps/v8/Makefile
+++ b/deps/v8/Makefile
@@ -98,8 +98,9 @@ CHECKS = $(addsuffix .check,$(BUILDS))
# File where previously used GYPFLAGS are stored.
ENVFILE = $(OUTDIR)/environment
-.PHONY: all clean $(ENVFILE).new \
- $(ARCHES) $(MODES) $(BUILDS) $(addsuffix .clean,$(ARCHES))
+.PHONY: all check clean $(ENVFILE).new \
+ $(ARCHES) $(MODES) $(BUILDS) $(CHECKS) $(addsuffix .clean,$(ARCHES)) \
+ $(addsuffix .check,$(MODES)) $(addsuffix .check,$(ARCHES))
# Target definitions. "all" is the default.
all: $(MODES)
diff --git a/deps/v8/benchmarks/crypto.js b/deps/v8/benchmarks/crypto.js
index ffa69b53bb..531ad456e0 100644
--- a/deps/v8/benchmarks/crypto.js
+++ b/deps/v8/benchmarks/crypto.js
@@ -1406,7 +1406,7 @@ function rng_seed_int(x) {
// Mix in the current time (w/milliseconds) into the pool
function rng_seed_time() {
- // Use pre-computed date to avoid making the benchmark
+ // Use pre-computed date to avoid making the benchmark
// results dependent on the current date.
rng_seed_int(1122926989487);
}
diff --git a/deps/v8/benchmarks/earley-boyer.js b/deps/v8/benchmarks/earley-boyer.js
index 1be480e8ee..b2328d6ba1 100644
--- a/deps/v8/benchmarks/earley-boyer.js
+++ b/deps/v8/benchmarks/earley-boyer.js
@@ -134,7 +134,7 @@ function sc_rempropBang(sym, key) {
/*** META ((export #t)) */
function sc_any2String(o) {
return jsstring2string(sc_toDisplayString(o));
-}
+}
/*** META ((export #t)
(peephole (infix 2 2 "==="))
@@ -923,7 +923,7 @@ function sc_dualAppendBang(l1, l2) {
tmp.cdr = l2;
return l1;
}
-
+
/*** META ((export #t)) */
function sc_appendBang() {
var res = null;
@@ -1163,7 +1163,7 @@ sc_Char.readable2char = {
"us": "\037",
"sp": "\040",
"del": "\177"};
-
+
sc_Char.prototype.toString = function() {
return this.val;
};
@@ -1533,7 +1533,7 @@ function sc_mapBang(proc, l1) {
}
return l1_orig;
}
-
+
/*** META ((export #t)) */
function sc_forEach(proc, l1) {
if (l1 === undefined)
@@ -1871,7 +1871,7 @@ function sc_jsNew(c) {
evalStr += ", arguments[" + i + "]";
evalStr +=")";
return eval(evalStr);
-}
+}
// ======================== RegExp ====================
/*** META ((export #t)) */
@@ -1883,9 +1883,9 @@ function sc_pregexp(re) {
function sc_pregexpMatch(re, s) {
var reg = (re instanceof RegExp) ? re : sc_pregexp(re);
var tmp = reg.exec(sc_string2jsstring(s));
-
+
if (tmp == null) return false;
-
+
var res = null;
for (var i = tmp.length-1; i >= 0; i--) {
if (tmp[i] !== null) {
@@ -1896,7 +1896,7 @@ function sc_pregexpMatch(re, s) {
}
return res;
}
-
+
/*** META ((export #t)) */
function sc_pregexpReplace(re, s1, s2) {
var reg;
@@ -1914,7 +1914,7 @@ function sc_pregexpReplace(re, s1, s2) {
return jss1.replace(reg, jss2);
}
-
+
/*** META ((export pregexp-replace*)) */
function sc_pregexpReplaceAll(re, s1, s2) {
var reg;
@@ -1945,7 +1945,7 @@ function sc_pregexpSplit(re, s) {
return sc_vector2list(tmp);
}
-
+
/* =========================================================================== */
/* Other library stuff */
@@ -2136,7 +2136,7 @@ sc_ErrorInputPort.prototype.getNextChar = function() {
sc_ErrorInputPort.prototype.isCharReady = function() {
return false;
};
-
+
/* .............. String port ..........................*/
@@ -2200,7 +2200,7 @@ sc_Tokenizer.prototype.readToken = function() {
};
sc_Tokenizer.prototype.nextToken = function() {
var port = this.port;
-
+
function isNumberChar(c) {
return (c >= "0" && c <= "9");
};
@@ -2280,7 +2280,7 @@ sc_Tokenizer.prototype.nextToken = function() {
else
return new sc_Token(12/*NUMBER*/, res - 0);
};
-
+
function skipWhitespaceAndComments() {
var done = false;
while (!done) {
@@ -2299,7 +2299,7 @@ sc_Tokenizer.prototype.nextToken = function() {
}
}
};
-
+
function readDot() {
if (isWhitespace(port.peekChar()))
return new sc_Token(10/*DOT*/);
@@ -2429,7 +2429,7 @@ sc_Reader.prototype.read = function() {
while (true) {
var token = tokenizer.peekToken();
-
+
switch (token.type) {
case 2/*CLOSE_PAR*/:
case 4/*CLOSE_BRACE*/:
@@ -2491,7 +2491,7 @@ sc_Reader.prototype.read = function() {
else
throw "bad reference: " + nb;
};
-
+
var tokenizer = this.tokenizer;
var token = tokenizer.readToken();
@@ -2499,7 +2499,7 @@ sc_Reader.prototype.read = function() {
// handle error
if (token.type === 13/*ERROR*/)
throw token.val;
-
+
switch (token.type) {
case 1/*OPEN_PAR*/:
case 3/*OPEN_BRACE*/:
@@ -2550,7 +2550,7 @@ function sc_peekChar(port) {
port = SC_DEFAULT_IN; // THREAD: shared var...
var t = port.peekChar();
return t === SC_EOF_OBJECT? t: new sc_Char(t);
-}
+}
/*** META ((export #t)
(type bool))
*/
@@ -2722,7 +2722,7 @@ sc_StringOutputPort.prototype.close = function() {
function sc_getOutputString(sp) {
return sc_jsstring2string(sp.res);
}
-
+
function sc_ErrorOutputPort() {
}
@@ -2852,7 +2852,7 @@ function sc_newline(p) {
p = SC_DEFAULT_OUT;
p.appendJSString("\n");
}
-
+
/* ------------------ write-char ---------------------------------------------------*/
/*** META ((export #t)) */
@@ -2927,7 +2927,7 @@ sc_Pair.prototype.sc_toWriteCircleString = function(symb, inList) {
}
var res = "";
-
+
if (this[symb] !== undefined) { // implies > 0
this[symb + "use"] = true;
if (inList)
@@ -2939,10 +2939,10 @@ sc_Pair.prototype.sc_toWriteCircleString = function(symb, inList) {
if (!inList)
res += "(";
-
+
// print car
res += sc_genToWriteCircleString(this.car, symb);
-
+
if (sc_isPair(this.cdr)) {
res += " " + this.cdr.sc_toWriteCircleString(symb, true);
} else if (this.cdr !== null) {
@@ -3072,7 +3072,7 @@ function sc_format(s, args) {
p.appendJSString(arguments[j].toString(2));
i += 2; j++;
break;
-
+
case 37:
case 110:
// %, n
@@ -3186,7 +3186,7 @@ function sc_isEqual(o1, o2) {
function sc_number2symbol(x, radix) {
return sc_SYMBOL_PREFIX + sc_number2jsstring(x, radix);
}
-
+
/*** META ((export number->string integer->string)) */
var sc_number2string = sc_number2jsstring;
diff --git a/deps/v8/benchmarks/regexp.js b/deps/v8/benchmarks/regexp.js
index 71b9e6362c..9c83142266 100644
--- a/deps/v8/benchmarks/regexp.js
+++ b/deps/v8/benchmarks/regexp.js
@@ -33,7 +33,7 @@
// the popularity of the pages where it occurs and the number of times
// it is executed while loading each page. Furthermore the literal
// letters in the data are encoded using ROT13 in a way that does not
-// affect how the regexps match their input. Finally the strings are
+// affect how the regexps match their input. Finally the strings are
// scrambled to exercise the regexp engine on different input strings.
@@ -47,7 +47,7 @@ function RegExpSetup() {
regExpBenchmark = new RegExpBenchmark();
RegExpRun(); // run once to get system initialized
}
-
+
function RegExpRun() {
regExpBenchmark.run();
}
@@ -1759,6 +1759,6 @@ function RegExpBenchmark() {
runBlock11();
}
}
-
+
this.run = run;
}
diff --git a/deps/v8/build/all.gyp b/deps/v8/build/all.gyp
index 9c0f05c913..4b2fe52989 100644
--- a/deps/v8/build/all.gyp
+++ b/deps/v8/build/all.gyp
@@ -1,4 +1,4 @@
-# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Copyright 2011 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
@@ -11,13 +11,7 @@
'../preparser/preparser.gyp:*',
'../samples/samples.gyp:*',
'../src/d8.gyp:d8',
- ],
- 'conditions': [
- [ 'component!="shared_library"', {
- 'dependencies': [
- '../test/cctest/cctest.gyp:*',
- ],
- }]
+ '../test/cctest/cctest.gyp:*',
],
}
]
diff --git a/deps/v8/build/common.gypi b/deps/v8/build/common.gypi
index 27fddcf338..9b32608178 100644
--- a/deps/v8/build/common.gypi
+++ b/deps/v8/build/common.gypi
@@ -173,6 +173,14 @@
},
},
}],
+ ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', {
+ 'conditions': [
+ [ 'target_arch=="ia32"', {
+ 'cflags': [ '-m32' ],
+ 'ldflags': [ '-m32' ],
+ }],
+ ],
+ }],
],
'configurations': {
'Debug': {
@@ -207,7 +215,7 @@
'cflags': [ '-I/usr/local/include' ],
}],
['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
- 'cflags': [ '-Wall', '-W', '-Wno-unused-parameter',
+ 'cflags': [ '-Wall', '-Werror', '-W', '-Wno-unused-parameter',
'-Wnon-virtual-dtor' ],
}],
],
diff --git a/deps/v8/build/standalone.gypi b/deps/v8/build/standalone.gypi
index 1442789ad1..cb5e133039 100644
--- a/deps/v8/build/standalone.gypi
+++ b/deps/v8/build/standalone.gypi
@@ -74,15 +74,11 @@
'conditions': [
[ 'OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', {
'target_defaults': {
- 'cflags': [ '-Wall', '-W', '-Wno-unused-parameter',
+ 'cflags': [ '-Wall', '-Werror', '-W', '-Wno-unused-parameter',
'-Wnon-virtual-dtor', '-pthread', '-fno-rtti',
'-fno-exceptions', '-pedantic' ],
'ldflags': [ '-pthread', ],
'conditions': [
- [ 'target_arch=="ia32"', {
- 'cflags': [ '-m32' ],
- 'ldflags': [ '-m32' ],
- }],
[ 'OS=="linux"', {
'cflags': [ '-ansi' ],
}],
@@ -172,6 +168,7 @@
'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES',
'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden
'GCC_THREADSAFE_STATICS': 'NO', # -fno-threadsafe-statics
+ 'GCC_TREAT_WARNINGS_AS_ERRORS': 'YES', # -Werror
'GCC_VERSION': '4.2',
'GCC_WARN_ABOUT_MISSING_NEWLINE': 'YES', # -Wnewline-eof
'MACOSX_DEPLOYMENT_TARGET': '10.4', # -mmacosx-version-min=10.4
diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h
index 5a781607f7..80193c423a 100644
--- a/deps/v8/include/v8.h
+++ b/deps/v8/include/v8.h
@@ -1656,7 +1656,7 @@ class Object : public Value {
V8EXPORT bool IsCallable();
/**
- * Call an Object as a function if a callback is set by the
+ * Call an Object as a function if a callback is set by the
* ObjectTemplate::SetCallAsFunctionHandler method.
*/
V8EXPORT Local<Value> CallAsFunction(Handle<Object> recv,
@@ -3562,7 +3562,7 @@ class V8EXPORT Context {
* // V8 Now no longer locked.
* \endcode
*
- *
+ *
*/
class V8EXPORT Unlocker {
public:
diff --git a/deps/v8/samples/shell.cc b/deps/v8/samples/shell.cc
index 8ed9d032aa..b40eca2f7c 100644
--- a/deps/v8/samples/shell.cc
+++ b/deps/v8/samples/shell.cc
@@ -250,16 +250,14 @@ void RunShell(v8::Handle<v8::Context> context) {
static const int kBufferSize = 256;
// Enter the execution environment before evaluating any code.
v8::Context::Scope context_scope(context);
+ v8::Local<v8::String> name(v8::String::New("(shell)"));
while (true) {
char buffer[kBufferSize];
printf("> ");
char* str = fgets(buffer, kBufferSize, stdin);
if (str == NULL) break;
v8::HandleScope handle_scope;
- ExecuteString(v8::String::New(str),
- v8::String::New("(shell)"),
- true,
- true);
+ ExecuteString(v8::String::New(str), name, true, true);
}
printf("\n");
}
diff --git a/deps/v8/src/accessors.cc b/deps/v8/src/accessors.cc
index e7d6aa0e8b..f02efa55a2 100644
--- a/deps/v8/src/accessors.cc
+++ b/deps/v8/src/accessors.cc
@@ -599,6 +599,7 @@ MaybeObject* Accessors::FunctionGetArguments(Object* object, void*) {
if (!found_it) return isolate->heap()->undefined_value();
Handle<JSFunction> function(holder, isolate);
+ if (function->shared()->native()) return isolate->heap()->null_value();
// Find the top invocation of the function by traversing frames.
List<JSFunction*> functions(2);
for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
@@ -732,6 +733,7 @@ MaybeObject* Accessors::FunctionGetCaller(Object* object, void*) {
bool found_it = false;
JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it);
if (!found_it) return isolate->heap()->undefined_value();
+ if (holder->shared()->native()) return isolate->heap()->null_value();
Handle<JSFunction> function(holder, isolate);
FrameFunctionIterator it(isolate, no_alloc);
diff --git a/deps/v8/src/arm/assembler-arm.cc b/deps/v8/src/arm/assembler-arm.cc
index 89df079f90..0ec36921ab 100644
--- a/deps/v8/src/arm/assembler-arm.cc
+++ b/deps/v8/src/arm/assembler-arm.cc
@@ -692,11 +692,11 @@ void Assembler::bind(Label* L) {
void Assembler::next(Label* L) {
ASSERT(L->is_linked());
int link = target_at(L->pos());
- if (link > 0) {
- L->link_to(link);
- } else {
- ASSERT(link == kEndOfChain);
+ if (link == kEndOfChain) {
L->Unuse();
+ } else {
+ ASSERT(link >= 0);
+ L->link_to(link);
}
}
diff --git a/deps/v8/src/arm/builtins-arm.cc b/deps/v8/src/arm/builtins-arm.cc
index 328102bb40..a35380c175 100644
--- a/deps/v8/src/arm/builtins-arm.cc
+++ b/deps/v8/src/arm/builtins-arm.cc
@@ -138,7 +138,7 @@ static void AllocateEmptyJSArray(MacroAssembler* masm,
__ str(scratch1, FieldMemOperand(result, JSArray::kElementsOffset));
// Clear the heap tag on the elements array.
- ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTag == 0);
__ sub(scratch1, scratch1, Operand(kHeapObjectTag));
// Initialize the FixedArray and fill it with holes. FixedArray length is
@@ -207,7 +207,7 @@ static void AllocateJSArray(MacroAssembler* masm,
// Allocate the JSArray object together with space for a FixedArray with the
// requested number of elements.
__ bind(&not_empty);
- ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
+ STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
__ mov(elements_array_end,
Operand((JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize));
__ add(elements_array_end,
@@ -243,7 +243,7 @@ static void AllocateJSArray(MacroAssembler* masm,
FieldMemOperand(result, JSArray::kElementsOffset));
// Clear the heap tag on the elements array.
- ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTag == 0);
__ sub(elements_array_storage,
elements_array_storage,
Operand(kHeapObjectTag));
@@ -255,7 +255,7 @@ static void AllocateJSArray(MacroAssembler* masm,
__ LoadRoot(scratch1, Heap::kFixedArrayMapRootIndex);
ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset);
__ str(scratch1, MemOperand(elements_array_storage, kPointerSize, PostIndex));
- ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTag == 0);
__ tst(array_size, array_size);
// Length of the FixedArray is the number of pre-allocated elements if
// the actual JSArray has length 0 and the size of the JSArray for non-empty
@@ -272,7 +272,7 @@ static void AllocateJSArray(MacroAssembler* masm,
// result: JSObject
// elements_array_storage: elements array element storage
// array_size: smi-tagged size of elements array
- ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
+ STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
__ add(elements_array_end,
elements_array_storage,
Operand(array_size, LSL, kPointerSizeLog2 - kSmiTagSize));
@@ -337,14 +337,14 @@ static void ArrayNativeCode(MacroAssembler* masm,
__ bind(&argc_one_or_more);
__ cmp(r0, Operand(1));
__ b(ne, &argc_two_or_more);
- ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTag == 0);
__ ldr(r2, MemOperand(sp)); // Get the argument from the stack.
__ and_(r3, r2, Operand(kIntptrSignBit | kSmiTagMask), SetCC);
__ b(ne, call_generic_code);
// Handle construction of an empty array of a certain size. Bail out if size
// is too large to actually allocate an elements array.
- ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTag == 0);
__ cmp(r2, Operand(JSObject::kInitialMaxFastElementArray << kSmiTagSize));
__ b(ge, call_generic_code);
@@ -571,7 +571,7 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
// Is it a String?
__ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
__ ldrb(r3, FieldMemOperand(r2, Map::kInstanceTypeOffset));
- ASSERT(kNotStringTag != 0);
+ STATIC_ASSERT(kNotStringTag != 0);
__ tst(r3, Operand(kIsNotStringMask));
__ b(ne, &convert_argument);
__ mov(argument, r0);
diff --git a/deps/v8/src/arm/code-stubs-arm.cc b/deps/v8/src/arm/code-stubs-arm.cc
index ffe32bc60a..c310da88bc 100644
--- a/deps/v8/src/arm/code-stubs-arm.cc
+++ b/deps/v8/src/arm/code-stubs-arm.cc
@@ -4389,8 +4389,8 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// a sequential string or an external string.
// In the case of a sliced string its offset has to be taken into account.
Label cons_string, check_encoding;
- STATIC_ASSERT((kConsStringTag < kExternalStringTag));
- STATIC_ASSERT((kSlicedStringTag > kExternalStringTag));
+ STATIC_ASSERT(kConsStringTag < kExternalStringTag);
+ STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
__ cmp(r1, Operand(kExternalStringTag));
__ b(lt, &cons_string);
__ b(eq, &runtime);
@@ -4487,7 +4487,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// frame. Therefore we have to use fp, which points exactly to two pointer
// sizes below the previous sp. (Because creating a new stack frame pushes
// the previous fp onto the stack and moves up sp by 2 * kPointerSize.)
- __ ldr(r0, MemOperand(fp, kSubjectOffset + 2 * kPointerSize));
+ __ ldr(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize));
// If slice offset is not 0, load the length from the original sliced string.
// Argument 4, r3: End of string data
// Argument 3, r2: Start of string data
@@ -4495,7 +4495,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
__ add(r9, r8, Operand(r9, LSL, r3));
__ add(r2, r9, Operand(r1, LSL, r3));
- __ ldr(r8, FieldMemOperand(r0, String::kLengthOffset));
+ __ ldr(r8, FieldMemOperand(subject, String::kLengthOffset));
__ mov(r8, Operand(r8, ASR, kSmiTagSize));
__ add(r3, r9, Operand(r8, LSL, r3));
@@ -4503,7 +4503,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// Already there
// Argument 1 (r0): Subject string.
- // Already there
+ __ mov(r0, subject);
// Locate the code entry and call it.
__ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag));
@@ -4520,12 +4520,12 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// Check the result.
Label success;
- __ cmp(subject, Operand(NativeRegExpMacroAssembler::SUCCESS));
+ __ cmp(r0, Operand(NativeRegExpMacroAssembler::SUCCESS));
__ b(eq, &success);
Label failure;
- __ cmp(subject, Operand(NativeRegExpMacroAssembler::FAILURE));
+ __ cmp(r0, Operand(NativeRegExpMacroAssembler::FAILURE));
__ b(eq, &failure);
- __ cmp(subject, Operand(NativeRegExpMacroAssembler::EXCEPTION));
+ __ cmp(r0, Operand(NativeRegExpMacroAssembler::EXCEPTION));
// If not exception it can only be retry. Handle that in the runtime system.
__ b(ne, &runtime);
// Result must now be exception. If there is no pending exception already a
@@ -4537,18 +4537,18 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
__ mov(r2, Operand(ExternalReference(Isolate::k_pending_exception_address,
isolate)));
__ ldr(r0, MemOperand(r2, 0));
- __ cmp(subject, r1);
+ __ cmp(r0, r1);
__ b(eq, &runtime);
__ str(r1, MemOperand(r2, 0)); // Clear pending exception.
// Check if the exception is a termination. If so, throw as uncatchable.
- __ LoadRoot(ip, Heap::kTerminationExceptionRootIndex);
- __ cmp(subject, ip);
+ __ CompareRoot(r0, Heap::kTerminationExceptionRootIndex);
+
Label termination_exception;
__ b(eq, &termination_exception);
- __ Throw(subject); // Expects thrown value in r0.
+ __ Throw(r0); // Expects thrown value in r0.
__ bind(&termination_exception);
__ ThrowUncatchable(TERMINATION, r0); // Expects thrown value in r0.
@@ -4857,8 +4857,8 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
// Handle non-flat strings.
__ and_(result_, result_, Operand(kStringRepresentationMask));
- STATIC_ASSERT((kConsStringTag < kExternalStringTag));
- STATIC_ASSERT((kSlicedStringTag > kExternalStringTag));
+ STATIC_ASSERT(kConsStringTag < kExternalStringTag);
+ STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
__ cmp(result_, Operand(kExternalStringTag));
__ b(gt, &sliced_string);
__ b(eq, &call_runtime_);
@@ -4894,7 +4894,8 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
// Check for 1-byte or 2-byte string.
__ bind(&flat_string);
- STATIC_ASSERT(kAsciiStringTag != 0);
+ STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
+ STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
__ tst(result_, Operand(kStringEncodingMask));
__ b(ne, &ascii_string);
@@ -5468,11 +5469,6 @@ void SubStringStub::Generate(MacroAssembler* masm) {
Register to = r6;
Register from = r7;
- if (FLAG_string_slices) {
- __ nop(0); // Jumping as first instruction would crash the code generation.
- __ jmp(&runtime);
- }
-
__ Ldrd(to, from, MemOperand(sp, kToOffset));
STATIC_ASSERT(kFromOffset == kToOffset + 4);
STATIC_ASSERT(kSmiTag == 0);
@@ -5490,64 +5486,79 @@ void SubStringStub::Generate(MacroAssembler* masm) {
__ b(mi, &runtime); // Fail if from > to.
// Special handling of sub-strings of length 1 and 2. One character strings
// are handled in the runtime system (looked up in the single character
- // cache). Two character strings are looked for in the symbol cache.
+ // cache). Two character strings are looked for in the symbol cache in
+ // generated code.
__ cmp(r2, Operand(2));
__ b(lt, &runtime);
- // r2: length
- // r3: from index (untaged smi)
+ // r2: result string length
+ // r3: from index (untagged smi)
// r6 (a.k.a. to): to (smi)
// r7 (a.k.a. from): from offset (smi)
-
// Make sure first argument is a sequential (or flat) string.
- __ ldr(r5, MemOperand(sp, kStringOffset));
+ __ ldr(r0, MemOperand(sp, kStringOffset));
STATIC_ASSERT(kSmiTag == 0);
- __ JumpIfSmi(r5, &runtime);
- Condition is_string = masm->IsObjectStringType(r5, r1);
+ __ JumpIfSmi(r0, &runtime);
+ Condition is_string = masm->IsObjectStringType(r0, r1);
__ b(NegateCondition(is_string), &runtime);
+ // Short-cut for the case of trivial substring.
+ Label return_r0;
+ // r0: original string
+ // r2: result string length
+ __ ldr(r4, FieldMemOperand(r0, String::kLengthOffset));
+ __ cmp(r2, Operand(r4, ASR, 1));
+ __ b(eq, &return_r0);
+
+ Label create_slice;
+ if (FLAG_string_slices) {
+ __ cmp(r2, Operand(SlicedString::kMinLength));
+ __ b(ge, &create_slice);
+ }
+
+ // r0: original string
// r1: instance type
- // r2: length
+ // r2: result string length
// r3: from index (untagged smi)
- // r5: string
// r6 (a.k.a. to): to (smi)
// r7 (a.k.a. from): from offset (smi)
Label seq_string;
__ and_(r4, r1, Operand(kStringRepresentationMask));
STATIC_ASSERT(kSeqStringTag < kConsStringTag);
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
+ STATIC_ASSERT(kConsStringTag < kSlicedStringTag);
__ cmp(r4, Operand(kConsStringTag));
- __ b(gt, &runtime); // External strings go to runtime.
+ __ b(gt, &runtime); // Slices and external strings go to runtime.
__ b(lt, &seq_string); // Sequential strings are handled directly.
// Cons string. Try to recurse (once) on the first substring.
// (This adds a little more generality than necessary to handle flattened
// cons strings, but not much).
- __ ldr(r5, FieldMemOperand(r5, ConsString::kFirstOffset));
- __ ldr(r4, FieldMemOperand(r5, HeapObject::kMapOffset));
+ __ ldr(r0, FieldMemOperand(r0, ConsString::kFirstOffset));
+ __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
__ ldrb(r1, FieldMemOperand(r4, Map::kInstanceTypeOffset));
__ tst(r1, Operand(kStringRepresentationMask));
STATIC_ASSERT(kSeqStringTag == 0);
- __ b(ne, &runtime); // Cons and External strings go to runtime.
+ __ b(ne, &runtime); // Cons, slices and external strings go to runtime.
// Definitly a sequential string.
__ bind(&seq_string);
- // r1: instance type.
- // r2: length
- // r3: from index (untaged smi)
- // r5: string
+ // r0: original string
+ // r1: instance type
+ // r2: result string length
+ // r3: from index (untagged smi)
// r6 (a.k.a. to): to (smi)
// r7 (a.k.a. from): from offset (smi)
- __ ldr(r4, FieldMemOperand(r5, String::kLengthOffset));
+ __ ldr(r4, FieldMemOperand(r0, String::kLengthOffset));
__ cmp(r4, Operand(to));
__ b(lt, &runtime); // Fail if to > length.
to = no_reg;
- // r1: instance type.
- // r2: result string length.
- // r3: from index (untaged smi)
- // r5: string.
+ // r0: original string or left hand side of the original cons string.
+ // r1: instance type
+ // r2: result string length
+ // r3: from index (untagged smi)
// r7 (a.k.a. from): from offset (smi)
// Check for flat ASCII string.
Label non_ascii_flat;
@@ -5561,82 +5572,146 @@ void SubStringStub::Generate(MacroAssembler* masm) {
// Sub string of length 2 requested.
// Get the two characters forming the sub string.
- __ add(r5, r5, Operand(r3));
- __ ldrb(r3, FieldMemOperand(r5, SeqAsciiString::kHeaderSize));
- __ ldrb(r4, FieldMemOperand(r5, SeqAsciiString::kHeaderSize + 1));
+ __ add(r0, r0, Operand(r3));
+ __ ldrb(r3, FieldMemOperand(r0, SeqAsciiString::kHeaderSize));
+ __ ldrb(r4, FieldMemOperand(r0, SeqAsciiString::kHeaderSize + 1));
// Try to lookup two character string in symbol table.
Label make_two_character_string;
StringHelper::GenerateTwoCharacterSymbolTableProbe(
masm, r3, r4, r1, r5, r6, r7, r9, &make_two_character_string);
Counters* counters = masm->isolate()->counters();
- __ IncrementCounter(counters->sub_string_native(), 1, r3, r4);
- __ add(sp, sp, Operand(3 * kPointerSize));
- __ Ret();
+ __ jmp(&return_r0);
// r2: result string length.
// r3: two characters combined into halfword in little endian byte order.
__ bind(&make_two_character_string);
__ AllocateAsciiString(r0, r2, r4, r5, r9, &runtime);
__ strh(r3, FieldMemOperand(r0, SeqAsciiString::kHeaderSize));
- __ IncrementCounter(counters->sub_string_native(), 1, r3, r4);
- __ add(sp, sp, Operand(3 * kPointerSize));
- __ Ret();
+ __ jmp(&return_r0);
__ bind(&result_longer_than_two);
+ // Locate 'from' character of string.
+ __ add(r5, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
+ __ add(r5, r5, Operand(from, ASR, 1));
+
// Allocate the result.
__ AllocateAsciiString(r0, r2, r3, r4, r1, &runtime);
- // r0: result string.
- // r2: result string length.
- // r5: string.
+ // r0: result string
+ // r2: result string length
+ // r5: first character of substring to copy
// r7 (a.k.a. from): from offset (smi)
// Locate first character of result.
__ add(r1, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
- // Locate 'from' character of string.
- __ add(r5, r5, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
- __ add(r5, r5, Operand(from, ASR, 1));
- // r0: result string.
- // r1: first character of result string.
- // r2: result string length.
- // r5: first character of sub string to copy.
+ // r0: result string
+ // r1: first character of result string
+ // r2: result string length
+ // r5: first character of substring to copy
STATIC_ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0);
StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9,
COPY_ASCII | DEST_ALWAYS_ALIGNED);
- __ IncrementCounter(counters->sub_string_native(), 1, r3, r4);
- __ add(sp, sp, Operand(3 * kPointerSize));
- __ Ret();
+ __ jmp(&return_r0);
__ bind(&non_ascii_flat);
- // r2: result string length.
- // r5: string.
+ // r0: original string
+ // r2: result string length
// r7 (a.k.a. from): from offset (smi)
// Check for flat two byte string.
+ // Locate 'from' character of string.
+ __ add(r5, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
+ // As "from" is a smi it is 2 times the value which matches the size of a two
+ // byte character.
+ STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
+ __ add(r5, r5, Operand(from));
+
// Allocate the result.
__ AllocateTwoByteString(r0, r2, r1, r3, r4, &runtime);
- // r0: result string.
- // r2: result string length.
- // r5: string.
+ // r0: result string
+ // r2: result string length
+ // r5: first character of substring to copy
// Locate first character of result.
__ add(r1, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
- // Locate 'from' character of string.
- __ add(r5, r5, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
- // As "from" is a smi it is 2 times the value which matches the size of a two
- // byte character.
- __ add(r5, r5, Operand(from));
+
from = no_reg;
// r0: result string.
// r1: first character of result.
// r2: result length.
- // r5: first character of string to copy.
+ // r5: first character of substring to copy.
STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
StringHelper::GenerateCopyCharactersLong(
masm, r1, r5, r2, r3, r4, r6, r7, r9, DEST_ALWAYS_ALIGNED);
+ __ jmp(&return_r0);
+
+ if (FLAG_string_slices) {
+ __ bind(&create_slice);
+ // r0: original string
+ // r1: instance type
+ // r2: length
+ // r3: from index (untagged smi)
+ // r6 (a.k.a. to): to (smi)
+ // r7 (a.k.a. from): from offset (smi)
+ Label allocate_slice, sliced_string, seq_string;
+ STATIC_ASSERT(kSeqStringTag == 0);
+ __ tst(r1, Operand(kStringRepresentationMask));
+ __ b(eq, &seq_string);
+ STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
+ STATIC_ASSERT(kIsIndirectStringMask != 0);
+ __ tst(r1, Operand(kIsIndirectStringMask));
+ // External string. Jump to runtime.
+ __ b(eq, &runtime);
+
+ __ tst(r1, Operand(kSlicedNotConsMask));
+ __ b(ne, &sliced_string);
+ // Cons string. Check whether it is flat, then fetch first part.
+ __ ldr(r5, FieldMemOperand(r0, ConsString::kSecondOffset));
+ __ LoadRoot(r9, Heap::kEmptyStringRootIndex);
+ __ cmp(r5, r9);
+ __ b(ne, &runtime);
+ __ ldr(r5, FieldMemOperand(r0, ConsString::kFirstOffset));
+ __ jmp(&allocate_slice);
+
+ __ bind(&sliced_string);
+ // Sliced string. Fetch parent and correct start index by offset.
+ __ ldr(r5, FieldMemOperand(r0, SlicedString::kOffsetOffset));
+ __ add(r7, r7, r5);
+ __ ldr(r5, FieldMemOperand(r0, SlicedString::kParentOffset));
+ __ jmp(&allocate_slice);
+
+ __ bind(&seq_string);
+ // Sequential string. Just move string to the right register.
+ __ mov(r5, r0);
+
+ __ bind(&allocate_slice);
+ // r1: instance type of original string
+ // r2: length
+ // r5: underlying subject string
+ // r7 (a.k.a. from): from offset (smi)
+ // Allocate new sliced string. At this point we do not reload the instance
+ // type including the string encoding because we simply rely on the info
+ // provided by the original string. It does not matter if the original
+ // string's encoding is wrong because we always have to recheck encoding of
+ // the newly created string's parent anyways due to externalized strings.
+ Label two_byte_slice, set_slice_header;
+ STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
+ STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
+ __ tst(r1, Operand(kStringEncodingMask));
+ __ b(eq, &two_byte_slice);
+ __ AllocateAsciiSlicedString(r0, r2, r3, r4, &runtime);
+ __ jmp(&set_slice_header);
+ __ bind(&two_byte_slice);
+ __ AllocateTwoByteSlicedString(r0, r2, r3, r4, &runtime);
+ __ bind(&set_slice_header);
+ __ str(r7, FieldMemOperand(r0, SlicedString::kOffsetOffset));
+ __ str(r5, FieldMemOperand(r0, SlicedString::kParentOffset));
+ }
+
+ __ bind(&return_r0);
__ IncrementCounter(counters->sub_string_native(), 1, r3, r4);
__ add(sp, sp, Operand(3 * kPointerSize));
__ Ret();
diff --git a/deps/v8/src/arm/full-codegen-arm.cc b/deps/v8/src/arm/full-codegen-arm.cc
index b58743de41..4d27a8d3ca 100644
--- a/deps/v8/src/arm/full-codegen-arm.cc
+++ b/deps/v8/src/arm/full-codegen-arm.cc
@@ -193,14 +193,14 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
// Copy any necessary parameters into the context.
int num_parameters = info->scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) {
- Slot* slot = scope()->parameter(i)->AsSlot();
- if (slot != NULL && slot->type() == Slot::CONTEXT) {
+ Variable* var = scope()->parameter(i);
+ if (var->IsContextSlot()) {
int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(num_parameters - 1 - i) * kPointerSize;
// Load parameter from stack.
__ ldr(r0, MemOperand(fp, parameter_offset));
// Store it in the context.
- __ mov(r1, Operand(Context::SlotOffset(slot->index())));
+ __ mov(r1, Operand(Context::SlotOffset(var->index())));
__ str(r0, MemOperand(cp, r1));
// Update the write barrier. This clobbers all involved
// registers, so we have to use two more registers to avoid
@@ -244,7 +244,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
ArgumentsAccessStub stub(type);
__ CallStub(&stub);
- Move(arguments->AsSlot(), r0, r1, r2);
+ SetVar(arguments, r0, r1, r2);
}
if (FLAG_trace) {
@@ -258,17 +258,19 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
scope()->VisitIllegalRedeclaration(this);
} else {
+ PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
{ Comment cmnt(masm_, "[ Declarations");
// For named function expressions, declare the function name as a
// constant.
if (scope()->is_function_scope() && scope()->function() != NULL) {
- EmitDeclaration(scope()->function(), Variable::CONST, NULL);
+ int ignored = 0;
+ EmitDeclaration(scope()->function(), Variable::CONST, NULL, &ignored);
}
VisitDeclarations(scope()->declarations());
}
{ Comment cmnt(masm_, "[ Stack check");
- PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
+ PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS);
Label ok;
__ LoadRoot(ip, Heap::kStackLimitRootIndex);
__ cmp(sp, Operand(ip));
@@ -367,24 +369,28 @@ void FullCodeGenerator::EmitReturnSequence() {
}
-void FullCodeGenerator::EffectContext::Plug(Slot* slot) const {
+void FullCodeGenerator::EffectContext::Plug(Variable* var) const {
+ ASSERT(var->IsStackAllocated() || var->IsContextSlot());
}
-void FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const {
- codegen()->Move(result_register(), slot);
+void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
+ ASSERT(var->IsStackAllocated() || var->IsContextSlot());
+ codegen()->GetVar(result_register(), var);
}
-void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const {
- codegen()->Move(result_register(), slot);
+void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
+ ASSERT(var->IsStackAllocated() || var->IsContextSlot());
+ codegen()->GetVar(result_register(), var);
__ push(result_register());
}
-void FullCodeGenerator::TestContext::Plug(Slot* slot) const {
+void FullCodeGenerator::TestContext::Plug(Variable* var) const {
+ ASSERT(var->IsStackAllocated() || var->IsContextSlot());
// For simplicity we always test the accumulator register.
- codegen()->Move(result_register(), slot);
+ codegen()->GetVar(result_register(), var);
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
codegen()->DoTest(this);
}
@@ -616,45 +622,54 @@ void FullCodeGenerator::Split(Condition cond,
}
-MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
- switch (slot->type()) {
- case Slot::PARAMETER:
- case Slot::LOCAL:
- return MemOperand(fp, SlotOffset(slot));
- case Slot::CONTEXT: {
- int context_chain_length =
- scope()->ContextChainLength(slot->var()->scope());
- __ LoadContext(scratch, context_chain_length);
- return ContextOperand(scratch, slot->index());
- }
- case Slot::LOOKUP:
- UNREACHABLE();
+MemOperand FullCodeGenerator::StackOperand(Variable* var) {
+ ASSERT(var->IsStackAllocated());
+ // Offset is negative because higher indexes are at lower addresses.
+ int offset = -var->index() * kPointerSize;
+ // Adjust by a (parameter or local) base offset.
+ if (var->IsParameter()) {
+ offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
+ } else {
+ offset += JavaScriptFrameConstants::kLocal0Offset;
+ }
+ return MemOperand(fp, offset);
+}
+
+
+MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
+ ASSERT(var->IsContextSlot() || var->IsStackAllocated());
+ if (var->IsContextSlot()) {
+ int context_chain_length = scope()->ContextChainLength(var->scope());
+ __ LoadContext(scratch, context_chain_length);
+ return ContextOperand(scratch, var->index());
+ } else {
+ return StackOperand(var);
}
- UNREACHABLE();
- return MemOperand(r0, 0);
}
-void FullCodeGenerator::Move(Register destination, Slot* source) {
+void FullCodeGenerator::GetVar(Register dest, Variable* var) {
// Use destination as scratch.
- MemOperand slot_operand = EmitSlotSearch(source, destination);
- __ ldr(destination, slot_operand);
+ MemOperand location = VarOperand(var, dest);
+ __ ldr(dest, location);
}
-void FullCodeGenerator::Move(Slot* dst,
- Register src,
- Register scratch1,
- Register scratch2) {
- ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented.
- ASSERT(!scratch1.is(src) && !scratch2.is(src));
- MemOperand location = EmitSlotSearch(dst, scratch1);
+void FullCodeGenerator::SetVar(Variable* var,
+ Register src,
+ Register scratch0,
+ Register scratch1) {
+ ASSERT(var->IsContextSlot() || var->IsStackAllocated());
+ ASSERT(!scratch0.is(src));
+ ASSERT(!scratch0.is(scratch1));
+ ASSERT(!scratch1.is(src));
+ MemOperand location = VarOperand(var, scratch0);
__ str(src, location);
// Emit the write barrier code if the location is in the heap.
- if (dst->type() == Slot::CONTEXT) {
- __ RecordWrite(scratch1,
- Operand(Context::SlotOffset(dst->index())),
- scratch2,
+ if (var->IsContextSlot()) {
+ __ RecordWrite(scratch0,
+ Operand(Context::SlotOffset(var->index())),
+ scratch1,
src);
}
}
@@ -687,29 +702,33 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
}
-void FullCodeGenerator::EmitDeclaration(Variable* variable,
+void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
Variable::Mode mode,
- FunctionLiteral* function) {
- Comment cmnt(masm_, "[ Declaration");
- ASSERT(variable != NULL); // Must have been resolved.
- Slot* slot = variable->AsSlot();
- ASSERT(slot != NULL);
- switch (slot->type()) {
- case Slot::PARAMETER:
- case Slot::LOCAL:
- if (mode == Variable::CONST) {
- __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
- __ str(ip, MemOperand(fp, SlotOffset(slot)));
- } else if (function != NULL) {
+ FunctionLiteral* function,
+ int* global_count) {
+ // If it was not possible to allocate the variable at compile time, we
+ // need to "declare" it at runtime to make sure it actually exists in the
+ // local context.
+ Variable* variable = proxy->var();
+ switch (variable->location()) {
+ case Variable::UNALLOCATED:
+ ++(*global_count);
+ break;
+
+ case Variable::PARAMETER:
+ case Variable::LOCAL:
+ if (function != NULL) {
+ Comment cmnt(masm_, "[ Declaration");
VisitForAccumulatorValue(function);
- __ str(result_register(), MemOperand(fp, SlotOffset(slot)));
+ __ str(result_register(), StackOperand(variable));
+ } else if (mode == Variable::CONST || mode == Variable::LET) {
+ Comment cmnt(masm_, "[ Declaration");
+ __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+ __ str(ip, StackOperand(variable));
}
break;
- case Slot::CONTEXT:
- // We bypass the general EmitSlotSearch because we know more about
- // this specific context.
-
+ case Variable::CONTEXT:
// The variable in the decl always resides in the current function
// context.
ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
@@ -721,23 +740,28 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
__ CompareRoot(r1, Heap::kCatchContextMapRootIndex);
__ Check(ne, "Declaration in catch context.");
}
- if (mode == Variable::CONST) {
- __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
- __ str(ip, ContextOperand(cp, slot->index()));
- // No write barrier since the_hole_value is in old space.
- } else if (function != NULL) {
+ if (function != NULL) {
+ Comment cmnt(masm_, "[ Declaration");
VisitForAccumulatorValue(function);
- __ str(result_register(), ContextOperand(cp, slot->index()));
- int offset = Context::SlotOffset(slot->index());
+ __ str(result_register(), ContextOperand(cp, variable->index()));
+ int offset = Context::SlotOffset(variable->index());
// We know that we have written a function, which is not a smi.
__ mov(r1, Operand(cp));
__ RecordWrite(r1, Operand(offset), r2, result_register());
+ PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+ } else if (mode == Variable::CONST || mode == Variable::LET) {
+ Comment cmnt(masm_, "[ Declaration");
+ __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+ __ str(ip, ContextOperand(cp, variable->index()));
+ // No write barrier since the_hole_value is in old space.
+ PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
}
break;
- case Slot::LOOKUP: {
+ case Variable::LOOKUP: {
+ Comment cmnt(masm_, "[ Declaration");
__ mov(r2, Operand(variable->name()));
- // Declaration nodes are always introduced in one of two modes.
+ // Declaration nodes are always introduced in one of three modes.
ASSERT(mode == Variable::VAR ||
mode == Variable::CONST ||
mode == Variable::LET);
@@ -747,15 +771,15 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
// Note: For variables we must not push an initial value (such as
// 'undefined') because we may have a (legal) redeclaration and we
// must not destroy the current value.
- if (mode == Variable::CONST) {
- __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
- __ Push(cp, r2, r1, r0);
- } else if (function != NULL) {
+ if (function != NULL) {
__ Push(cp, r2, r1);
// Push initial value for function declaration.
VisitForStackValue(function);
+ } else if (mode == Variable::CONST || mode == Variable::LET) {
+ __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
+ __ Push(cp, r2, r1, r0);
} else {
- __ mov(r0, Operand(Smi::FromInt(0))); // No initial value!
+ __ mov(r0, Operand(Smi::FromInt(0))); // Indicates no initial value.
__ Push(cp, r2, r1, r0);
}
__ CallRuntime(Runtime::kDeclareContextSlot, 4);
@@ -765,19 +789,16 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
}
-void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
- EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
-}
+void FullCodeGenerator::VisitDeclaration(Declaration* decl) { }
void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals.
// The context is the first argument.
- __ mov(r2, Operand(pairs));
- __ mov(r1, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
- __ mov(r0, Operand(Smi::FromInt(strict_mode_flag())));
- __ Push(cp, r2, r1, r0);
- __ CallRuntime(Runtime::kDeclareGlobals, 4);
+ __ mov(r1, Operand(pairs));
+ __ mov(r0, Operand(Smi::FromInt(DeclareGlobalsFlags())));
+ __ Push(cp, r1, r0);
+ __ CallRuntime(Runtime::kDeclareGlobals, 3);
// Return value is ignored.
}
@@ -1085,10 +1106,9 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
}
-void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
- Slot* slot,
- TypeofState typeof_state,
- Label* slow) {
+void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
+ TypeofState typeof_state,
+ Label* slow) {
Register current = cp;
Register next = r1;
Register temp = r2;
@@ -1135,7 +1155,7 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
}
__ ldr(r0, GlobalObjectOperand());
- __ mov(r2, Operand(slot->var()->name()));
+ __ mov(r2, Operand(var->name()));
RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
? RelocInfo::CODE_TARGET
: RelocInfo::CODE_TARGET_CONTEXT;
@@ -1144,15 +1164,14 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
}
-MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(
- Slot* slot,
- Label* slow) {
- ASSERT(slot->type() == Slot::CONTEXT);
+MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
+ Label* slow) {
+ ASSERT(var->IsContextSlot());
Register context = cp;
Register next = r3;
Register temp = r4;
- for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) {
+ for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
if (s->num_heap_slots() > 0) {
if (s->calls_eval()) {
// Check that extension is NULL.
@@ -1173,59 +1192,30 @@ MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(
// This function is used only for loads, not stores, so it's safe to
// return an cp-based operand (the write barrier cannot be allowed to
// destroy the cp register).
- return ContextOperand(context, slot->index());
+ return ContextOperand(context, var->index());
}
-void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
- Slot* slot,
- TypeofState typeof_state,
- Label* slow,
- Label* done) {
+void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var,
+ TypeofState typeof_state,
+ Label* slow,
+ Label* done) {
// Generate fast-case code for variables that might be shadowed by
// eval-introduced variables. Eval is used a lot without
// introducing variables. In those cases, we do not want to
// perform a runtime call for all variables in the scope
// containing the eval.
- if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
- EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow);
+ if (var->mode() == Variable::DYNAMIC_GLOBAL) {
+ EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
__ jmp(done);
- } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
- Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot();
- Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
- if (potential_slot != NULL) {
- // Generate fast case for locals that rewrite to slots.
- __ ldr(r0, ContextSlotOperandCheckExtensions(potential_slot, slow));
- if (potential_slot->var()->mode() == Variable::CONST) {
- __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
- __ cmp(r0, ip);
- __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
- }
- __ jmp(done);
- } else if (rewrite != NULL) {
- // Generate fast case for calls of an argument function.
- Property* property = rewrite->AsProperty();
- if (property != NULL) {
- VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
- Literal* key_literal = property->key()->AsLiteral();
- if (obj_proxy != NULL &&
- key_literal != NULL &&
- obj_proxy->IsArguments() &&
- key_literal->handle()->IsSmi()) {
- // Load arguments object if there are no eval-introduced
- // variables. Then load the argument from the arguments
- // object using keyed load.
- __ ldr(r1,
- ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(),
- slow));
- __ mov(r0, Operand(key_literal->handle()));
- Handle<Code> ic =
- isolate()->builtins()->KeyedLoadIC_Initialize();
- __ Call(ic, RelocInfo::CODE_TARGET, GetPropertyId(property));
- __ jmp(done);
- }
- }
+ } else if (var->mode() == Variable::DYNAMIC_LOCAL) {
+ Variable* local = var->local_if_not_shadowed();
+ __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow));
+ if (local->mode() == Variable::CONST) {
+ __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
+ __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
}
+ __ jmp(done);
}
}
@@ -1235,52 +1225,60 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
SetSourcePosition(proxy->position());
Variable* var = proxy->var();
- // Three cases: non-this global variables, lookup slots, and all other
- // types of slots.
- Slot* slot = var->AsSlot();
- ASSERT((var->is_global() && !var->is_this()) == (slot == NULL));
-
- if (slot == NULL) {
- Comment cmnt(masm_, "Global variable");
- // Use inline caching. Variable name is passed in r2 and the global
- // object (receiver) in r0.
- __ ldr(r0, GlobalObjectOperand());
- __ mov(r2, Operand(var->name()));
- Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
- __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
- context()->Plug(r0);
-
- } else if (slot->type() == Slot::LOOKUP) {
- Label done, slow;
-
- // Generate code for loading from variables potentially shadowed
- // by eval-introduced variables.
- EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done);
-
- __ bind(&slow);
- Comment cmnt(masm_, "Lookup slot");
- __ mov(r1, Operand(var->name()));
- __ Push(cp, r1); // Context and name.
- __ CallRuntime(Runtime::kLoadContextSlot, 2);
- __ bind(&done);
+ // Three cases: global variables, lookup variables, and all other types of
+ // variables.
+ switch (var->location()) {
+ case Variable::UNALLOCATED: {
+ Comment cmnt(masm_, "Global variable");
+ // Use inline caching. Variable name is passed in r2 and the global
+ // object (receiver) in r0.
+ __ ldr(r0, GlobalObjectOperand());
+ __ mov(r2, Operand(var->name()));
+ Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+ __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
+ context()->Plug(r0);
+ break;
+ }
- context()->Plug(r0);
+ case Variable::PARAMETER:
+ case Variable::LOCAL:
+ case Variable::CONTEXT: {
+ Comment cmnt(masm_, var->IsContextSlot()
+ ? "Context variable"
+ : "Stack variable");
+ if (var->mode() != Variable::LET && var->mode() != Variable::CONST) {
+ context()->Plug(var);
+ } else {
+ // Let and const need a read barrier.
+ GetVar(r0, var);
+ __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
+ if (var->mode() == Variable::LET) {
+ Label done;
+ __ b(ne, &done);
+ __ mov(r0, Operand(var->name()));
+ __ push(r0);
+ __ CallRuntime(Runtime::kThrowReferenceError, 1);
+ __ bind(&done);
+ } else {
+ __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
+ }
+ context()->Plug(r0);
+ }
+ break;
+ }
- } else {
- Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
- ? "Context slot"
- : "Stack slot");
- if (var->mode() == Variable::CONST) {
- // Constants may be the hole value if they have not been initialized.
- // Unhole them.
- MemOperand slot_operand = EmitSlotSearch(slot, r0);
- __ ldr(r0, slot_operand);
- __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
- __ cmp(r0, ip);
- __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
+ case Variable::LOOKUP: {
+ Label done, slow;
+ // Generate code for loading from variables potentially shadowed
+ // by eval-introduced variables.
+ EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done);
+ __ bind(&slow);
+ Comment cmnt(masm_, "Lookup variable");
+ __ mov(r1, Operand(var->name()));
+ __ Push(cp, r1); // Context and name.
+ __ CallRuntime(Runtime::kLoadContextSlot, 2);
+ __ bind(&done);
context()->Plug(r0);
- } else {
- context()->Plug(slot);
}
}
}
@@ -1814,14 +1812,8 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
void FullCodeGenerator::EmitVariableAssignment(Variable* var,
Token::Value op) {
- ASSERT(var != NULL);
- ASSERT(var->is_global() || var->AsSlot() != NULL);
-
- if (var->is_global()) {
- ASSERT(!var->is_this());
- // Assignment to a global variable. Use inline caching for the
- // assignment. Right-hand-side value is passed in r0, variable name in
- // r2, and the global object in r1.
+ if (var->IsUnallocated()) {
+ // Global var, const, or let.
__ mov(r2, Operand(var->name()));
__ ldr(r1, GlobalObjectOperand());
Handle<Code> ic = is_strict_mode()
@@ -1830,67 +1822,83 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
__ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
} else if (op == Token::INIT_CONST) {
- // Like var declarations, const declarations are hoisted to function
- // scope. However, unlike var initializers, const initializers are able
- // to drill a hole to that function context, even from inside a 'with'
- // context. We thus bypass the normal static scope lookup.
- Slot* slot = var->AsSlot();
- Label skip;
- switch (slot->type()) {
- case Slot::PARAMETER:
- // No const parameters.
- UNREACHABLE();
- break;
- case Slot::LOCAL:
- // Detect const reinitialization by checking for the hole value.
- __ ldr(r1, MemOperand(fp, SlotOffset(slot)));
- __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
- __ cmp(r1, ip);
- __ b(ne, &skip);
- __ str(result_register(), MemOperand(fp, SlotOffset(slot)));
- break;
- case Slot::CONTEXT:
- case Slot::LOOKUP:
- __ push(r0);
- __ mov(r0, Operand(slot->var()->name()));
- __ Push(cp, r0); // Context and name.
- __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
- break;
+ // Const initializers need a write barrier.
+ ASSERT(!var->IsParameter()); // No const parameters.
+ if (var->IsStackLocal()) {
+ Label skip;
+ __ ldr(r1, StackOperand(var));
+ __ CompareRoot(r1, Heap::kTheHoleValueRootIndex);
+ __ b(ne, &skip);
+ __ str(result_register(), StackOperand(var));
+ __ bind(&skip);
+ } else {
+ ASSERT(var->IsContextSlot() || var->IsLookupSlot());
+ // Like var declarations, const declarations are hoisted to function
+ // scope. However, unlike var initializers, const initializers are
+ // able to drill a hole to that function context, even from inside a
+ // 'with' context. We thus bypass the normal static scope lookup for
+ // var->IsContextSlot().
+ __ push(r0);
+ __ mov(r0, Operand(var->name()));
+ __ Push(cp, r0); // Context and name.
+ __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
}
- __ bind(&skip);
- } else if (var->mode() != Variable::CONST) {
- // Perform the assignment for non-const variables. Const assignments
- // are simply skipped.
- Slot* slot = var->AsSlot();
- switch (slot->type()) {
- case Slot::PARAMETER:
- case Slot::LOCAL:
- // Perform the assignment.
- __ str(result_register(), MemOperand(fp, SlotOffset(slot)));
- break;
-
- case Slot::CONTEXT: {
- MemOperand target = EmitSlotSearch(slot, r1);
- // Perform the assignment and issue the write barrier.
- __ str(result_register(), target);
+ } else if (var->mode() == Variable::LET && op != Token::INIT_LET) {
+ // Non-initializing assignment to let variable needs a write barrier.
+ if (var->IsLookupSlot()) {
+ __ push(r0); // Value.
+ __ mov(r1, Operand(var->name()));
+ __ mov(r0, Operand(Smi::FromInt(strict_mode_flag())));
+ __ Push(cp, r1, r0); // Context, name, strict mode.
+ __ CallRuntime(Runtime::kStoreContextSlot, 4);
+ } else {
+ ASSERT(var->IsStackAllocated() || var->IsContextSlot());
+ Label assign;
+ MemOperand location = VarOperand(var, r1);
+ __ ldr(r3, location);
+ __ CompareRoot(r3, Heap::kTheHoleValueRootIndex);
+ __ b(ne, &assign);
+ __ mov(r3, Operand(var->name()));
+ __ push(r3);
+ __ CallRuntime(Runtime::kThrowReferenceError, 1);
+ // Perform the assignment.
+ __ bind(&assign);
+ __ str(result_register(), location);
+ if (var->IsContextSlot()) {
// RecordWrite may destroy all its register arguments.
__ mov(r3, result_register());
- int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
+ int offset = Context::SlotOffset(var->index());
__ RecordWrite(r1, Operand(offset), r2, r3);
- break;
}
+ }
- case Slot::LOOKUP:
- // Call the runtime for the assignment.
- __ push(r0); // Value.
- __ mov(r1, Operand(slot->var()->name()));
- __ mov(r0, Operand(Smi::FromInt(strict_mode_flag())));
- __ Push(cp, r1, r0); // Context, name, strict mode.
- __ CallRuntime(Runtime::kStoreContextSlot, 4);
- break;
+ } else if (var->mode() != Variable::CONST) {
+ // Assignment to var or initializing assignment to let.
+ if (var->IsStackAllocated() || var->IsContextSlot()) {
+ MemOperand location = VarOperand(var, r1);
+ if (FLAG_debug_code && op == Token::INIT_LET) {
+ // Check for an uninitialized let binding.
+ __ ldr(r2, location);
+ __ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
+ __ Check(eq, "Let binding re-initialization.");
+ }
+ // Perform the assignment.
+ __ str(r0, location);
+ if (var->IsContextSlot()) {
+ __ mov(r3, r0);
+ __ RecordWrite(r1, Operand(Context::SlotOffset(var->index())), r2, r3);
+ }
+ } else {
+ ASSERT(var->IsLookupSlot());
+ __ push(r0); // Value.
+ __ mov(r1, Operand(var->name()));
+ __ mov(r0, Operand(Smi::FromInt(strict_mode_flag())));
+ __ Push(cp, r1, r0); // Context, name, strict mode.
+ __ CallRuntime(Runtime::kStoreContextSlot, 4);
}
}
+ // Non-initializing assignments to consts are ignored.
}
@@ -2100,8 +2108,13 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
int receiver_offset = 2 + info_->scope()->num_parameters();
__ ldr(r1, MemOperand(fp, receiver_offset * kPointerSize));
__ push(r1);
- // Push the strict mode flag.
- __ mov(r1, Operand(Smi::FromInt(strict_mode_flag())));
+ // Push the strict mode flag. In harmony mode every eval call
+ // is a strict mode eval call.
+ StrictModeFlag strict_mode = strict_mode_flag();
+ if (FLAG_harmony_block_scoping) {
+ strict_mode = kStrictMode;
+ }
+ __ mov(r1, Operand(Smi::FromInt(strict_mode)));
__ push(r1);
__ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
@@ -2118,10 +2131,11 @@ void FullCodeGenerator::VisitCall(Call* expr) {
#endif
Comment cmnt(masm_, "[ Call");
- Expression* fun = expr->expression();
- Variable* var = fun->AsVariableProxy()->AsVariable();
+ Expression* callee = expr->expression();
+ VariableProxy* proxy = callee->AsVariableProxy();
+ Property* property = callee->AsProperty();
- if (var != NULL && var->is_possibly_eval()) {
+ if (proxy != NULL && proxy->var()->is_possibly_eval()) {
// In a call to eval, we first call %ResolvePossiblyDirectEval to
// resolve the function we need to call and the receiver of the
// call. Then we call the resolved function using the given
@@ -2130,7 +2144,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
int arg_count = args->length();
{ PreservePositionScope pos_scope(masm()->positions_recorder());
- VisitForStackValue(fun);
+ VisitForStackValue(callee);
__ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
__ push(r2); // Reserved receiver slot.
@@ -2144,11 +2158,10 @@ void FullCodeGenerator::VisitCall(Call* expr) {
// in generated code. If we succeed, there is no need to perform a
// context lookup in the runtime system.
Label done;
- if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) {
+ Variable* var = proxy->var();
+ if (!var->IsUnallocated() && var->mode() == Variable::DYNAMIC_GLOBAL) {
Label slow;
- EmitLoadGlobalSlotCheckExtensions(var->AsSlot(),
- NOT_INSIDE_TYPEOF,
- &slow);
+ EmitLoadGlobalCheckExtensions(var, NOT_INSIDE_TYPEOF, &slow);
// Push the function and resolve eval.
__ push(r0);
EmitResolvePossiblyDirectEval(SKIP_CONTEXT_LOOKUP, arg_count);
@@ -2156,14 +2169,12 @@ void FullCodeGenerator::VisitCall(Call* expr) {
__ bind(&slow);
}
- // Push copy of the function (found below the arguments) and
+ // Push a copy of the function (found below the arguments) and
// resolve eval.
__ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ push(r1);
EmitResolvePossiblyDirectEval(PERFORM_CONTEXT_LOOKUP, arg_count);
- if (done.is_linked()) {
- __ bind(&done);
- }
+ __ bind(&done);
// The runtime call returns a pair of values in r0 (function) and
// r1 (receiver). Touch up the stack with the right values.
@@ -2180,30 +2191,26 @@ void FullCodeGenerator::VisitCall(Call* expr) {
// Restore context register.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, r0);
- } else if (var != NULL && !var->is_this() && var->is_global()) {
+ } else if (proxy != NULL && proxy->var()->IsUnallocated()) {
// Push global object as receiver for the call IC.
__ ldr(r0, GlobalObjectOperand());
__ push(r0);
- EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
- } else if (var != NULL && var->AsSlot() != NULL &&
- var->AsSlot()->type() == Slot::LOOKUP) {
+ EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
+ } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
// Call to a lookup slot (dynamically introduced variable).
Label slow, done;
{ PreservePositionScope scope(masm()->positions_recorder());
// Generate code for loading from variables potentially shadowed
// by eval-introduced variables.
- EmitDynamicLoadFromSlotFastCase(var->AsSlot(),
- NOT_INSIDE_TYPEOF,
- &slow,
- &done);
+ EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
}
__ bind(&slow);
// Call the runtime to find the function to call (returned in r0)
// and the object holding it (returned in edx).
__ push(context_register());
- __ mov(r2, Operand(var->name()));
+ __ mov(r2, Operand(proxy->name()));
__ push(r2);
__ CallRuntime(Runtime::kLoadContextSlot, 2);
__ Push(r0, r1); // Function, receiver.
@@ -2228,26 +2235,21 @@ void FullCodeGenerator::VisitCall(Call* expr) {
// by LoadContextSlot. That object could be the hole if the
// receiver is implicitly the global object.
EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT);
- } else if (fun->AsProperty() != NULL) {
- // Call to an object property.
- Property* prop = fun->AsProperty();
- Literal* key = prop->key()->AsLiteral();
- if (key != NULL && key->handle()->IsSymbol()) {
- // Call to a named property, use call IC.
- { PreservePositionScope scope(masm()->positions_recorder());
- VisitForStackValue(prop->obj());
- }
- EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
+ } else if (property != NULL) {
+ { PreservePositionScope scope(masm()->positions_recorder());
+ VisitForStackValue(property->obj());
+ }
+ if (property->key()->IsPropertyName()) {
+ EmitCallWithIC(expr,
+ property->key()->AsLiteral()->handle(),
+ RelocInfo::CODE_TARGET);
} else {
- // Call to a keyed property.
- { PreservePositionScope scope(masm()->positions_recorder());
- VisitForStackValue(prop->obj());
- }
- EmitKeyedCallWithIC(expr, prop->key());
+ EmitKeyedCallWithIC(expr, property->key());
}
} else {
+ // Call to an arbitrary expression not handled specially above.
{ PreservePositionScope scope(masm()->positions_recorder());
- VisitForStackValue(fun);
+ VisitForStackValue(callee);
}
// Load global receiver object.
__ ldr(r1, GlobalObjectOperand());
@@ -3194,7 +3196,7 @@ void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
Label done, not_found;
// tmp now holds finger offset as a smi.
- ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
+ STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
__ ldr(r2, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset));
// r2 now holds finger offset as a smi.
__ add(r3, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
@@ -3569,32 +3571,32 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
switch (expr->op()) {
case Token::DELETE: {
Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
- Property* prop = expr->expression()->AsProperty();
- Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
+ Property* property = expr->expression()->AsProperty();
+ VariableProxy* proxy = expr->expression()->AsVariableProxy();
- if (prop != NULL) {
- VisitForStackValue(prop->obj());
- VisitForStackValue(prop->key());
+ if (property != NULL) {
+ VisitForStackValue(property->obj());
+ VisitForStackValue(property->key());
__ mov(r1, Operand(Smi::FromInt(strict_mode_flag())));
__ push(r1);
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(r0);
- } else if (var != NULL) {
+ } else if (proxy != NULL) {
+ Variable* var = proxy->var();
// Delete of an unqualified identifier is disallowed in strict mode
- // but "delete this" is.
+ // but "delete this" is allowed.
ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this());
- if (var->is_global()) {
+ if (var->IsUnallocated()) {
__ ldr(r2, GlobalObjectOperand());
__ mov(r1, Operand(var->name()));
__ mov(r0, Operand(Smi::FromInt(kNonStrictMode)));
__ Push(r2, r1, r0);
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(r0);
- } else if (var->AsSlot() != NULL &&
- var->AsSlot()->type() != Slot::LOOKUP) {
+ } else if (var->IsStackAllocated() || var->IsContextSlot()) {
// Result of deleting non-global, non-dynamic variables is false.
// The subexpression does not have side effects.
- context()->Plug(false);
+ context()->Plug(var->is_this());
} else {
// Non-global variable. Call the runtime to try to delete from the
// context where the variable was introduced.
@@ -3869,7 +3871,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
ASSERT(!context()->IsEffect());
ASSERT(!context()->IsTest());
VariableProxy* proxy = expr->AsVariableProxy();
- if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
+ if (proxy != NULL && proxy->var()->IsUnallocated()) {
Comment cmnt(masm_, "Global variable");
__ ldr(r0, GlobalObjectOperand());
__ mov(r2, Operand(proxy->name()));
@@ -3879,15 +3881,12 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
__ Call(ic);
PrepareForBailout(expr, TOS_REG);
context()->Plug(r0);
- } else if (proxy != NULL &&
- proxy->var()->AsSlot() != NULL &&
- proxy->var()->AsSlot()->type() == Slot::LOOKUP) {
+ } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
Label done, slow;
// Generate code for loading from variables potentially shadowed
// by eval-introduced variables.
- Slot* slot = proxy->var()->AsSlot();
- EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done);
+ EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done);
__ bind(&slow);
__ mov(r0, Operand(proxy->name()));
@@ -4182,7 +4181,7 @@ void FullCodeGenerator::EnterFinallyBlock() {
// Cook return address in link register to stack (smi encoded Code* delta)
__ sub(r1, lr, Operand(masm_->CodeObject()));
ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
- ASSERT_EQ(0, kSmiTag);
+ STATIC_ASSERT(kSmiTag == 0);
__ add(r1, r1, Operand(r1)); // Convert to smi.
__ push(r1);
}
@@ -4202,6 +4201,34 @@ void FullCodeGenerator::ExitFinallyBlock() {
#undef __
+#define __ ACCESS_MASM(masm())
+
+FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
+ int* stack_depth,
+ int* context_length) {
+ // The macros used here must preserve the result register.
+
+ // Because the handler block contains the context of the finally
+ // code, we can restore it directly from there for the finally code
+ // rather than iteratively unwinding contexts via their previous
+ // links.
+ __ Drop(*stack_depth); // Down to the handler block.
+ if (*context_length > 0) {
+ // Restore the context to its dedicated register and the stack.
+ __ ldr(cp, MemOperand(sp, StackHandlerConstants::kContextOffset));
+ __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+ }
+ __ PopTryHandler();
+ __ bl(finally_entry_);
+
+ *stack_depth = 0;
+ *context_length = 0;
+ return previous_;
+}
+
+
+#undef __
+
} } // namespace v8::internal
#endif // V8_TARGET_ARCH_ARM
diff --git a/deps/v8/src/arm/ic-arm.cc b/deps/v8/src/arm/ic-arm.cc
index 6038153a1a..6bad5ac03e 100644
--- a/deps/v8/src/arm/ic-arm.cc
+++ b/deps/v8/src/arm/ic-arm.cc
@@ -337,7 +337,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm,
// Fast case: Do the load.
__ add(scratch1, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
// The key is a smi.
- ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
+ STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
__ ldr(scratch2,
MemOperand(scratch1, key, LSL, kPointerSizeLog2 - kSmiTagSize));
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
@@ -370,7 +370,7 @@ static void GenerateKeyStringCheck(MacroAssembler* masm,
// Is the string a symbol?
// map: key map
__ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset));
- ASSERT(kSymbolTag != 0);
+ STATIC_ASSERT(kSymbolTag != 0);
__ tst(hash, Operand(kIsSymbolMask));
__ b(eq, not_symbol);
}
@@ -1333,7 +1333,7 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
__ cmp(key, Operand(ip));
__ b(hs, &slow);
// Calculate key + 1 as smi.
- ASSERT_EQ(0, kSmiTag);
+ STATIC_ASSERT(kSmiTag == 0);
__ add(r4, key, Operand(Smi::FromInt(1)));
__ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset));
__ b(&fast);
diff --git a/deps/v8/src/arm/lithium-codegen-arm.cc b/deps/v8/src/arm/lithium-codegen-arm.cc
index 65a6169252..24e51e0681 100644
--- a/deps/v8/src/arm/lithium-codegen-arm.cc
+++ b/deps/v8/src/arm/lithium-codegen-arm.cc
@@ -198,14 +198,14 @@ bool LCodeGen::GeneratePrologue() {
// Copy any necessary parameters into the context.
int num_parameters = scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) {
- Slot* slot = scope()->parameter(i)->AsSlot();
- if (slot != NULL && slot->type() == Slot::CONTEXT) {
+ Variable* var = scope()->parameter(i);
+ if (var->IsContextSlot()) {
int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(num_parameters - 1 - i) * kPointerSize;
// Load parameter from stack.
__ ldr(r0, MemOperand(fp, parameter_offset));
// Store it in the context.
- __ mov(r1, Operand(Context::SlotOffset(slot->index())));
+ __ mov(r1, Operand(Context::SlotOffset(var->index())));
__ str(r0, MemOperand(cp, r1));
// Update the write barrier. This clobbers all involved
// registers, so we have to use two more registers to avoid
@@ -3473,8 +3473,6 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
// Dispatch on the indirect string shape: slice or cons.
Label cons_string;
- const uint32_t kSlicedNotConsMask = kSlicedStringTag & ~kConsStringTag;
- ASSERT(IsPowerOf2(kSlicedNotConsMask) && kSlicedNotConsMask != 0);
__ tst(result, Operand(kSlicedNotConsMask));
__ b(eq, &cons_string);
@@ -3511,7 +3509,8 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
// Dispatch on the encoding: ASCII or two-byte.
Label ascii_string;
- STATIC_ASSERT(kAsciiStringTag != 0);
+ STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
+ STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
__ tst(result, Operand(kStringEncodingMask));
__ b(ne, &ascii_string);
@@ -3759,7 +3758,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
LOperand* input = instr->InputAt(0);
ASSERT(input->IsRegister() && input->Equals(instr->result()));
if (instr->needs_check()) {
- ASSERT(kHeapObjectTag == 1);
+ STATIC_ASSERT(kHeapObjectTag == 1);
// If the input is a HeapObject, SmiUntag will set the carry flag.
__ SmiUntag(ToRegister(input), SetCC);
DeoptimizeIf(cs, instr->environment());
@@ -3844,7 +3843,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
// The input was optimistically untagged; revert it.
// The carry flag is set when we reach this deferred code as we just executed
// SmiUntag(heap_object, SetCC)
- ASSERT(kHeapObjectTag == 1);
+ STATIC_ASSERT(kHeapObjectTag == 1);
__ adc(input_reg, input_reg, Operand(input_reg));
// Heap number map check.
diff --git a/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc
index 88477bb7f0..613a1f69f1 100644
--- a/deps/v8/src/arm/macro-assembler-arm.cc
+++ b/deps/v8/src/arm/macro-assembler-arm.cc
@@ -1725,6 +1725,46 @@ void MacroAssembler::AllocateAsciiConsString(Register result,
}
+void MacroAssembler::AllocateTwoByteSlicedString(Register result,
+ Register length,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required) {
+ AllocateInNewSpace(SlicedString::kSize,
+ result,
+ scratch1,
+ scratch2,
+ gc_required,
+ TAG_OBJECT);
+
+ InitializeNewString(result,
+ length,
+ Heap::kSlicedStringMapRootIndex,
+ scratch1,
+ scratch2);
+}
+
+
+void MacroAssembler::AllocateAsciiSlicedString(Register result,
+ Register length,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required) {
+ AllocateInNewSpace(SlicedString::kSize,
+ result,
+ scratch1,
+ scratch2,
+ gc_required,
+ TAG_OBJECT);
+
+ InitializeNewString(result,
+ length,
+ Heap::kSlicedAsciiStringMapRootIndex,
+ scratch1,
+ scratch2);
+}
+
+
void MacroAssembler::CompareObjectType(Register object,
Register map,
Register type_reg,
diff --git a/deps/v8/src/arm/macro-assembler-arm.h b/deps/v8/src/arm/macro-assembler-arm.h
index 9c653adbba..9d66359625 100644
--- a/deps/v8/src/arm/macro-assembler-arm.h
+++ b/deps/v8/src/arm/macro-assembler-arm.h
@@ -532,6 +532,16 @@ class MacroAssembler: public Assembler {
Register scratch1,
Register scratch2,
Label* gc_required);
+ void AllocateTwoByteSlicedString(Register result,
+ Register length,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required);
+ void AllocateAsciiSlicedString(Register result,
+ Register length,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required);
// Allocates a heap number or jumps to the gc_required label if the young
// space is full and a scavenge is needed. All registers are clobbered also
diff --git a/deps/v8/src/arm/regexp-macro-assembler-arm.cc b/deps/v8/src/arm/regexp-macro-assembler-arm.cc
index 81645c72ea..cd76edbf15 100644
--- a/deps/v8/src/arm/regexp-macro-assembler-arm.cc
+++ b/deps/v8/src/arm/regexp-macro-assembler-arm.cc
@@ -1049,7 +1049,7 @@ int RegExpMacroAssemblerARM::CheckStackGuardState(Address* return_address,
MaybeObject* result = Execution::HandleStackGuardInterrupt();
if (*code_handle != re_code) { // Return address no longer valid
- int delta = *code_handle - re_code;
+ int delta = code_handle->address() - re_code->address();
// Overwrite the return address on the stack.
*return_address += delta;
}
diff --git a/deps/v8/src/arm/stub-cache-arm.cc b/deps/v8/src/arm/stub-cache-arm.cc
index 16e6468422..5345892925 100644
--- a/deps/v8/src/arm/stub-cache-arm.cc
+++ b/deps/v8/src/arm/stub-cache-arm.cc
@@ -3497,7 +3497,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
// We are not untagging smi key and instead work with it
// as if it was premultiplied by 2.
- ASSERT((kSmiTag == 0) && (kSmiTagSize == 1));
+ STATIC_ASSERT((kSmiTag == 0) && (kSmiTagSize == 1));
Register value = r2;
switch (elements_kind) {
@@ -4147,7 +4147,7 @@ void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
// Load the result and make sure it's not the hole.
__ add(r3, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
- ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
+ STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
__ ldr(r4,
MemOperand(r3, r0, LSL, kPointerSizeLog2 - kSmiTagSize));
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
@@ -4279,7 +4279,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
__ add(scratch,
elements_reg, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
- ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
+ STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
__ str(value_reg,
MemOperand(scratch, key_reg, LSL, kPointerSizeLog2 - kSmiTagSize));
__ RecordWrite(scratch,
diff --git a/deps/v8/src/array.js b/deps/v8/src/array.js
index a12fdc84bc..32a370fda8 100644
--- a/deps/v8/src/array.js
+++ b/deps/v8/src/array.js
@@ -996,6 +996,9 @@ function ArrayFilter(f, receiver) {
if (!IS_FUNCTION(f)) {
throw MakeTypeError('called_non_callable', [ f ]);
}
+ if (IS_NULL_OR_UNDEFINED(receiver)) {
+ receiver = %GetDefaultReceiver(f) || receiver;
+ }
// Pull out the length so that modifications to the length in the
// loop will not affect the looping.
var length = ToUint32(this.length);
@@ -1004,7 +1007,7 @@ function ArrayFilter(f, receiver) {
for (var i = 0; i < length; i++) {
var current = this[i];
if (!IS_UNDEFINED(current) || i in this) {
- if (f.call(receiver, current, i, this)) {
+ if (%_CallFunction(receiver, current, i, this, f)) {
result[result_length++] = current;
}
}
@@ -1022,13 +1025,16 @@ function ArrayForEach(f, receiver) {
if (!IS_FUNCTION(f)) {
throw MakeTypeError('called_non_callable', [ f ]);
}
+ if (IS_NULL_OR_UNDEFINED(receiver)) {
+ receiver = %GetDefaultReceiver(f) || receiver;
+ }
// Pull out the length so that modifications to the length in the
// loop will not affect the looping.
var length = TO_UINT32(this.length);
for (var i = 0; i < length; i++) {
var current = this[i];
if (!IS_UNDEFINED(current) || i in this) {
- f.call(receiver, current, i, this);
+ %_CallFunction(receiver, current, i, this, f);
}
}
}
@@ -1045,13 +1051,16 @@ function ArraySome(f, receiver) {
if (!IS_FUNCTION(f)) {
throw MakeTypeError('called_non_callable', [ f ]);
}
+ if (IS_NULL_OR_UNDEFINED(receiver)) {
+ receiver = %GetDefaultReceiver(f) || receiver;
+ }
// Pull out the length so that modifications to the length in the
// loop will not affect the looping.
var length = TO_UINT32(this.length);
for (var i = 0; i < length; i++) {
var current = this[i];
if (!IS_UNDEFINED(current) || i in this) {
- if (f.call(receiver, current, i, this)) return true;
+ if (%_CallFunction(receiver, current, i, this, f)) return true;
}
}
return false;
@@ -1067,13 +1076,16 @@ function ArrayEvery(f, receiver) {
if (!IS_FUNCTION(f)) {
throw MakeTypeError('called_non_callable', [ f ]);
}
+ if (IS_NULL_OR_UNDEFINED(receiver)) {
+ receiver = %GetDefaultReceiver(f) || receiver;
+ }
// Pull out the length so that modifications to the length in the
// loop will not affect the looping.
var length = TO_UINT32(this.length);
for (var i = 0; i < length; i++) {
var current = this[i];
if (!IS_UNDEFINED(current) || i in this) {
- if (!f.call(receiver, current, i, this)) return false;
+ if (!%_CallFunction(receiver, current, i, this, f)) return false;
}
}
return true;
@@ -1088,6 +1100,9 @@ function ArrayMap(f, receiver) {
if (!IS_FUNCTION(f)) {
throw MakeTypeError('called_non_callable', [ f ]);
}
+ if (IS_NULL_OR_UNDEFINED(receiver)) {
+ receiver = %GetDefaultReceiver(f) || receiver;
+ }
// Pull out the length so that modifications to the length in the
// loop will not affect the looping.
var length = TO_UINT32(this.length);
@@ -1096,7 +1111,7 @@ function ArrayMap(f, receiver) {
for (var i = 0; i < length; i++) {
var current = this[i];
if (!IS_UNDEFINED(current) || i in this) {
- accumulator[i] = f.call(receiver, current, i, this);
+ accumulator[i] = %_CallFunction(receiver, current, i, this, f);
}
}
%MoveArrayContents(accumulator, result);
@@ -1233,6 +1248,7 @@ function ArrayReduce(callback, current) {
if (!IS_FUNCTION(callback)) {
throw MakeTypeError('called_non_callable', [callback]);
}
+
// Pull out the length so that modifications to the length in the
// loop will not affect the looping.
var length = ToUint32(this.length);
@@ -1249,10 +1265,11 @@ function ArrayReduce(callback, current) {
throw MakeTypeError('reduce_no_initial', []);
}
+ var receiver = %GetDefaultReceiver(callback);
for (; i < length; i++) {
var element = this[i];
if (!IS_UNDEFINED(element) || i in this) {
- current = callback.call(void 0, current, element, i, this);
+ current = %_CallFunction(receiver, current, element, i, this, callback);
}
}
return current;
@@ -1280,10 +1297,11 @@ function ArrayReduceRight(callback, current) {
throw MakeTypeError('reduce_no_initial', []);
}
+ var receiver = %GetDefaultReceiver(callback);
for (; i >= 0; i--) {
var element = this[i];
if (!IS_UNDEFINED(element) || i in this) {
- current = callback.call(void 0, current, element, i, this);
+ current = %_CallFunction(receiver, current, element, i, this, callback);
}
}
return current;
@@ -1296,12 +1314,13 @@ function ArrayIsArray(obj) {
// -------------------------------------------------------------------
-function SetupArray() {
- // Setup non-enumerable constructor property on the Array.prototype
+function SetUpArray() {
+ %CheckIsBootstrapping();
+ // Set up non-enumerable constructor property on the Array.prototype
// object.
%SetProperty($Array.prototype, "constructor", $Array, DONT_ENUM);
- // Setup non-enumerable functions on the Array object.
+ // Set up non-enumerable functions on the Array object.
InstallFunctions($Array, DONT_ENUM, $Array(
"isArray", ArrayIsArray
));
@@ -1319,7 +1338,7 @@ function SetupArray() {
return f;
}
- // Setup non-enumerable functions of the Array.prototype object and
+ // Set up non-enumerable functions of the Array.prototype object and
// set their names.
// Manipulate the length of some of the functions to meet
// expectations set by ECMA-262 or Mozilla.
@@ -1350,19 +1369,13 @@ function SetupArray() {
%FinishArrayPrototypeSetup($Array.prototype);
// The internal Array prototype doesn't need to be fancy, since it's never
- // exposed to user code, so no hidden prototypes or DONT_ENUM attributes
- // are necessary.
- // The null __proto__ ensures that we never inherit any user created
- // getters or setters from, e.g., Object.prototype.
- InternalArray.prototype.__proto__ = null;
- // Adding only the functions that are actually used, and a toString.
- InternalArray.prototype.join = getFunction("join", ArrayJoin);
- InternalArray.prototype.pop = getFunction("pop", ArrayPop);
- InternalArray.prototype.push = getFunction("push", ArrayPush);
- InternalArray.prototype.toString = function() {
- return "Internal Array, length " + this.length;
- };
+ // exposed to user code.
+ // Adding only the functions that are actually used.
+ SetUpLockedPrototype(InternalArray, $Array(), $Array(
+ "join", getFunction("join", ArrayJoin),
+ "pop", getFunction("pop", ArrayPop),
+ "push", getFunction("push", ArrayPush)
+ ));
}
-
-SetupArray();
+SetUpArray();
diff --git a/deps/v8/src/ast.cc b/deps/v8/src/ast.cc
index 7319abe6dd..8b8a2a884e 100644
--- a/deps/v8/src/ast.cc
+++ b/deps/v8/src/ast.cc
@@ -36,20 +36,9 @@
namespace v8 {
namespace internal {
-AstSentinels::AstSentinels()
- : this_proxy_(Isolate::Current(), true),
- identifier_proxy_(Isolate::Current(), false),
- valid_left_hand_side_sentinel_(Isolate::Current()),
- this_property_(Isolate::Current(), &this_proxy_, NULL, 0),
- call_sentinel_(Isolate::Current(), NULL, NULL, 0) {
-}
-
-
// ----------------------------------------------------------------------------
// All the Accept member functions for each syntax tree node type.
-void Slot::Accept(AstVisitor* v) { v->VisitSlot(this); }
-
#define DECL_ACCEPT(type) \
void type::Accept(AstVisitor* v) { v->Visit##type(this); }
AST_NODE_LIST(DECL_ACCEPT)
@@ -101,15 +90,6 @@ VariableProxy::VariableProxy(Isolate* isolate,
}
-VariableProxy::VariableProxy(Isolate* isolate, bool is_this)
- : Expression(isolate),
- var_(NULL),
- is_this_(is_this),
- inside_with_(false),
- is_trivial_(false) {
-}
-
-
void VariableProxy::BindTo(Variable* var) {
ASSERT(var_ == NULL); // must be bound only once
ASSERT(var != NULL); // must bind
@@ -414,12 +394,6 @@ bool TargetCollector::IsInlineable() const {
}
-bool Slot::IsInlineable() const {
- UNREACHABLE();
- return false;
-}
-
-
bool ForInStatement::IsInlineable() const {
return false;
}
@@ -487,12 +461,6 @@ bool SharedFunctionInfoLiteral::IsInlineable() const {
}
-bool ValidLeftHandSideSentinel::IsInlineable() const {
- UNREACHABLE();
- return false;
-}
-
-
bool ForStatement::IsInlineable() const {
return (init() == NULL || init()->IsInlineable())
&& (cond() == NULL || cond()->IsInlineable())
@@ -566,7 +534,7 @@ bool Conditional::IsInlineable() const {
bool VariableProxy::IsInlineable() const {
- return var()->is_global() || var()->IsStackAllocated();
+ return var()->IsUnallocated() || var()->IsStackAllocated();
}
diff --git a/deps/v8/src/ast.h b/deps/v8/src/ast.h
index 74182d5dc1..0eacb42102 100644
--- a/deps/v8/src/ast.h
+++ b/deps/v8/src/ast.h
@@ -134,6 +134,10 @@ class AstNode: public ZoneObject {
static const int kNoNumber = -1;
static const int kFunctionEntryId = 2; // Using 0 could disguise errors.
+ // This AST id identifies the point after the declarations have been
+ // visited. We need it to capture the environment effects of declarations
+ // that emit code (function declarations).
+ static const int kDeclarationsId = 3;
// Override ZoneObject's new to count allocated AST nodes.
void* operator new(size_t size, Zone* zone) {
@@ -161,7 +165,6 @@ class AstNode: public ZoneObject {
virtual BreakableStatement* AsBreakableStatement() { return NULL; }
virtual IterationStatement* AsIterationStatement() { return NULL; }
virtual MaterializedLiteral* AsMaterializedLiteral() { return NULL; }
- virtual Slot* AsSlot() { return NULL; }
// True if the node is simple enough for us to inline calls containing it.
virtual bool IsInlineable() const = 0;
@@ -316,20 +319,6 @@ class Expression: public AstNode {
};
-/**
- * A sentinel used during pre parsing that represents some expression
- * that is a valid left hand side without having to actually build
- * the expression.
- */
-class ValidLeftHandSideSentinel: public Expression {
- public:
- explicit ValidLeftHandSideSentinel(Isolate* isolate) : Expression(isolate) {}
- virtual bool IsValidLeftHandSide() { return true; }
- virtual void Accept(AstVisitor* v) { UNREACHABLE(); }
- virtual bool IsInlineable() const;
-};
-
-
class BreakableStatement: public Statement {
public:
enum Type {
@@ -404,10 +393,14 @@ class Block: public BreakableStatement {
class Declaration: public AstNode {
public:
- Declaration(VariableProxy* proxy, Variable::Mode mode, FunctionLiteral* fun)
+ Declaration(VariableProxy* proxy,
+ Variable::Mode mode,
+ FunctionLiteral* fun,
+ Scope* scope)
: proxy_(proxy),
mode_(mode),
- fun_(fun) {
+ fun_(fun),
+ scope_(scope) {
ASSERT(mode == Variable::VAR ||
mode == Variable::CONST ||
mode == Variable::LET);
@@ -421,11 +414,15 @@ class Declaration: public AstNode {
Variable::Mode mode() const { return mode_; }
FunctionLiteral* fun() const { return fun_; } // may be NULL
virtual bool IsInlineable() const;
+ Scope* scope() const { return scope_; }
private:
VariableProxy* proxy_;
Variable::Mode mode_;
FunctionLiteral* fun_;
+
+ // Nested scope from which the declaration originated.
+ Scope* scope_;
};
@@ -1114,9 +1111,6 @@ class VariableProxy: public Expression {
DECLARE_NODE_TYPE(VariableProxy)
- // Type testing & conversion
- Variable* AsVariable() { return (this == NULL) ? NULL : var_; }
-
virtual bool IsValidLeftHandSide() {
return var_ == NULL ? true : var_->IsValidLeftHandSide();
}
@@ -1133,10 +1127,7 @@ class VariableProxy: public Expression {
return !is_this() && name().is_identical_to(n);
}
- bool IsArguments() {
- Variable* variable = AsVariable();
- return (variable == NULL) ? false : variable->is_arguments();
- }
+ bool IsArguments() { return var_ != NULL && var_->is_arguments(); }
Handle<String> name() const { return name_; }
Variable* var() const { return var_; }
@@ -1162,73 +1153,11 @@ class VariableProxy: public Expression {
bool is_this,
bool inside_with,
int position = RelocInfo::kNoPosition);
- VariableProxy(Isolate* isolate, bool is_this);
friend class Scope;
};
-class VariableProxySentinel: public VariableProxy {
- public:
- virtual bool IsValidLeftHandSide() { return !is_this(); }
-
- private:
- VariableProxySentinel(Isolate* isolate, bool is_this)
- : VariableProxy(isolate, is_this) { }
-
- friend class AstSentinels;
-};
-
-
-class Slot: public Expression {
- public:
- enum Type {
- // A slot in the parameter section on the stack. index() is
- // the parameter index, counting left-to-right, starting at 0.
- PARAMETER,
-
- // A slot in the local section on the stack. index() is
- // the variable index in the stack frame, starting at 0.
- LOCAL,
-
- // An indexed slot in a heap context. index() is the
- // variable index in the context object on the heap,
- // starting at 0. var()->scope() is the corresponding
- // scope.
- CONTEXT,
-
- // A named slot in a heap context. var()->name() is the
- // variable name in the context object on the heap,
- // with lookup starting at the current context. index()
- // is invalid.
- LOOKUP
- };
-
- Slot(Isolate* isolate, Variable* var, Type type, int index)
- : Expression(isolate), var_(var), type_(type), index_(index) {
- ASSERT(var != NULL);
- }
-
- virtual void Accept(AstVisitor* v);
-
- virtual Slot* AsSlot() { return this; }
-
- bool IsStackAllocated() { return type_ == PARAMETER || type_ == LOCAL; }
-
- // Accessors
- Variable* var() const { return var_; }
- Type type() const { return type_; }
- int index() const { return index_; }
- bool is_arguments() const { return var_->is_arguments(); }
- virtual bool IsInlineable() const;
-
- private:
- Variable* var_;
- Type type_;
- int index_;
-};
-
-
class Property: public Expression {
public:
Property(Isolate* isolate,
@@ -1337,36 +1266,6 @@ class Call: public Expression {
};
-class AstSentinels {
- public:
- ~AstSentinels() { }
-
- // Returns a property singleton property access on 'this'. Used
- // during preparsing.
- Property* this_property() { return &this_property_; }
- VariableProxySentinel* this_proxy() { return &this_proxy_; }
- VariableProxySentinel* identifier_proxy() { return &identifier_proxy_; }
- ValidLeftHandSideSentinel* valid_left_hand_side_sentinel() {
- return &valid_left_hand_side_sentinel_;
- }
- Call* call_sentinel() { return &call_sentinel_; }
- EmptyStatement* empty_statement() { return &empty_statement_; }
-
- private:
- AstSentinels();
- VariableProxySentinel this_proxy_;
- VariableProxySentinel identifier_proxy_;
- ValidLeftHandSideSentinel valid_left_hand_side_sentinel_;
- Property this_property_;
- Call call_sentinel_;
- EmptyStatement empty_statement_;
-
- friend class Isolate;
-
- DISALLOW_COPY_AND_ASSIGN(AstSentinels);
-};
-
-
class CallNew: public Expression {
public:
CallNew(Isolate* isolate,
@@ -2239,9 +2138,6 @@ class AstVisitor BASE_EMBEDDED {
void SetStackOverflow() { stack_overflow_ = true; }
void ClearStackOverflow() { stack_overflow_ = false; }
- // Nodes not appearing in the AST, including slots.
- virtual void VisitSlot(Slot* node) { UNREACHABLE(); }
-
// Individual AST nodes.
#define DEF_VISIT(type) \
virtual void Visit##type(type* node) = 0;
diff --git a/deps/v8/src/bootstrapper.cc b/deps/v8/src/bootstrapper.cc
index 4f7cf40940..7abd45cac0 100644
--- a/deps/v8/src/bootstrapper.cc
+++ b/deps/v8/src/bootstrapper.cc
@@ -350,7 +350,14 @@ static Handle<JSFunction> InstallFunction(Handle<JSObject> target,
prototype,
call_code,
is_ecma_native);
- SetLocalPropertyNoThrow(target, symbol, function, DONT_ENUM);
+ PropertyAttributes attributes;
+ if (target->IsJSBuiltinsObject()) {
+ attributes =
+ static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
+ } else {
+ attributes = DONT_ENUM;
+ }
+ SetLocalPropertyNoThrow(target, symbol, function, attributes);
if (is_ecma_native) {
function->shared()->set_instance_class_name(*symbol);
}
@@ -1160,7 +1167,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
{
- // Setup the call-as-function delegate.
+ // Set up the call-as-function delegate.
Handle<Code> code =
Handle<Code>(isolate->builtins()->builtin(
Builtins::kHandleApiCallAsFunction));
@@ -1172,7 +1179,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
}
{
- // Setup the call-as-constructor delegate.
+ // Set up the call-as-constructor delegate.
Handle<Code> code =
Handle<Code>(isolate->builtins()->builtin(
Builtins::kHandleApiCallAsConstructor));
@@ -1192,15 +1199,15 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
void Genesis::InitializeExperimentalGlobal() {
- Isolate* isolate = this->isolate();
Handle<JSObject> global = Handle<JSObject>(global_context()->global());
// TODO(mstarzinger): Move this into Genesis::InitializeGlobal once we no
// longer need to live behind a flag, so WeakMap gets added to the snapshot.
if (FLAG_harmony_weakmaps) { // -- W e a k M a p
+ Handle<JSObject> prototype =
+ factory()->NewJSObject(isolate()->object_function(), TENURED);
InstallFunction(global, "WeakMap", JS_WEAK_MAP_TYPE, JSWeakMap::kSize,
- isolate->initial_object_prototype(),
- Builtins::kIllegal, true);
+ prototype, Builtins::kIllegal, true);
}
}
@@ -1677,7 +1684,6 @@ bool Genesis::InstallNatives() {
global_context()->set_regexp_result_map(*initial_map);
}
-
#ifdef DEBUG
builtins->Verify();
#endif
diff --git a/deps/v8/src/checks.h b/deps/v8/src/checks.h
index a560b2fb15..2f359f6cd8 100644
--- a/deps/v8/src/checks.h
+++ b/deps/v8/src/checks.h
@@ -251,9 +251,9 @@ template <> class StaticAssertion<true> { };
// actually causes each use to introduce a new defined type with a
// name depending on the source line.
template <int> class StaticAssertionHelper { };
-#define STATIC_CHECK(test) \
- typedef \
- StaticAssertionHelper<sizeof(StaticAssertion<static_cast<bool>(test)>)> \
+#define STATIC_CHECK(test) \
+ typedef \
+ StaticAssertionHelper<sizeof(StaticAssertion<static_cast<bool>((test))>)> \
SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__)
diff --git a/deps/v8/src/contexts.cc b/deps/v8/src/contexts.cc
index c0e724253f..4f93abdff1 100644
--- a/deps/v8/src/contexts.cc
+++ b/deps/v8/src/contexts.cc
@@ -87,13 +87,15 @@ void Context::set_global_proxy(JSObject* object) {
Handle<Object> Context::Lookup(Handle<String> name,
ContextLookupFlags flags,
int* index_,
- PropertyAttributes* attributes) {
+ PropertyAttributes* attributes,
+ BindingFlags* binding_flags) {
Isolate* isolate = GetIsolate();
Handle<Context> context(this, isolate);
bool follow_context_chain = (flags & FOLLOW_CONTEXT_CHAIN) != 0;
*index_ = -1;
*attributes = ABSENT;
+ *binding_flags = MISSING_BINDING;
if (FLAG_trace_contexts) {
PrintF("Context::Lookup(");
@@ -118,6 +120,7 @@ Handle<Object> Context::Lookup(Handle<String> name,
}
*index_ = Context::THROWN_OBJECT_INDEX;
*attributes = NONE;
+ *binding_flags = MUTABLE_IS_INITIALIZED;
return context;
}
} else {
@@ -180,11 +183,16 @@ Handle<Object> Context::Lookup(Handle<String> name,
switch (mode) {
case Variable::INTERNAL: // Fall through.
case Variable::VAR:
+ *attributes = NONE;
+ *binding_flags = MUTABLE_IS_INITIALIZED;
+ break;
case Variable::LET:
*attributes = NONE;
+ *binding_flags = MUTABLE_CHECK_INITIALIZED;
break;
case Variable::CONST:
*attributes = READ_ONLY;
+ *binding_flags = IMMUTABLE_CHECK_INITIALIZED;
break;
case Variable::DYNAMIC:
case Variable::DYNAMIC_GLOBAL:
@@ -207,6 +215,7 @@ Handle<Object> Context::Lookup(Handle<String> name,
}
*index_ = index;
*attributes = READ_ONLY;
+ *binding_flags = IMMUTABLE_IS_INITIALIZED;
return context;
}
}
diff --git a/deps/v8/src/contexts.h b/deps/v8/src/contexts.h
index 3d9e7f4bfe..505f86c8ca 100644
--- a/deps/v8/src/contexts.h
+++ b/deps/v8/src/contexts.h
@@ -44,6 +44,30 @@ enum ContextLookupFlags {
};
+// ES5 10.2 defines lexical environments with mutable and immutable bindings.
+// Immutable bindings have two states, initialized and uninitialized, and
+// their state is changed by the InitializeImmutableBinding method.
+//
+// The harmony proposal for block scoped bindings also introduces the
+// uninitialized state for mutable bindings. A 'let' declared variable
+// is a mutable binding that is created uninitalized upon activation of its
+// lexical environment and it is initialized when evaluating its declaration
+// statement. Var declared variables are mutable bindings that are
+// immediately initialized upon creation. The BindingFlags enum represents
+// information if a binding has definitely been initialized. 'const' declared
+// variables are created as uninitialized immutable bindings.
+
+// In harmony mode accessing an uninitialized binding produces a reference
+// error.
+enum BindingFlags {
+ MUTABLE_IS_INITIALIZED,
+ MUTABLE_CHECK_INITIALIZED,
+ IMMUTABLE_IS_INITIALIZED,
+ IMMUTABLE_CHECK_INITIALIZED,
+ MISSING_BINDING
+};
+
+
// Heap-allocated activation contexts.
//
// Contexts are implemented as FixedArray objects; the Context
@@ -351,8 +375,11 @@ class Context: public FixedArray {
// 4) index_ < 0 && result.is_null():
// there was no context found with the corresponding property.
// attributes == ABSENT.
- Handle<Object> Lookup(Handle<String> name, ContextLookupFlags flags,
- int* index_, PropertyAttributes* attributes);
+ Handle<Object> Lookup(Handle<String> name,
+ ContextLookupFlags flags,
+ int* index_,
+ PropertyAttributes* attributes,
+ BindingFlags* binding_flags);
// Determine if a local variable with the given name exists in a
// context. Do not consider context extension objects. This is
diff --git a/deps/v8/src/conversions.h b/deps/v8/src/conversions.h
index 7b02c47f6a..0f8d5da8ee 100644
--- a/deps/v8/src/conversions.h
+++ b/deps/v8/src/conversions.h
@@ -45,14 +45,14 @@ namespace internal {
const int kMaxSignificantDigits = 772;
-static bool isDigit(int x, int radix) {
+static inline bool isDigit(int x, int radix) {
return (x >= '0' && x <= '9' && x < '0' + radix)
|| (radix > 10 && x >= 'a' && x < 'a' + radix - 10)
|| (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
}
-static double SignedZero(bool negative) {
+static inline double SignedZero(bool negative) {
return negative ? -0.0 : 0.0;
}
diff --git a/deps/v8/src/d8.cc b/deps/v8/src/d8.cc
index 120496eccc..5c60436892 100644
--- a/deps/v8/src/d8.cc
+++ b/deps/v8/src/d8.cc
@@ -176,8 +176,8 @@ bool Shell::ExecuteString(Handle<String> source,
// If all went well and the result wasn't undefined then print
// the returned value.
v8::String::Utf8Value str(result);
- const char* cstr = ToCString(str);
- printf("%s\n", cstr);
+ fwrite(*str, sizeof(**str), str.length(), stdout);
+ printf("\n");
}
return true;
}
@@ -678,12 +678,12 @@ Handle<ObjectTemplate> Shell::CreateGlobalTemplate() {
FunctionTemplate::New(PixelArray));
#ifdef LIVE_OBJECT_LIST
- global_template->Set(String::New("lol_is_enabled"), Boolean::New(true));
+ global_template->Set(String::New("lol_is_enabled"), True());
#else
- global_template->Set(String::New("lol_is_enabled"), Boolean::New(false));
+ global_template->Set(String::New("lol_is_enabled"), False());
#endif
-#ifndef V8_SHARED
+#if !defined(V8_SHARED) && !defined(_WIN32) && !defined(_WIN64)
Handle<ObjectTemplate> os_templ = ObjectTemplate::New();
AddOSMethods(os_templ);
global_template->Set(String::New("os"), os_templ);
@@ -864,7 +864,7 @@ Handle<String> Shell::ReadFile(const char* name) {
void Shell::RunShell() {
Locker locker;
Context::Scope context_scope(evaluation_context_);
- HandleScope handle_scope;
+ HandleScope outer_scope;
Handle<String> name = String::New("(d8)");
#ifndef V8_SHARED
LineEditor* editor = LineEditor::Get();
@@ -877,6 +877,7 @@ void Shell::RunShell() {
i::SmartPointer<char> input = editor->Prompt(Shell::kPrompt);
if (input.is_empty()) break;
editor->AddHistory(*input);
+ HandleScope inner_scope;
ExecuteString(String::New(*input), name, true, true);
}
editor->Close();
@@ -887,6 +888,7 @@ void Shell::RunShell() {
char buffer[kBufferSize];
printf("%s", Shell::kPrompt);
if (fgets(buffer, kBufferSize, stdin) == NULL) break;
+ HandleScope inner_scope;
ExecuteString(String::New(buffer), name, true, true);
}
#endif // V8_SHARED
diff --git a/deps/v8/src/d8.js b/deps/v8/src/d8.js
index a2b9585ce8..3009037e78 100644
--- a/deps/v8/src/d8.js
+++ b/deps/v8/src/d8.js
@@ -1786,7 +1786,7 @@ function decodeLolInfoResponse(body) {
function decodeLolListResponse(body, title) {
-
+
var result;
var total_count = body.count;
var total_size = body.size;
diff --git a/deps/v8/src/date.js b/deps/v8/src/date.js
index 79b846d4a7..ccefce5763 100644
--- a/deps/v8/src/date.js
+++ b/deps/v8/src/date.js
@@ -1048,18 +1048,19 @@ function ResetDateCache() {
// -------------------------------------------------------------------
-function SetupDate() {
- // Setup non-enumerable properties of the Date object itself.
+function SetUpDate() {
+ %CheckIsBootstrapping();
+ // Set up non-enumerable properties of the Date object itself.
InstallFunctions($Date, DONT_ENUM, $Array(
"UTC", DateUTC,
"parse", DateParse,
"now", DateNow
));
- // Setup non-enumerable constructor property of the Date prototype object.
+ // Set up non-enumerable constructor property of the Date prototype object.
%SetProperty($Date.prototype, "constructor", $Date, DONT_ENUM);
- // Setup non-enumerable functions of the Date prototype object and
+ // Set up non-enumerable functions of the Date prototype object and
// set their names.
InstallFunctionsOnHiddenPrototype($Date.prototype, DONT_ENUM, $Array(
"toString", DateToString,
@@ -1111,4 +1112,4 @@ function SetupDate() {
));
}
-SetupDate();
+SetUpDate();
diff --git a/deps/v8/src/elements.cc b/deps/v8/src/elements.cc
index 70d58b31ac..1afc5dad5e 100644
--- a/deps/v8/src/elements.cc
+++ b/deps/v8/src/elements.cc
@@ -590,7 +590,6 @@ ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) {
default:
UNREACHABLE();
return NULL;
- break;
}
}
diff --git a/deps/v8/src/extensions/externalize-string-extension.cc b/deps/v8/src/extensions/externalize-string-extension.cc
index b3f83fe98d..9fbf329818 100644
--- a/deps/v8/src/extensions/externalize-string-extension.cc
+++ b/deps/v8/src/extensions/externalize-string-extension.cc
@@ -133,9 +133,11 @@ v8::Handle<v8::Value> ExternalizeStringExtension::IsAscii(
void ExternalizeStringExtension::Register() {
- static ExternalizeStringExtension externalize_extension;
+ static ExternalizeStringExtension* externalize_extension = NULL;
+ if (externalize_extension == NULL)
+ externalize_extension = new ExternalizeStringExtension;
static v8::DeclareExtension externalize_extension_declaration(
- &externalize_extension);
+ externalize_extension);
}
} } // namespace v8::internal
diff --git a/deps/v8/src/full-codegen.cc b/deps/v8/src/full-codegen.cc
index fc7b6899bc..d810bb3dc0 100644
--- a/deps/v8/src/full-codegen.cc
+++ b/deps/v8/src/full-codegen.cc
@@ -190,9 +190,9 @@ void BreakableStatementChecker::VisitArrayLiteral(ArrayLiteral* expr) {
void BreakableStatementChecker::VisitAssignment(Assignment* expr) {
// If assigning to a property (including a global property) the assignment is
// breakable.
- Variable* var = expr->target()->AsVariableProxy()->AsVariable();
+ VariableProxy* proxy = expr->target()->AsVariableProxy();
Property* prop = expr->target()->AsProperty();
- if (prop != NULL || (var != NULL && var->is_global())) {
+ if (prop != NULL || (proxy != NULL && proxy->var()->IsUnallocated())) {
is_breakable_ = true;
return;
}
@@ -395,26 +395,6 @@ void FullCodeGenerator::RecordStackCheck(int ast_id) {
}
-int FullCodeGenerator::SlotOffset(Slot* slot) {
- ASSERT(slot != NULL);
- // Offset is negative because higher indexes are at lower addresses.
- int offset = -slot->index() * kPointerSize;
- // Adjust by a (parameter or local) base offset.
- switch (slot->type()) {
- case Slot::PARAMETER:
- offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
- break;
- case Slot::LOCAL:
- offset += JavaScriptFrameConstants::kLocal0Offset;
- break;
- case Slot::CONTEXT:
- case Slot::LOOKUP:
- UNREACHABLE();
- }
- return offset;
-}
-
-
bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) {
// Inline smi case inside loops, but not division and modulo which
// are too complicated and take up too much space.
@@ -529,34 +509,21 @@ void FullCodeGenerator::DoTest(const TestContext* context) {
void FullCodeGenerator::VisitDeclarations(
ZoneList<Declaration*>* declarations) {
int length = declarations->length();
- int globals = 0;
+ int global_count = 0;
for (int i = 0; i < length; i++) {
Declaration* decl = declarations->at(i);
- Variable* var = decl->proxy()->var();
- Slot* slot = var->AsSlot();
-
- // If it was not possible to allocate the variable at compile
- // time, we need to "declare" it at runtime to make sure it
- // actually exists in the local context.
- if ((slot != NULL && slot->type() == Slot::LOOKUP) || !var->is_global()) {
- VisitDeclaration(decl);
- } else {
- // Count global variables and functions for later processing
- globals++;
- }
+ EmitDeclaration(decl->proxy(), decl->mode(), decl->fun(), &global_count);
}
- // Compute array of global variable and function declarations.
- // Do nothing in case of no declared global functions or variables.
- if (globals > 0) {
+ // Batch declare global functions and variables.
+ if (global_count > 0) {
Handle<FixedArray> array =
- isolate()->factory()->NewFixedArray(2 * globals, TENURED);
+ isolate()->factory()->NewFixedArray(2 * global_count, TENURED);
for (int j = 0, i = 0; i < length; i++) {
Declaration* decl = declarations->at(i);
Variable* var = decl->proxy()->var();
- Slot* slot = var->AsSlot();
- if ((slot == NULL || slot->type() != Slot::LOOKUP) && var->is_global()) {
+ if (var->IsUnallocated()) {
array->set(j++, *(var->name()));
if (decl->fun() == NULL) {
if (var->mode() == Variable::CONST) {
@@ -578,12 +545,21 @@ void FullCodeGenerator::VisitDeclarations(
}
}
// Invoke the platform-dependent code generator to do the actual
- // declaration the global variables and functions.
+ // declaration the global functions and variables.
DeclareGlobals(array);
}
}
+int FullCodeGenerator::DeclareGlobalsFlags() {
+ int flags = 0;
+ if (is_eval()) flags |= kDeclareGlobalsEvalFlag;
+ if (is_strict_mode()) flags |= kDeclareGlobalsStrictModeFlag;
+ if (is_native()) flags |= kDeclareGlobalsNativeFlag;
+ return flags;
+}
+
+
void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) {
CodeGenerator::RecordPositions(masm_, fun->start_position());
}
@@ -842,10 +818,11 @@ void FullCodeGenerator::VisitInCurrentContext(Expression* expr) {
void FullCodeGenerator::VisitBlock(Block* stmt) {
Comment cmnt(masm_, "[ Block");
- Breakable nested_statement(this, stmt);
+ NestedBlock nested_block(this, stmt);
SetStatementPosition(stmt);
Scope* saved_scope = scope();
+ // Push a block context when entering a block with block scoped variables.
if (stmt->block_scope() != NULL) {
{ Comment cmnt(masm_, "[ Extend block context");
scope_ = stmt->block_scope();
@@ -862,8 +839,16 @@ void FullCodeGenerator::VisitBlock(Block* stmt) {
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
VisitStatements(stmt->statements());
scope_ = saved_scope;
- __ bind(nested_statement.break_label());
+ __ bind(nested_block.break_label());
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+
+ // Pop block context if necessary.
+ if (stmt->block_scope() != NULL) {
+ LoadContextField(context_register(), Context::PREVIOUS_INDEX);
+ // Update local stack frame context field.
+ StoreToFrameField(StandardFrameConstants::kContextOffset,
+ context_register());
+ }
}
@@ -1336,25 +1321,6 @@ void FullCodeGenerator::VisitThrow(Throw* expr) {
}
-FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
- int* stack_depth,
- int* context_length) {
- // The macros used here must preserve the result register.
- __ Drop(*stack_depth);
- __ PopTryHandler();
- *stack_depth = 0;
-
- Register context = FullCodeGenerator::context_register();
- while (*context_length > 0) {
- codegen_->LoadContextField(context, Context::PREVIOUS_INDEX);
- --(*context_length);
- }
-
- __ Call(finally_entry_);
- return previous_;
-}
-
-
FullCodeGenerator::NestedStatement* FullCodeGenerator::TryCatch::Exit(
int* stack_depth,
int* context_length) {
diff --git a/deps/v8/src/full-codegen.h b/deps/v8/src/full-codegen.h
index 0ed26a149e..803c618732 100644
--- a/deps/v8/src/full-codegen.h
+++ b/deps/v8/src/full-codegen.h
@@ -191,6 +191,22 @@ class FullCodeGenerator: public AstVisitor {
Label continue_label_;
};
+ // A nested block statement.
+ class NestedBlock : public Breakable {
+ public:
+ NestedBlock(FullCodeGenerator* codegen, Block* block)
+ : Breakable(codegen, block) {
+ }
+ virtual ~NestedBlock() {}
+
+ virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
+ if (statement()->AsBlock()->block_scope() != NULL) {
+ ++(*context_length);
+ }
+ return previous_;
+ };
+ };
+
// The try block of a try/catch statement.
class TryCatch : public NestedStatement {
public:
@@ -288,10 +304,6 @@ class FullCodeGenerator: public AstVisitor {
// with a GC-safe value.
void ClearAccumulator();
- // Compute the frame pointer relative offset for a given local or
- // parameter slot.
- int SlotOffset(Slot* slot);
-
// Determine whether or not to inline the smi case for the given
// operation.
bool ShouldInlineSmiCase(Token::Value op);
@@ -321,13 +333,29 @@ class FullCodeGenerator: public AstVisitor {
Label* fall_through);
#endif // V8_TARGET_ARCH_MIPS
- void Move(Slot* dst, Register source, Register scratch1, Register scratch2);
- void Move(Register dst, Slot* source);
-
- // Return an operand used to read/write to a known (ie, non-LOOKUP) slot.
- // May emit code to traverse the context chain, destroying the scratch
- // register.
- MemOperand EmitSlotSearch(Slot* slot, Register scratch);
+ // Load the value of a known (PARAMETER, LOCAL, or CONTEXT) variable into
+ // a register. Emits a context chain walk if if necessary (so does
+ // SetVar) so avoid calling both on the same variable.
+ void GetVar(Register destination, Variable* var);
+
+ // Assign to a known (PARAMETER, LOCAL, or CONTEXT) variable. If it's in
+ // the context, the write barrier will be emitted and source, scratch0,
+ // scratch1 will be clobbered. Emits a context chain walk if if necessary
+ // (so does GetVar) so avoid calling both on the same variable.
+ void SetVar(Variable* var,
+ Register source,
+ Register scratch0,
+ Register scratch1);
+
+ // An operand used to read/write a stack-allocated (PARAMETER or LOCAL)
+ // variable. Writing does not need the write barrier.
+ MemOperand StackOperand(Variable* var);
+
+ // An operand used to read/write a known (PARAMETER, LOCAL, or CONTEXT)
+ // variable. May emit code to traverse the context chain, loading the
+ // found context into the scratch register. Writing to this operand will
+ // need the write barrier if location is CONTEXT.
+ MemOperand VarOperand(Variable* var, Register scratch);
// Forward the bailout responsibility for the given expression to
// the next child visited (which must be in a test context).
@@ -358,6 +386,7 @@ class FullCodeGenerator: public AstVisitor {
void VisitDeclarations(ZoneList<Declaration*>* declarations);
void DeclareGlobals(Handle<FixedArray> pairs);
+ int DeclareGlobalsFlags();
// Try to perform a comparison as a fast inlined literal compare if
// the operands allow it. Returns true if the compare operations
@@ -402,9 +431,10 @@ class FullCodeGenerator: public AstVisitor {
// Platform-specific code for a variable, constant, or function
// declaration. Functions have an initial value.
- void EmitDeclaration(Variable* variable,
+ void EmitDeclaration(VariableProxy* proxy,
Variable::Mode mode,
- FunctionLiteral* function);
+ FunctionLiteral* function,
+ int* global_count);
// Platform-specific code for checking the stack limit at the back edge of
// a loop.
@@ -435,14 +465,14 @@ class FullCodeGenerator: public AstVisitor {
#undef EMIT_INLINE_RUNTIME_CALL
// Platform-specific code for loading variables.
- void EmitLoadGlobalSlotCheckExtensions(Slot* slot,
- TypeofState typeof_state,
- Label* slow);
- MemOperand ContextSlotOperandCheckExtensions(Slot* slot, Label* slow);
- void EmitDynamicLoadFromSlotFastCase(Slot* slot,
- TypeofState typeof_state,
- Label* slow,
- Label* done);
+ void EmitLoadGlobalCheckExtensions(Variable* var,
+ TypeofState typeof_state,
+ Label* slow);
+ MemOperand ContextSlotOperandCheckExtensions(Variable* var, Label* slow);
+ void EmitDynamicLookupFastCase(Variable* var,
+ TypeofState typeof_state,
+ Label* slow,
+ Label* done);
void EmitVariableLoad(VariableProxy* proxy);
enum ResolveEvalFlag {
@@ -555,6 +585,7 @@ class FullCodeGenerator: public AstVisitor {
Handle<Script> script() { return info_->script(); }
bool is_eval() { return info_->is_eval(); }
+ bool is_native() { return info_->is_native(); }
bool is_strict_mode() { return function()->strict_mode(); }
StrictModeFlag strict_mode_flag() {
return is_strict_mode() ? kStrictMode : kNonStrictMode;
@@ -618,11 +649,11 @@ class FullCodeGenerator: public AstVisitor {
// this expression context.
virtual void Plug(bool flag) const = 0;
- // Emit code to convert a pure value (in a register, slot, as a literal,
- // or on top of the stack) into the result expected according to this
- // expression context.
+ // Emit code to convert a pure value (in a register, known variable
+ // location, as a literal, or on top of the stack) into the result
+ // expected according to this expression context.
virtual void Plug(Register reg) const = 0;
- virtual void Plug(Slot* slot) const = 0;
+ virtual void Plug(Variable* var) const = 0;
virtual void Plug(Handle<Object> lit) const = 0;
virtual void Plug(Heap::RootListIndex index) const = 0;
virtual void PlugTOS() const = 0;
@@ -680,7 +711,7 @@ class FullCodeGenerator: public AstVisitor {
virtual void Plug(bool flag) const;
virtual void Plug(Register reg) const;
virtual void Plug(Label* materialize_true, Label* materialize_false) const;
- virtual void Plug(Slot* slot) const;
+ virtual void Plug(Variable* var) const;
virtual void Plug(Handle<Object> lit) const;
virtual void Plug(Heap::RootListIndex) const;
virtual void PlugTOS() const;
@@ -703,7 +734,7 @@ class FullCodeGenerator: public AstVisitor {
virtual void Plug(bool flag) const;
virtual void Plug(Register reg) const;
virtual void Plug(Label* materialize_true, Label* materialize_false) const;
- virtual void Plug(Slot* slot) const;
+ virtual void Plug(Variable* var) const;
virtual void Plug(Handle<Object> lit) const;
virtual void Plug(Heap::RootListIndex) const;
virtual void PlugTOS() const;
@@ -744,7 +775,7 @@ class FullCodeGenerator: public AstVisitor {
virtual void Plug(bool flag) const;
virtual void Plug(Register reg) const;
virtual void Plug(Label* materialize_true, Label* materialize_false) const;
- virtual void Plug(Slot* slot) const;
+ virtual void Plug(Variable* var) const;
virtual void Plug(Handle<Object> lit) const;
virtual void Plug(Heap::RootListIndex) const;
virtual void PlugTOS() const;
@@ -774,7 +805,7 @@ class FullCodeGenerator: public AstVisitor {
virtual void Plug(bool flag) const;
virtual void Plug(Register reg) const;
virtual void Plug(Label* materialize_true, Label* materialize_false) const;
- virtual void Plug(Slot* slot) const;
+ virtual void Plug(Variable* var) const;
virtual void Plug(Handle<Object> lit) const;
virtual void Plug(Heap::RootListIndex) const;
virtual void PlugTOS() const;
diff --git a/deps/v8/src/heap.cc b/deps/v8/src/heap.cc
index 90d0e11edd..a480e9e331 100644
--- a/deps/v8/src/heap.cc
+++ b/deps/v8/src/heap.cc
@@ -81,14 +81,14 @@ Heap::Heap()
reserved_semispace_size_(16*MB),
max_semispace_size_(16*MB),
initial_semispace_size_(1*MB),
- max_old_generation_size_(1*GB),
+ max_old_generation_size_(1400*MB),
max_executable_size_(256*MB),
code_range_size_(512*MB),
#else
reserved_semispace_size_(8*MB),
max_semispace_size_(8*MB),
initial_semispace_size_(512*KB),
- max_old_generation_size_(512*MB),
+ max_old_generation_size_(700*MB),
max_executable_size_(128*MB),
code_range_size_(0),
#endif
@@ -842,6 +842,7 @@ void Heap::MarkCompactPrologue(bool is_compacting) {
isolate_->keyed_lookup_cache()->Clear();
isolate_->context_slot_cache()->Clear();
isolate_->descriptor_lookup_cache()->Clear();
+ StringSplitCache::Clear(string_split_cache());
isolate_->compilation_cache()->MarkCompactPrologue();
@@ -2223,6 +2224,13 @@ bool Heap::CreateInitialObjects() {
}
set_single_character_string_cache(FixedArray::cast(obj));
+ // Allocate cache for string split.
+ { MaybeObject* maybe_obj =
+ AllocateFixedArray(StringSplitCache::kStringSplitCacheSize, TENURED);
+ if (!maybe_obj->ToObject(&obj)) return false;
+ }
+ set_string_split_cache(FixedArray::cast(obj));
+
// Allocate cache for external strings pointing to native source code.
{ MaybeObject* maybe_obj = AllocateFixedArray(Natives::GetBuiltinsCount());
if (!maybe_obj->ToObject(&obj)) return false;
@@ -2248,6 +2256,75 @@ bool Heap::CreateInitialObjects() {
}
+Object* StringSplitCache::Lookup(
+ FixedArray* cache, String* string, String* pattern) {
+ if (!string->IsSymbol() || !pattern->IsSymbol()) return Smi::FromInt(0);
+ uintptr_t hash = string->Hash();
+ uintptr_t index = ((hash & (kStringSplitCacheSize - 1)) &
+ ~(kArrayEntriesPerCacheEntry - 1));
+ if (cache->get(index + kStringOffset) == string &&
+ cache->get(index + kPatternOffset) == pattern) {
+ return cache->get(index + kArrayOffset);
+ }
+ index = ((index + kArrayEntriesPerCacheEntry) & (kStringSplitCacheSize - 1));
+ if (cache->get(index + kStringOffset) == string &&
+ cache->get(index + kPatternOffset) == pattern) {
+ return cache->get(index + kArrayOffset);
+ }
+ return Smi::FromInt(0);
+}
+
+
+void StringSplitCache::Enter(Heap* heap,
+ FixedArray* cache,
+ String* string,
+ String* pattern,
+ FixedArray* array) {
+ if (!string->IsSymbol() || !pattern->IsSymbol()) return;
+ uintptr_t hash = string->Hash();
+ array->set_map(heap->fixed_cow_array_map());
+ uintptr_t index = ((hash & (kStringSplitCacheSize - 1)) &
+ ~(kArrayEntriesPerCacheEntry - 1));
+ if (cache->get(index + kStringOffset) == Smi::FromInt(0)) {
+ cache->set(index + kStringOffset, string);
+ cache->set(index + kPatternOffset, pattern);
+ cache->set(index + kArrayOffset, array);
+ return;
+ }
+ uintptr_t index2 =
+ ((index + kArrayEntriesPerCacheEntry) & (kStringSplitCacheSize - 1));
+ if (cache->get(index2 + kStringOffset) == Smi::FromInt(0)) {
+ cache->set(index2 + kStringOffset, string);
+ cache->set(index2 + kPatternOffset, pattern);
+ cache->set(index2 + kArrayOffset, array);
+ return;
+ }
+ cache->set(index2 + kStringOffset, Smi::FromInt(0));
+ cache->set(index2 + kPatternOffset, Smi::FromInt(0));
+ cache->set(index2 + kArrayOffset, Smi::FromInt(0));
+ cache->set(index + kStringOffset, string);
+ cache->set(index + kPatternOffset, pattern);
+ cache->set(index + kArrayOffset, array);
+ if (array->length() < 100) { // Limit how many new symbols we want to make.
+ for (int i = 0; i < array->length(); i++) {
+ String* str = String::cast(array->get(i));
+ Object* symbol;
+ MaybeObject* maybe_symbol = heap->LookupSymbol(str);
+ if (maybe_symbol->ToObject(&symbol)) {
+ array->set(i, symbol);
+ }
+ }
+ }
+}
+
+
+void StringSplitCache::Clear(FixedArray* cache) {
+ for (int i = 0; i < kStringSplitCacheSize; i++) {
+ cache->set(i, Smi::FromInt(0));
+ }
+}
+
+
MaybeObject* Heap::InitializeNumberStringCache() {
// Compute the size of the number string cache based on the max heap size.
// max_semispace_size_ == 512 KB => number_string_cache_size = 32.
@@ -4085,10 +4162,9 @@ MaybeObject* Heap::AllocateBlockContext(JSFunction* function,
SerializedScopeInfo* scope_info) {
Object* result;
{ MaybeObject* maybe_result =
- AllocateFixedArray(scope_info->NumberOfContextSlots());
+ AllocateFixedArrayWithHoles(scope_info->NumberOfContextSlots());
if (!maybe_result->ToObject(&result)) return maybe_result;
}
- // TODO(keuchel): properly initialize context slots.
Context* context = reinterpret_cast<Context*>(result);
context->set_map(block_context_map());
context->set_closure(function);
diff --git a/deps/v8/src/heap.h b/deps/v8/src/heap.h
index 0f69fab391..cc689df17b 100644
--- a/deps/v8/src/heap.h
+++ b/deps/v8/src/heap.h
@@ -77,6 +77,7 @@ inline Heap* _inline_get_heap_();
V(Object, instanceof_cache_map, InstanceofCacheMap) \
V(Object, instanceof_cache_answer, InstanceofCacheAnswer) \
V(FixedArray, single_character_string_cache, SingleCharacterStringCache) \
+ V(FixedArray, string_split_cache, StringSplitCache) \
V(Object, termination_exception, TerminationException) \
V(FixedArray, empty_fixed_array, EmptyFixedArray) \
V(ByteArray, empty_byte_array, EmptyByteArray) \
@@ -225,8 +226,7 @@ inline Heap* _inline_get_heap_();
V(closure_symbol, "(closure)") \
V(use_strict, "use strict") \
V(dot_symbol, ".") \
- V(anonymous_function_symbol, "(anonymous function)") \
- V(block_scope_symbol, ".block")
+ V(anonymous_function_symbol, "(anonymous function)")
// Forward declarations.
class GCTracer;
@@ -2177,6 +2177,27 @@ class GCTracer BASE_EMBEDDED {
};
+class StringSplitCache {
+ public:
+ static Object* Lookup(FixedArray* cache, String* string, String* pattern);
+ static void Enter(Heap* heap,
+ FixedArray* cache,
+ String* string,
+ String* pattern,
+ FixedArray* array);
+ static void Clear(FixedArray* cache);
+ static const int kStringSplitCacheSize = 0x100;
+
+ private:
+ static const int kArrayEntriesPerCacheEntry = 4;
+ static const int kStringOffset = 0;
+ static const int kPatternOffset = 1;
+ static const int kArrayOffset = 2;
+
+ static MaybeObject* WrapFixedArrayInJSArray(Object* fixed_array);
+};
+
+
class TranscendentalCache {
public:
enum Type {ACOS, ASIN, ATAN, COS, EXP, LOG, SIN, TAN, kNumberOfCaches};
diff --git a/deps/v8/src/hydrogen-instructions.cc b/deps/v8/src/hydrogen-instructions.cc
index d3cc8a62b4..14e1bc8a46 100644
--- a/deps/v8/src/hydrogen-instructions.cc
+++ b/deps/v8/src/hydrogen-instructions.cc
@@ -425,7 +425,7 @@ void HValue::PrintRangeTo(StringStream* stream) {
void HValue::PrintChangesTo(StringStream* stream) {
- int changes_flags = (flags() & HValue::ChangesFlagsMask());
+ int changes_flags = ChangesFlags();
if (changes_flags == 0) return;
stream->Add(" changes[");
if (changes_flags == AllSideEffects()) {
@@ -512,9 +512,7 @@ void HInstruction::PrintTo(StringStream* stream) {
void HInstruction::PrintMnemonicTo(StringStream* stream) {
- stream->Add("%s", Mnemonic());
- if (HasSideEffects()) stream->Add("*");
- stream->Add(" ");
+ stream->Add("%s ", Mnemonic());
}
@@ -791,6 +789,13 @@ void HChange::PrintDataTo(StringStream* stream) {
}
+void HJSArrayLength::PrintDataTo(StringStream* stream) {
+ value()->PrintNameTo(stream);
+ stream->Add(" ");
+ typecheck()->PrintNameTo(stream);
+}
+
+
HValue* HCheckInstanceType::Canonicalize() {
if (check_ == IS_STRING &&
!value()->type().IsUninitialized() &&
@@ -1020,11 +1025,14 @@ void HPhi::PrintTo(StringStream* stream) {
value->PrintNameTo(stream);
stream->Add(" ");
}
- stream->Add(" uses%d_%di_%dd_%dt]",
+ stream->Add(" uses%d_%di_%dd_%dt",
UseCount(),
int32_non_phi_uses() + int32_indirect_uses(),
double_non_phi_uses() + double_indirect_uses(),
tagged_non_phi_uses() + tagged_indirect_uses());
+ stream->Add("%s%s]",
+ is_live() ? "_live" : "",
+ IsConvertibleToInteger() ? "" : "_ncti");
}
diff --git a/deps/v8/src/hydrogen-instructions.h b/deps/v8/src/hydrogen-instructions.h
index 76007d764e..3ccf302e40 100644
--- a/deps/v8/src/hydrogen-instructions.h
+++ b/deps/v8/src/hydrogen-instructions.h
@@ -513,19 +513,6 @@ class HValue: public ZoneObject {
static const int kChangesToDependsFlagsLeftShift = 1;
- static int ChangesFlagsMask() {
- int result = 0;
- // Create changes mask.
-#define DECLARE_DO(type) result |= (1 << kChanges##type);
- GVN_FLAG_LIST(DECLARE_DO)
-#undef DECLARE_DO
- return result;
- }
-
- static int DependsFlagsMask() {
- return ConvertChangesToDependsFlags(ChangesFlagsMask());
- }
-
static int ConvertChangesToDependsFlags(int flags) {
return flags << kChangesToDependsFlagsLeftShift;
}
@@ -629,6 +616,8 @@ class HValue: public ZoneObject {
void ClearAllSideEffects() { flags_ &= ~AllSideEffects(); }
bool HasSideEffects() const { return (flags_ & AllSideEffects()) != 0; }
+ int ChangesFlags() const { return flags_ & ChangesFlagsMask(); }
+
Range* range() const { return range_; }
bool HasRange() const { return range_ != NULL; }
void AddNewRange(Range* r);
@@ -693,6 +682,15 @@ class HValue: public ZoneObject {
}
private:
+ static int ChangesFlagsMask() {
+ int result = 0;
+ // Create changes mask.
+#define ADD_FLAG(type) result |= (1 << kChanges##type);
+ GVN_FLAG_LIST(ADD_FLAG)
+#undef ADD_FLAG
+ return result;
+ }
+
// A flag mask to mark an instruction as having arbitrary side effects.
static int AllSideEffects() {
return ChangesFlagsMask() & ~(1 << kChangesOsrEntries);
@@ -1696,7 +1694,10 @@ class HJSArrayLength: public HTemplateInstruction<2> {
return Representation::Tagged();
}
+ virtual void PrintDataTo(StringStream* stream);
+
HValue* value() { return OperandAt(0); }
+ HValue* typecheck() { return OperandAt(1); }
DECLARE_CONCRETE_INSTRUCTION(JSArrayLength)
diff --git a/deps/v8/src/hydrogen.cc b/deps/v8/src/hydrogen.cc
index dd3a591d60..01046bf9bf 100644
--- a/deps/v8/src/hydrogen.cc
+++ b/deps/v8/src/hydrogen.cc
@@ -1382,7 +1382,7 @@ void HGlobalValueNumberer::ComputeBlockSideEffects() {
int id = block->block_id();
int side_effects = 0;
while (instr != NULL) {
- side_effects |= (instr->flags() & HValue::ChangesFlagsMask());
+ side_effects |= instr->ChangesFlags();
instr = instr->next();
}
block_side_effects_[id] |= side_effects;
@@ -1499,7 +1499,7 @@ void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
HInstruction* instr = block->first();
while (instr != NULL) {
HInstruction* next = instr->next();
- int flags = (instr->flags() & HValue::ChangesFlagsMask());
+ int flags = instr->ChangesFlags();
if (flags != 0) {
ASSERT(!instr->CheckFlag(HValue::kUseGVN));
// Clear all instructions in the map that are affected by side effects.
@@ -2273,10 +2273,6 @@ HGraph* HGraphBuilder::CreateGraph() {
return NULL;
}
SetupScope(scope);
- VisitDeclarations(scope->declarations());
- HValue* context = environment()->LookupContext();
- AddInstruction(
- new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry));
// Add an edge to the body entry. This is warty: the graph's start
// environment will be used by the Lithium translation as the initial
@@ -2298,6 +2294,19 @@ HGraph* HGraphBuilder::CreateGraph() {
current_block()->Goto(body_entry);
body_entry->SetJoinId(AstNode::kFunctionEntryId);
set_current_block(body_entry);
+
+ // Handle implicit declaration of the function name in named function
+ // expressions before other declarations.
+ if (scope->is_function_scope() && scope->function() != NULL) {
+ HandleDeclaration(scope->function(), Variable::CONST, NULL);
+ }
+ VisitDeclarations(scope->declarations());
+ AddSimulate(AstNode::kDeclarationsId);
+
+ HValue* context = environment()->LookupContext();
+ AddInstruction(
+ new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry));
+
VisitStatements(info()->function()->body());
if (HasStackOverflow()) return NULL;
@@ -3119,54 +3128,63 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- Variable* variable = expr->AsVariable();
- if (variable == NULL) {
- return Bailout("reference to rewritten variable");
- } else if (variable->IsStackAllocated()) {
- HValue* value = environment()->Lookup(variable);
- if (variable->mode() == Variable::CONST &&
- value == graph()->GetConstantHole()) {
- return Bailout("reference to uninitialized const variable");
- }
- return ast_context()->ReturnValue(value);
- } else if (variable->IsContextSlot()) {
- if (variable->mode() == Variable::CONST) {
- return Bailout("reference to const context slot");
- }
- HValue* context = BuildContextChainWalk(variable);
- int index = variable->AsSlot()->index();
- HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, index);
- return ast_context()->ReturnInstruction(instr, expr->id());
- } else if (variable->is_global()) {
- LookupResult lookup;
- GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false);
+ Variable* variable = expr->var();
+ if (variable->mode() == Variable::LET) {
+ return Bailout("reference to let variable");
+ }
+ switch (variable->location()) {
+ case Variable::UNALLOCATED: {
+ LookupResult lookup;
+ GlobalPropertyAccess type =
+ LookupGlobalProperty(variable, &lookup, false);
+
+ if (type == kUseCell &&
+ info()->global_object()->IsAccessCheckNeeded()) {
+ type = kUseGeneric;
+ }
- if (type == kUseCell &&
- info()->global_object()->IsAccessCheckNeeded()) {
- type = kUseGeneric;
+ if (type == kUseCell) {
+ Handle<GlobalObject> global(info()->global_object());
+ Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
+ bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
+ HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole);
+ return ast_context()->ReturnInstruction(instr, expr->id());
+ } else {
+ HValue* context = environment()->LookupContext();
+ HGlobalObject* global_object = new(zone()) HGlobalObject(context);
+ AddInstruction(global_object);
+ HLoadGlobalGeneric* instr =
+ new(zone()) HLoadGlobalGeneric(context,
+ global_object,
+ variable->name(),
+ ast_context()->is_for_typeof());
+ instr->set_position(expr->position());
+ return ast_context()->ReturnInstruction(instr, expr->id());
+ }
}
- if (type == kUseCell) {
- Handle<GlobalObject> global(info()->global_object());
- Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
- bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
- HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole);
- return ast_context()->ReturnInstruction(instr, expr->id());
- } else {
- HValue* context = environment()->LookupContext();
- HGlobalObject* global_object = new(zone()) HGlobalObject(context);
- AddInstruction(global_object);
- HLoadGlobalGeneric* instr =
- new(zone()) HLoadGlobalGeneric(context,
- global_object,
- variable->name(),
- ast_context()->is_for_typeof());
- instr->set_position(expr->position());
- ASSERT(instr->HasSideEffects());
+ case Variable::PARAMETER:
+ case Variable::LOCAL: {
+ HValue* value = environment()->Lookup(variable);
+ if (variable->mode() == Variable::CONST &&
+ value == graph()->GetConstantHole()) {
+ return Bailout("reference to uninitialized const variable");
+ }
+ return ast_context()->ReturnValue(value);
+ }
+
+ case Variable::CONTEXT: {
+ if (variable->mode() == Variable::CONST) {
+ return Bailout("reference to const context slot");
+ }
+ HValue* context = BuildContextChainWalk(variable);
+ HLoadContextSlot* instr =
+ new(zone()) HLoadContextSlot(context, variable->index());
return ast_context()->ReturnInstruction(instr, expr->id());
}
- } else {
- return Bailout("reference to a variable which requires dynamic lookup");
+
+ case Variable::LOOKUP:
+ return Bailout("reference to a variable which requires dynamic lookup");
}
}
@@ -3578,51 +3596,61 @@ void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
Expression* target = expr->target();
VariableProxy* proxy = target->AsVariableProxy();
- Variable* var = proxy->AsVariable();
Property* prop = target->AsProperty();
- ASSERT(var == NULL || prop == NULL);
+ ASSERT(proxy == NULL || prop == NULL);
// We have a second position recorded in the FullCodeGenerator to have
// type feedback for the binary operation.
BinaryOperation* operation = expr->binary_operation();
- if (var != NULL) {
- if (var->mode() == Variable::CONST) {
- return Bailout("unsupported const compound assignment");
+ if (proxy != NULL) {
+ Variable* var = proxy->var();
+ if (var->mode() == Variable::CONST || var->mode() == Variable::LET) {
+ return Bailout("unsupported let or const compound assignment");
}
CHECK_ALIVE(VisitForValue(operation));
- if (var->is_global()) {
- HandleGlobalVariableAssignment(var,
- Top(),
- expr->position(),
- expr->AssignmentId());
- } else if (var->IsStackAllocated()) {
- Bind(var, Top());
- } else if (var->IsContextSlot()) {
- // Bail out if we try to mutate a parameter value in a function using
- // the arguments object. We do not (yet) correctly handle the
- // arguments property of the function.
- if (info()->scope()->arguments() != NULL) {
- // Parameters will rewrite to context slots. We have no direct way
- // to detect that the variable is a parameter.
- int count = info()->scope()->num_parameters();
- for (int i = 0; i < count; ++i) {
- if (var == info()->scope()->parameter(i)) {
- Bailout("assignment to parameter, function uses arguments object");
+ switch (var->location()) {
+ case Variable::UNALLOCATED:
+ HandleGlobalVariableAssignment(var,
+ Top(),
+ expr->position(),
+ expr->AssignmentId());
+ break;
+
+ case Variable::PARAMETER:
+ case Variable::LOCAL:
+ Bind(var, Top());
+ break;
+
+ case Variable::CONTEXT: {
+ // Bail out if we try to mutate a parameter value in a function
+ // using the arguments object. We do not (yet) correctly handle the
+ // arguments property of the function.
+ if (info()->scope()->arguments() != NULL) {
+ // Parameters will be allocated to context slots. We have no
+ // direct way to detect that the variable is a parameter so we do
+ // a linear search of the parameter variables.
+ int count = info()->scope()->num_parameters();
+ for (int i = 0; i < count; ++i) {
+ if (var == info()->scope()->parameter(i)) {
+ Bailout(
+ "assignment to parameter, function uses arguments object");
+ }
}
}
+
+ HValue* context = BuildContextChainWalk(var);
+ HStoreContextSlot* instr =
+ new(zone()) HStoreContextSlot(context, var->index(), Top());
+ AddInstruction(instr);
+ if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
+ break;
}
- HValue* context = BuildContextChainWalk(var);
- int index = var->AsSlot()->index();
- HStoreContextSlot* instr =
- new(zone()) HStoreContextSlot(context, index, Top());
- AddInstruction(instr);
- if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
- } else {
- return Bailout("compound assignment to lookup slot");
+ case Variable::LOOKUP:
+ return Bailout("compound assignment to lookup slot");
}
return ast_context()->ReturnValue(Pop());
@@ -3710,16 +3738,18 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) {
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
VariableProxy* proxy = expr->target()->AsVariableProxy();
- Variable* var = proxy->AsVariable();
Property* prop = expr->target()->AsProperty();
- ASSERT(var == NULL || prop == NULL);
+ ASSERT(proxy == NULL || prop == NULL);
if (expr->is_compound()) {
HandleCompoundAssignment(expr);
return;
}
- if (var != NULL) {
+ if (prop != NULL) {
+ HandlePropertyAssignment(expr);
+ } else if (proxy != NULL) {
+ Variable* var = proxy->var();
if (var->mode() == Variable::CONST) {
if (expr->op() != Token::INIT_CONST) {
return Bailout("non-initializer assignment to const");
@@ -3731,59 +3761,61 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) {
// variables (e.g. initialization inside a loop).
HValue* old_value = environment()->Lookup(var);
AddInstruction(new HUseConst(old_value));
+ } else if (var->mode() == Variable::LET) {
+ return Bailout("unsupported assignment to let");
}
if (proxy->IsArguments()) return Bailout("assignment to arguments");
// Handle the assignment.
- if (var->IsStackAllocated()) {
- // We do not allow the arguments object to occur in a context where it
- // may escape, but assignments to stack-allocated locals are
- // permitted.
- CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
- HValue* value = Pop();
- Bind(var, value);
- return ast_context()->ReturnValue(value);
+ switch (var->location()) {
+ case Variable::UNALLOCATED:
+ CHECK_ALIVE(VisitForValue(expr->value()));
+ HandleGlobalVariableAssignment(var,
+ Top(),
+ expr->position(),
+ expr->AssignmentId());
+ return ast_context()->ReturnValue(Pop());
+
+ case Variable::PARAMETER:
+ case Variable::LOCAL: {
+ // We do not allow the arguments object to occur in a context where it
+ // may escape, but assignments to stack-allocated locals are
+ // permitted.
+ CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
+ HValue* value = Pop();
+ Bind(var, value);
+ return ast_context()->ReturnValue(value);
+ }
- } else if (var->IsContextSlot()) {
- ASSERT(var->mode() != Variable::CONST);
- // Bail out if we try to mutate a parameter value in a function using
- // the arguments object. We do not (yet) correctly handle the
- // arguments property of the function.
- if (info()->scope()->arguments() != NULL) {
- // Parameters will rewrite to context slots. We have no direct way
- // to detect that the variable is a parameter.
- int count = info()->scope()->num_parameters();
- for (int i = 0; i < count; ++i) {
- if (var == info()->scope()->parameter(i)) {
- Bailout("assignment to parameter, function uses arguments object");
+ case Variable::CONTEXT: {
+ ASSERT(var->mode() != Variable::CONST);
+ // Bail out if we try to mutate a parameter value in a function using
+ // the arguments object. We do not (yet) correctly handle the
+ // arguments property of the function.
+ if (info()->scope()->arguments() != NULL) {
+ // Parameters will rewrite to context slots. We have no direct way
+ // to detect that the variable is a parameter.
+ int count = info()->scope()->num_parameters();
+ for (int i = 0; i < count; ++i) {
+ if (var == info()->scope()->parameter(i)) {
+ return Bailout("assignment to parameter in arguments object");
+ }
}
}
- }
-
- CHECK_ALIVE(VisitForValue(expr->value()));
- HValue* context = BuildContextChainWalk(var);
- int index = var->AsSlot()->index();
- HStoreContextSlot* instr =
- new(zone()) HStoreContextSlot(context, index, Top());
- AddInstruction(instr);
- if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
- return ast_context()->ReturnValue(Pop());
- } else if (var->is_global()) {
- CHECK_ALIVE(VisitForValue(expr->value()));
- HandleGlobalVariableAssignment(var,
- Top(),
- expr->position(),
- expr->AssignmentId());
- return ast_context()->ReturnValue(Pop());
+ CHECK_ALIVE(VisitForValue(expr->value()));
+ HValue* context = BuildContextChainWalk(var);
+ HStoreContextSlot* instr =
+ new(zone()) HStoreContextSlot(context, var->index(), Top());
+ AddInstruction(instr);
+ if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
+ return ast_context()->ReturnValue(Pop());
+ }
- } else {
- return Bailout("assignment to LOOKUP or const CONTEXT variable");
+ case Variable::LOOKUP:
+ return Bailout("assignment to LOOKUP variable");
}
-
- } else if (prop != NULL) {
- HandlePropertyAssignment(expr);
} else {
return Bailout("invalid left-hand side in assignment");
}
@@ -4795,13 +4827,15 @@ bool HGraphBuilder::TryCallApply(Call* expr) {
// Found pattern f.apply(receiver, arguments).
VisitForValue(prop->obj());
if (HasStackOverflow() || current_block() == NULL) return true;
- HValue* function = Pop();
+ HValue* function = Top();
+ AddCheckConstantFunction(expr, function, function_map, true);
+ Drop(1);
+
VisitForValue(args->at(0));
if (HasStackOverflow() || current_block() == NULL) return true;
HValue* receiver = Pop();
HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements));
- AddCheckConstantFunction(expr, function, function_map, true);
HInstruction* result =
new(zone()) HApplyArguments(function, receiver, length, elements);
result->set_position(expr->position());
@@ -4893,10 +4927,12 @@ void HGraphBuilder::VisitCall(Call* expr) {
}
} else {
- Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
- bool global_call = (var != NULL) && var->is_global() && !var->is_this();
+ VariableProxy* proxy = expr->expression()->AsVariableProxy();
+ // FIXME.
+ bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
if (global_call) {
+ Variable* var = proxy->var();
bool known_global_function = false;
// If there is a global property cell for the name at compile time and
// access check is not enabled we assume that the function will not change
@@ -5060,20 +5096,8 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
void HGraphBuilder::VisitDelete(UnaryOperation* expr) {
Property* prop = expr->expression()->AsProperty();
- Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
- if (prop == NULL && var == NULL) {
- // Result of deleting non-property, non-variable reference is true.
- // Evaluate the subexpression for side effects.
- CHECK_ALIVE(VisitForEffect(expr->expression()));
- return ast_context()->ReturnValue(graph()->GetConstantTrue());
- } else if (var != NULL &&
- !var->is_global() &&
- var->AsSlot() != NULL &&
- var->AsSlot()->type() != Slot::LOOKUP) {
- // Result of deleting non-global, non-dynamic variables is false.
- // The subexpression does not have side effects.
- return ast_context()->ReturnValue(graph()->GetConstantFalse());
- } else if (prop != NULL) {
+ VariableProxy* proxy = expr->expression()->AsVariableProxy();
+ if (prop != NULL) {
CHECK_ALIVE(VisitForValue(prop->obj()));
CHECK_ALIVE(VisitForValue(prop->key()));
HValue* key = Pop();
@@ -5081,10 +5105,26 @@ void HGraphBuilder::VisitDelete(UnaryOperation* expr) {
HValue* context = environment()->LookupContext();
HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key);
return ast_context()->ReturnInstruction(instr, expr->id());
- } else if (var->is_global()) {
- Bailout("delete with global variable");
+ } else if (proxy != NULL) {
+ Variable* var = proxy->var();
+ if (var->IsUnallocated()) {
+ Bailout("delete with global variable");
+ } else if (var->IsStackAllocated() || var->IsContextSlot()) {
+ // Result of deleting non-global variables is false. 'this' is not
+ // really a variable, though we implement it as one. The
+ // subexpression does not have side effects.
+ HValue* value = var->is_this()
+ ? graph()->GetConstantTrue()
+ : graph()->GetConstantFalse();
+ return ast_context()->ReturnValue(value);
+ } else {
+ Bailout("delete with non-global variable");
+ }
} else {
- Bailout("delete with non-global variable");
+ // Result of deleting non-property, non-variable reference is true.
+ // Evaluate the subexpression for side effects.
+ CHECK_ALIVE(VisitForEffect(expr->expression()));
+ return ast_context()->ReturnValue(graph()->GetConstantTrue());
}
}
@@ -5231,9 +5271,8 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
ASSERT(current_block()->HasPredecessor());
Expression* target = expr->expression();
VariableProxy* proxy = target->AsVariableProxy();
- Variable* var = proxy->AsVariable();
Property* prop = target->AsProperty();
- if (var == NULL && prop == NULL) {
+ if (proxy == NULL && prop == NULL) {
return Bailout("invalid lhs in count operation");
}
@@ -5245,7 +5284,8 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
HValue* input = NULL; // ToNumber(original_input).
HValue* after = NULL; // The result after incrementing or decrementing.
- if (var != NULL) {
+ if (proxy != NULL) {
+ Variable* var = proxy->var();
if (var->mode() == Variable::CONST) {
return Bailout("unsupported count operation with const");
}
@@ -5257,36 +5297,45 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
input = returns_original_input ? Top() : Pop();
Push(after);
- if (var->is_global()) {
- HandleGlobalVariableAssignment(var,
- after,
- expr->position(),
- expr->AssignmentId());
- } else if (var->IsStackAllocated()) {
- Bind(var, after);
- } else if (var->IsContextSlot()) {
- // Bail out if we try to mutate a parameter value in a function using
- // the arguments object. We do not (yet) correctly handle the
- // arguments property of the function.
- if (info()->scope()->arguments() != NULL) {
- // Parameters will rewrite to context slots. We have no direct way
- // to detect that the variable is a parameter.
- int count = info()->scope()->num_parameters();
- for (int i = 0; i < count; ++i) {
- if (var == info()->scope()->parameter(i)) {
- Bailout("assignment to parameter, function uses arguments object");
+ switch (var->location()) {
+ case Variable::UNALLOCATED:
+ HandleGlobalVariableAssignment(var,
+ after,
+ expr->position(),
+ expr->AssignmentId());
+ break;
+
+ case Variable::PARAMETER:
+ case Variable::LOCAL:
+ Bind(var, after);
+ break;
+
+ case Variable::CONTEXT: {
+ // Bail out if we try to mutate a parameter value in a function
+ // using the arguments object. We do not (yet) correctly handle the
+ // arguments property of the function.
+ if (info()->scope()->arguments() != NULL) {
+ // Parameters will rewrite to context slots. We have no direct
+ // way to detect that the variable is a parameter so we use a
+ // linear search of the parameter list.
+ int count = info()->scope()->num_parameters();
+ for (int i = 0; i < count; ++i) {
+ if (var == info()->scope()->parameter(i)) {
+ return Bailout("assignment to parameter in arguments object");
+ }
}
}
+
+ HValue* context = BuildContextChainWalk(var);
+ HStoreContextSlot* instr =
+ new(zone()) HStoreContextSlot(context, var->index(), after);
+ AddInstruction(instr);
+ if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
+ break;
}
- HValue* context = BuildContextChainWalk(var);
- int index = var->AsSlot()->index();
- HStoreContextSlot* instr =
- new(zone()) HStoreContextSlot(context, index, after);
- AddInstruction(instr);
- if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
- } else {
- return Bailout("lookup variable in count operation");
+ case Variable::LOOKUP:
+ return Bailout("lookup variable in count operation");
}
} else {
@@ -5698,12 +5747,12 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
// residing in new space. If it is we assume that the function will stay the
// same.
Handle<JSFunction> target = Handle<JSFunction>::null();
- Variable* var = expr->right()->AsVariableProxy()->AsVariable();
- bool global_function = (var != NULL) && var->is_global() && !var->is_this();
+ VariableProxy* proxy = expr->right()->AsVariableProxy();
+ bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated();
if (global_function &&
info()->has_global_object() &&
!info()->global_object()->IsAccessCheckNeeded()) {
- Handle<String> name = var->name();
+ Handle<String> name = proxy->name();
Handle<GlobalObject> global(info()->global_object());
LookupResult lookup;
global->Lookup(*name, &lookup);
@@ -5802,15 +5851,42 @@ void HGraphBuilder::VisitThisFunction(ThisFunction* expr) {
void HGraphBuilder::VisitDeclaration(Declaration* decl) {
- // We support only declarations that do not require code generation.
- Variable* var = decl->proxy()->var();
- if (!var->IsStackAllocated() || decl->fun() != NULL) {
- return Bailout("unsupported declaration");
- }
-
- if (decl->mode() == Variable::CONST) {
- ASSERT(var->IsStackAllocated());
- environment()->Bind(var, graph()->GetConstantHole());
+ HandleDeclaration(decl->proxy(), decl->mode(), decl->fun());
+}
+
+
+void HGraphBuilder::HandleDeclaration(VariableProxy* proxy,
+ Variable::Mode mode,
+ FunctionLiteral* function) {
+ if (mode == Variable::LET) return Bailout("unsupported let declaration");
+ Variable* var = proxy->var();
+ switch (var->location()) {
+ case Variable::UNALLOCATED:
+ return Bailout("unsupported global declaration");
+ case Variable::PARAMETER:
+ case Variable::LOCAL:
+ case Variable::CONTEXT:
+ if (mode == Variable::CONST || function != NULL) {
+ HValue* value = NULL;
+ if (mode == Variable::CONST) {
+ value = graph()->GetConstantHole();
+ } else {
+ VisitForValue(function);
+ value = Pop();
+ }
+ if (var->IsContextSlot()) {
+ HValue* context = environment()->LookupContext();
+ HStoreContextSlot* store =
+ new HStoreContextSlot(context, var->index(), value);
+ AddInstruction(store);
+ if (store->HasSideEffects()) AddSimulate(proxy->id());
+ } else {
+ environment()->Bind(var, value);
+ }
+ }
+ break;
+ case Variable::LOOKUP:
+ return Bailout("unsupported lookup slot in declaration");
}
}
diff --git a/deps/v8/src/hydrogen.h b/deps/v8/src/hydrogen.h
index c18ba58153..614991f7c2 100644
--- a/deps/v8/src/hydrogen.h
+++ b/deps/v8/src/hydrogen.h
@@ -455,12 +455,11 @@ class HEnvironment: public ZoneObject {
// by 1 (receiver is parameter index -1 but environment index 0).
// Stack-allocated local indices are shifted by the number of parameters.
int IndexFor(Variable* variable) const {
- Slot* slot = variable->AsSlot();
- ASSERT(slot != NULL && slot->IsStackAllocated());
- int shift = (slot->type() == Slot::PARAMETER)
+ ASSERT(variable->IsStackAllocated());
+ int shift = variable->IsParameter()
? 1
: parameter_count_ + specials_count_;
- return slot->index() + shift;
+ return variable->index() + shift;
}
Handle<JSFunction> closure_;
@@ -779,6 +778,10 @@ class HGraphBuilder: public AstVisitor {
INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
#undef INLINE_FUNCTION_GENERATOR_DECLARATION
+ void HandleDeclaration(VariableProxy* proxy,
+ Variable::Mode mode,
+ FunctionLiteral* function);
+
void VisitDelete(UnaryOperation* expr);
void VisitVoid(UnaryOperation* expr);
void VisitTypeof(UnaryOperation* expr);
@@ -851,7 +854,6 @@ class HGraphBuilder: public AstVisitor {
TypeInfo info,
HValue* value,
Representation rep);
- void AssumeRepresentation(HValue* value, Representation rep);
static Representation ToRepresentation(TypeInfo info);
void SetupScope(Scope* scope);
diff --git a/deps/v8/src/ia32/builtins-ia32.cc b/deps/v8/src/ia32/builtins-ia32.cc
index f8a85de98c..845a073c40 100644
--- a/deps/v8/src/ia32/builtins-ia32.cc
+++ b/deps/v8/src/ia32/builtins-ia32.cc
@@ -373,7 +373,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ LeaveConstructFrame();
// Remove caller arguments from the stack and return.
- ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
+ STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
__ pop(ecx);
__ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver
__ push(ecx);
@@ -923,7 +923,7 @@ static void AllocateEmptyJSArray(MacroAssembler* masm,
// Fill the FixedArray with the hole value. Inline the code if short.
// Reconsider loop unfolding if kPreallocatedArrayElements gets changed.
static const int kLoopUnfoldLimit = 4;
- ASSERT(kPreallocatedArrayElements <= kLoopUnfoldLimit);
+ STATIC_ASSERT(kPreallocatedArrayElements <= kLoopUnfoldLimit);
if (initial_capacity <= kLoopUnfoldLimit) {
// Use a scratch register here to have only one reloc info when unfolding
// the loop.
@@ -975,7 +975,7 @@ static void AllocateJSArray(MacroAssembler* masm,
// Allocate the JSArray object together with space for a FixedArray with the
// requested elements.
- ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
+ STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
__ AllocateInNewSpace(JSArray::kSize + FixedArray::kHeaderSize,
times_half_pointer_size, // array_size is a smi.
array_size,
@@ -1100,7 +1100,7 @@ static void ArrayNativeCode(MacroAssembler* masm,
__ bind(&argc_one_or_more);
__ cmp(eax, 1);
__ j(not_equal, &argc_two_or_more);
- ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTag == 0);
__ mov(ecx, Operand(esp, (push_count + 1) * kPointerSize));
__ test(ecx, Operand(ecx));
__ j(not_zero, &not_empty_array);
@@ -1155,7 +1155,7 @@ static void ArrayNativeCode(MacroAssembler* masm,
// Handle construction of an array from a list of arguments.
__ bind(&argc_two_or_more);
- ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTag == 0);
__ SmiTag(eax); // Convet argc to a smi.
// eax: array_size (smi)
// edi: constructor
@@ -1437,7 +1437,7 @@ static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
// Preserve the number of arguments on the stack. Must preserve eax,
// ebx and ecx because these registers are used when copying the
// arguments and the receiver.
- ASSERT(kSmiTagSize == 1);
+ STATIC_ASSERT(kSmiTagSize == 1);
__ lea(edi, Operand(eax, eax, times_1, kSmiTag));
__ push(edi);
}
@@ -1451,7 +1451,7 @@ static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
__ leave();
// Remove caller arguments from the stack.
- ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
+ STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
__ pop(ecx);
__ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver
__ push(ecx);
diff --git a/deps/v8/src/ia32/code-stubs-ia32.cc b/deps/v8/src/ia32/code-stubs-ia32.cc
index d76e4bf1f4..f3eb09fa51 100644
--- a/deps/v8/src/ia32/code-stubs-ia32.cc
+++ b/deps/v8/src/ia32/code-stubs-ia32.cc
@@ -3396,8 +3396,8 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// a sequential string or an external string.
// In the case of a sliced string its offset has to be taken into account.
Label cons_string, check_encoding;
- STATIC_ASSERT((kConsStringTag < kExternalStringTag));
- STATIC_ASSERT((kSlicedStringTag > kExternalStringTag));
+ STATIC_ASSERT(kConsStringTag < kExternalStringTag);
+ STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
__ cmp(Operand(ebx), Immediate(kExternalStringTag));
__ j(less, &cons_string);
__ j(equal, &runtime);
@@ -4872,8 +4872,8 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
// Handle non-flat strings.
__ and_(result_, kStringRepresentationMask);
- STATIC_ASSERT((kConsStringTag < kExternalStringTag));
- STATIC_ASSERT((kSlicedStringTag > kExternalStringTag));
+ STATIC_ASSERT(kConsStringTag < kExternalStringTag);
+ STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
__ cmp(result_, kExternalStringTag);
__ j(greater, &sliced_string, Label::kNear);
__ j(equal, &call_runtime_);
@@ -4907,7 +4907,8 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
// Check for 1-byte or 2-byte string.
__ bind(&flat_string);
- STATIC_ASSERT(kAsciiStringTag != 0);
+ STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
+ STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
__ test(result_, Immediate(kStringEncodingMask));
__ j(not_zero, &ascii_string, Label::kNear);
@@ -5178,8 +5179,9 @@ void StringAddStub::Generate(MacroAssembler* masm) {
__ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
__ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset));
__ and_(ecx, Operand(edi));
- STATIC_ASSERT(kStringEncodingMask == kAsciiStringTag);
- __ test(ecx, Immediate(kAsciiStringTag));
+ STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
+ STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
+ __ test(ecx, Immediate(kStringEncodingMask));
__ j(zero, &non_ascii);
__ bind(&ascii_data);
// Allocate an acsii cons string.
@@ -5210,7 +5212,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
__ cmp(edi, kAsciiStringTag | kAsciiDataHintTag);
__ j(equal, &ascii_data);
// Allocate a two byte cons string.
- __ AllocateConsString(ecx, edi, no_reg, &string_add_runtime);
+ __ AllocateTwoByteConsString(ecx, edi, no_reg, &string_add_runtime);
__ jmp(&allocated);
// Handle creating a flat result. First check that both strings are not
@@ -5236,12 +5238,13 @@ void StringAddStub::Generate(MacroAssembler* masm) {
// ebx: length of resulting flat string as a smi
// edx: second string
Label non_ascii_string_add_flat_result;
- STATIC_ASSERT(kStringEncodingMask == kAsciiStringTag);
+ STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
+ STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
__ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
- __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag);
+ __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kStringEncodingMask);
__ j(zero, &non_ascii_string_add_flat_result);
__ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
- __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag);
+ __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kStringEncodingMask);
__ j(zero, &string_add_runtime);
// Both strings are ascii strings. As they are short they are both flat.
@@ -5281,7 +5284,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
// edx: second string
__ bind(&non_ascii_string_add_flat_result);
__ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
- __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kAsciiStringTag);
+ __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kStringEncodingMask);
__ j(not_zero, &string_add_runtime);
// Both strings are two byte strings. As they are short they are both
// flat.
@@ -5642,9 +5645,6 @@ void StringHelper::GenerateHashGetHash(MacroAssembler* masm,
void SubStringStub::Generate(MacroAssembler* masm) {
Label runtime;
- if (FLAG_string_slices) {
- __ jmp(&runtime);
- }
// Stack frame on entry.
// esp[0]: return address
// esp[4]: to
@@ -5706,7 +5706,84 @@ void SubStringStub::Generate(MacroAssembler* masm) {
__ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
__ Set(ecx, Immediate(2));
- __ bind(&result_longer_than_two);
+ if (FLAG_string_slices) {
+ Label copy_routine;
+ // If coming from the make_two_character_string path, the string
+ // is too short to be sliced anyways.
+ STATIC_ASSERT(2 < SlicedString::kMinLength);
+ __ jmp(&copy_routine);
+ __ bind(&result_longer_than_two);
+
+ // eax: string
+ // ebx: instance type
+ // ecx: sub string length
+ // edx: from index (smi)
+ Label allocate_slice, sliced_string, seq_string;
+ __ cmp(ecx, SlicedString::kMinLength);
+ // Short slice. Copy instead of slicing.
+ __ j(less, &copy_routine);
+ STATIC_ASSERT(kSeqStringTag == 0);
+ __ test(ebx, Immediate(kStringRepresentationMask));
+ __ j(zero, &seq_string, Label::kNear);
+ STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
+ STATIC_ASSERT(kIsIndirectStringMask != 0);
+ __ test(ebx, Immediate(kIsIndirectStringMask));
+ // External string. Jump to runtime.
+ __ j(zero, &runtime);
+
+ Factory* factory = masm->isolate()->factory();
+ __ test(ebx, Immediate(kSlicedNotConsMask));
+ __ j(not_zero, &sliced_string, Label::kNear);
+ // Cons string. Check whether it is flat, then fetch first part.
+ __ cmp(FieldOperand(eax, ConsString::kSecondOffset),
+ factory->empty_string());
+ __ j(not_equal, &runtime);
+ __ mov(edi, FieldOperand(eax, ConsString::kFirstOffset));
+ __ jmp(&allocate_slice, Label::kNear);
+
+ __ bind(&sliced_string);
+ // Sliced string. Fetch parent and correct start index by offset.
+ __ add(edx, FieldOperand(eax, SlicedString::kOffsetOffset));
+ __ mov(edi, FieldOperand(eax, SlicedString::kParentOffset));
+ __ jmp(&allocate_slice, Label::kNear);
+
+ __ bind(&seq_string);
+ // Sequential string. Just move string to the right register.
+ __ mov(edi, eax);
+
+ __ bind(&allocate_slice);
+ // edi: underlying subject string
+ // ebx: instance type of original subject string
+ // edx: offset
+ // ecx: length
+ // Allocate new sliced string. At this point we do not reload the instance
+ // type including the string encoding because we simply rely on the info
+ // provided by the original string. It does not matter if the original
+ // string's encoding is wrong because we always have to recheck encoding of
+ // the newly created string's parent anyways due to externalized strings.
+ Label two_byte_slice, set_slice_header;
+ STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
+ STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
+ __ test(ebx, Immediate(kStringEncodingMask));
+ __ j(zero, &two_byte_slice, Label::kNear);
+ __ AllocateAsciiSlicedString(eax, ebx, no_reg, &runtime);
+ __ jmp(&set_slice_header, Label::kNear);
+ __ bind(&two_byte_slice);
+ __ AllocateTwoByteSlicedString(eax, ebx, no_reg, &runtime);
+ __ bind(&set_slice_header);
+ __ mov(FieldOperand(eax, SlicedString::kOffsetOffset), edx);
+ __ SmiTag(ecx);
+ __ mov(FieldOperand(eax, SlicedString::kLengthOffset), ecx);
+ __ mov(FieldOperand(eax, SlicedString::kParentOffset), edi);
+ __ mov(FieldOperand(eax, SlicedString::kHashFieldOffset),
+ Immediate(String::kEmptyHashField));
+ __ jmp(&return_eax);
+
+ __ bind(&copy_routine);
+ } else {
+ __ bind(&result_longer_than_two);
+ }
+
// eax: string
// ebx: instance type
// ecx: result string length
diff --git a/deps/v8/src/ia32/full-codegen-ia32.cc b/deps/v8/src/ia32/full-codegen-ia32.cc
index 799ba73a26..59f7b9c7b3 100644
--- a/deps/v8/src/ia32/full-codegen-ia32.cc
+++ b/deps/v8/src/ia32/full-codegen-ia32.cc
@@ -41,7 +41,6 @@
namespace v8 {
namespace internal {
-
#define __ ACCESS_MASM(masm_)
@@ -192,14 +191,14 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
// Copy parameters into context if necessary.
int num_parameters = info->scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) {
- Slot* slot = scope()->parameter(i)->AsSlot();
- if (slot != NULL && slot->type() == Slot::CONTEXT) {
+ Variable* var = scope()->parameter(i);
+ if (var->IsContextSlot()) {
int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(num_parameters - 1 - i) * kPointerSize;
// Load parameter from stack.
__ mov(eax, Operand(ebp, parameter_offset));
// Store it in the context.
- int context_offset = Context::SlotOffset(slot->index());
+ int context_offset = Context::SlotOffset(var->index());
__ mov(Operand(esi, context_offset), eax);
// Update the write barrier. This clobbers all involved
// registers, so we have use a third register to avoid
@@ -241,7 +240,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
ArgumentsAccessStub stub(type);
__ CallStub(&stub);
- Move(arguments->AsSlot(), eax, ebx, edx);
+ SetVar(arguments, eax, ebx, edx);
}
if (FLAG_trace) {
@@ -255,17 +254,19 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
scope()->VisitIllegalRedeclaration(this);
} else {
+ PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
{ Comment cmnt(masm_, "[ Declarations");
// For named function expressions, declare the function name as a
// constant.
if (scope()->is_function_scope() && scope()->function() != NULL) {
- EmitDeclaration(scope()->function(), Variable::CONST, NULL);
+ int ignored = 0;
+ EmitDeclaration(scope()->function(), Variable::CONST, NULL, &ignored);
}
VisitDeclarations(scope()->declarations());
}
{ Comment cmnt(masm_, "[ Stack check");
- PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
+ PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS);
Label ok;
ExternalReference stack_limit =
ExternalReference::address_of_stack_limit(isolate());
@@ -371,27 +372,29 @@ void FullCodeGenerator::verify_stack_height() {
}
-void FullCodeGenerator::EffectContext::Plug(Slot* slot) const {
+void FullCodeGenerator::EffectContext::Plug(Variable* var) const {
+ ASSERT(var->IsStackAllocated() || var->IsContextSlot());
}
-void FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const {
- MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register());
- __ mov(result_register(), slot_operand);
+void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
+ ASSERT(var->IsStackAllocated() || var->IsContextSlot());
+ codegen()->GetVar(result_register(), var);
}
-void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const {
- MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register());
+void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
+ ASSERT(var->IsStackAllocated() || var->IsContextSlot());
+ MemOperand operand = codegen()->VarOperand(var, result_register());
// Memory operands can be pushed directly.
- __ push(slot_operand);
+ __ push(operand);
codegen()->increment_stack_height();
}
-void FullCodeGenerator::TestContext::Plug(Slot* slot) const {
+void FullCodeGenerator::TestContext::Plug(Variable* var) const {
// For simplicity we always test the accumulator register.
- codegen()->Move(result_register(), slot);
+ codegen()->GetVar(result_register(), var);
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
codegen()->DoTest(this);
}
@@ -615,44 +618,54 @@ void FullCodeGenerator::Split(Condition cc,
}
-MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
- switch (slot->type()) {
- case Slot::PARAMETER:
- case Slot::LOCAL:
- return Operand(ebp, SlotOffset(slot));
- case Slot::CONTEXT: {
- int context_chain_length =
- scope()->ContextChainLength(slot->var()->scope());
- __ LoadContext(scratch, context_chain_length);
- return ContextOperand(scratch, slot->index());
- }
- case Slot::LOOKUP:
- UNREACHABLE();
+MemOperand FullCodeGenerator::StackOperand(Variable* var) {
+ ASSERT(var->IsStackAllocated());
+ // Offset is negative because higher indexes are at lower addresses.
+ int offset = -var->index() * kPointerSize;
+ // Adjust by a (parameter or local) base offset.
+ if (var->IsParameter()) {
+ offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
+ } else {
+ offset += JavaScriptFrameConstants::kLocal0Offset;
}
- UNREACHABLE();
- return Operand(eax, 0);
+ return Operand(ebp, offset);
}
-void FullCodeGenerator::Move(Register destination, Slot* source) {
- MemOperand location = EmitSlotSearch(source, destination);
- __ mov(destination, location);
+MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
+ ASSERT(var->IsContextSlot() || var->IsStackAllocated());
+ if (var->IsContextSlot()) {
+ int context_chain_length = scope()->ContextChainLength(var->scope());
+ __ LoadContext(scratch, context_chain_length);
+ return ContextOperand(scratch, var->index());
+ } else {
+ return StackOperand(var);
+ }
}
-void FullCodeGenerator::Move(Slot* dst,
- Register src,
- Register scratch1,
- Register scratch2) {
- ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented.
- ASSERT(!scratch1.is(src) && !scratch2.is(src));
- MemOperand location = EmitSlotSearch(dst, scratch1);
+void FullCodeGenerator::GetVar(Register dest, Variable* var) {
+ ASSERT(var->IsContextSlot() || var->IsStackAllocated());
+ MemOperand location = VarOperand(var, dest);
+ __ mov(dest, location);
+}
+
+
+void FullCodeGenerator::SetVar(Variable* var,
+ Register src,
+ Register scratch0,
+ Register scratch1) {
+ ASSERT(var->IsContextSlot() || var->IsStackAllocated());
+ ASSERT(!scratch0.is(src));
+ ASSERT(!scratch0.is(scratch1));
+ ASSERT(!scratch1.is(src));
+ MemOperand location = VarOperand(var, scratch0);
__ mov(location, src);
// Emit the write barrier code if the location is in the heap.
- if (dst->type() == Slot::CONTEXT) {
- int offset = Context::SlotOffset(dst->index());
- ASSERT(!scratch1.is(esi) && !src.is(esi) && !scratch2.is(esi));
- __ RecordWrite(scratch1, offset, src, scratch2);
+ if (var->IsContextSlot()) {
+ int offset = Context::SlotOffset(var->index());
+ ASSERT(!scratch0.is(esi) && !src.is(esi) && !scratch1.is(esi));
+ __ RecordWrite(scratch0, offset, src, scratch1);
}
}
@@ -683,29 +696,33 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
}
-void FullCodeGenerator::EmitDeclaration(Variable* variable,
+void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
Variable::Mode mode,
- FunctionLiteral* function) {
- Comment cmnt(masm_, "[ Declaration");
- ASSERT(variable != NULL); // Must have been resolved.
- Slot* slot = variable->AsSlot();
- ASSERT(slot != NULL);
- switch (slot->type()) {
- case Slot::PARAMETER:
- case Slot::LOCAL:
- if (mode == Variable::CONST) {
- __ mov(Operand(ebp, SlotOffset(slot)),
- Immediate(isolate()->factory()->the_hole_value()));
- } else if (function != NULL) {
+ FunctionLiteral* function,
+ int* global_count) {
+ // If it was not possible to allocate the variable at compile time, we
+ // need to "declare" it at runtime to make sure it actually exists in the
+ // local context.
+ Variable* variable = proxy->var();
+ switch (variable->location()) {
+ case Variable::UNALLOCATED:
+ ++(*global_count);
+ break;
+
+ case Variable::PARAMETER:
+ case Variable::LOCAL:
+ if (function != NULL) {
+ Comment cmnt(masm_, "[ Declaration");
VisitForAccumulatorValue(function);
- __ mov(Operand(ebp, SlotOffset(slot)), result_register());
+ __ mov(StackOperand(variable), result_register());
+ } else if (mode == Variable::CONST || mode == Variable::LET) {
+ Comment cmnt(masm_, "[ Declaration");
+ __ mov(StackOperand(variable),
+ Immediate(isolate()->factory()->the_hole_value()));
}
break;
- case Slot::CONTEXT:
- // We bypass the general EmitSlotSearch because we know more about
- // this specific context.
-
+ case Variable::CONTEXT:
// The variable in the decl always resides in the current function
// context.
ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
@@ -717,23 +734,28 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
__ cmp(ebx, isolate()->factory()->catch_context_map());
__ Check(not_equal, "Declaration in catch context.");
}
- if (mode == Variable::CONST) {
- __ mov(ContextOperand(esi, slot->index()),
- Immediate(isolate()->factory()->the_hole_value()));
- // No write barrier since the hole value is in old space.
- } else if (function != NULL) {
+ if (function != NULL) {
+ Comment cmnt(masm_, "[ Declaration");
VisitForAccumulatorValue(function);
- __ mov(ContextOperand(esi, slot->index()), result_register());
- int offset = Context::SlotOffset(slot->index());
+ __ mov(ContextOperand(esi, variable->index()), result_register());
+ int offset = Context::SlotOffset(variable->index());
__ mov(ebx, esi);
__ RecordWrite(ebx, offset, result_register(), ecx);
+ PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+ } else if (mode == Variable::CONST || mode == Variable::LET) {
+ Comment cmnt(masm_, "[ Declaration");
+ __ mov(ContextOperand(esi, variable->index()),
+ Immediate(isolate()->factory()->the_hole_value()));
+ // No write barrier since the hole value is in old space.
+ PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
}
break;
- case Slot::LOOKUP: {
+ case Variable::LOOKUP: {
+ Comment cmnt(masm_, "[ Declaration");
__ push(esi);
__ push(Immediate(variable->name()));
- // Declaration nodes are always introduced in one of two modes.
+ // Declaration nodes are always introduced in one of three modes.
ASSERT(mode == Variable::VAR ||
mode == Variable::CONST ||
mode == Variable::LET);
@@ -744,13 +766,13 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
// 'undefined') because we may have a (legal) redeclaration and we
// must not destroy the current value.
increment_stack_height(3);
- if (mode == Variable::CONST) {
+ if (function != NULL) {
+ VisitForStackValue(function);
+ } else if (mode == Variable::CONST || mode == Variable::LET) {
__ push(Immediate(isolate()->factory()->the_hole_value()));
increment_stack_height();
- } else if (function != NULL) {
- VisitForStackValue(function);
} else {
- __ push(Immediate(Smi::FromInt(0))); // No initial value!
+ __ push(Immediate(Smi::FromInt(0))); // Indicates no initial value.
increment_stack_height();
}
__ CallRuntime(Runtime::kDeclareContextSlot, 4);
@@ -761,18 +783,15 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
}
-void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
- EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
-}
+void FullCodeGenerator::VisitDeclaration(Declaration* decl) { }
void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals.
__ push(esi); // The context is the first argument.
__ push(Immediate(pairs));
- __ push(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
- __ push(Immediate(Smi::FromInt(strict_mode_flag())));
- __ CallRuntime(Runtime::kDeclareGlobals, 4);
+ __ push(Immediate(Smi::FromInt(DeclareGlobalsFlags())));
+ __ CallRuntime(Runtime::kDeclareGlobals, 3);
// Return value is ignored.
}
@@ -1071,10 +1090,9 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
}
-void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
- Slot* slot,
- TypeofState typeof_state,
- Label* slow) {
+void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
+ TypeofState typeof_state,
+ Label* slow) {
Register context = esi;
Register temp = edx;
@@ -1123,7 +1141,7 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
// All extension objects were empty and it is safe to use a global
// load IC call.
__ mov(eax, GlobalObjectOperand());
- __ mov(ecx, slot->var()->name());
+ __ mov(ecx, var->name());
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
? RelocInfo::CODE_TARGET
@@ -1132,14 +1150,13 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
}
-MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(
- Slot* slot,
- Label* slow) {
- ASSERT(slot->type() == Slot::CONTEXT);
+MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
+ Label* slow) {
+ ASSERT(var->IsContextSlot());
Register context = esi;
Register temp = ebx;
- for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) {
+ for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
if (s->num_heap_slots() > 0) {
if (s->calls_eval()) {
// Check that extension is NULL.
@@ -1159,60 +1176,31 @@ MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(
// This function is used only for loads, not stores, so it's safe to
// return an esi-based operand (the write barrier cannot be allowed to
// destroy the esi register).
- return ContextOperand(context, slot->index());
+ return ContextOperand(context, var->index());
}
-void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
- Slot* slot,
- TypeofState typeof_state,
- Label* slow,
- Label* done) {
+void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var,
+ TypeofState typeof_state,
+ Label* slow,
+ Label* done) {
// Generate fast-case code for variables that might be shadowed by
// eval-introduced variables. Eval is used a lot without
// introducing variables. In those cases, we do not want to
// perform a runtime call for all variables in the scope
// containing the eval.
- if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
- EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow);
+ if (var->mode() == Variable::DYNAMIC_GLOBAL) {
+ EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
__ jmp(done);
- } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
- Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot();
- Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
- if (potential_slot != NULL) {
- // Generate fast case for locals that rewrite to slots.
- __ mov(eax,
- ContextSlotOperandCheckExtensions(potential_slot, slow));
- if (potential_slot->var()->mode() == Variable::CONST) {
- __ cmp(eax, isolate()->factory()->the_hole_value());
- __ j(not_equal, done);
- __ mov(eax, isolate()->factory()->undefined_value());
- }
- __ jmp(done);
- } else if (rewrite != NULL) {
- // Generate fast case for calls of an argument function.
- Property* property = rewrite->AsProperty();
- if (property != NULL) {
- VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
- Literal* key_literal = property->key()->AsLiteral();
- if (obj_proxy != NULL &&
- key_literal != NULL &&
- obj_proxy->IsArguments() &&
- key_literal->handle()->IsSmi()) {
- // Load arguments object if there are no eval-introduced
- // variables. Then load the argument from the arguments
- // object using keyed load.
- __ mov(edx,
- ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(),
- slow));
- __ SafeSet(eax, Immediate(key_literal->handle()));
- Handle<Code> ic =
- isolate()->builtins()->KeyedLoadIC_Initialize();
- __ call(ic, RelocInfo::CODE_TARGET, GetPropertyId(property));
- __ jmp(done);
- }
- }
+ } else if (var->mode() == Variable::DYNAMIC_LOCAL) {
+ Variable* local = var->local_if_not_shadowed();
+ __ mov(eax, ContextSlotOperandCheckExtensions(local, slow));
+ if (local->mode() == Variable::CONST) {
+ __ cmp(eax, isolate()->factory()->the_hole_value());
+ __ j(not_equal, done);
+ __ mov(eax, isolate()->factory()->undefined_value());
}
+ __ jmp(done);
}
}
@@ -1222,54 +1210,60 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
SetSourcePosition(proxy->position());
Variable* var = proxy->var();
- // Three cases: non-this global variables, lookup slots, and all other
- // types of slots.
- Slot* slot = var->AsSlot();
- ASSERT((var->is_global() && !var->is_this()) == (slot == NULL));
-
- if (slot == NULL) {
- Comment cmnt(masm_, "Global variable");
- // Use inline caching. Variable name is passed in ecx and the global
- // object on the stack.
- __ mov(eax, GlobalObjectOperand());
- __ mov(ecx, var->name());
- Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
- __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
- context()->Plug(eax);
-
- } else if (slot->type() == Slot::LOOKUP) {
- Label done, slow;
-
- // Generate code for loading from variables potentially shadowed
- // by eval-introduced variables.
- EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done);
-
- __ bind(&slow);
- Comment cmnt(masm_, "Lookup slot");
- __ push(esi); // Context.
- __ push(Immediate(var->name()));
- __ CallRuntime(Runtime::kLoadContextSlot, 2);
- __ bind(&done);
+ // Three cases: global variables, lookup variables, and all other types of
+ // variables.
+ switch (var->location()) {
+ case Variable::UNALLOCATED: {
+ Comment cmnt(masm_, "Global variable");
+ // Use inline caching. Variable name is passed in ecx and the global
+ // object in eax.
+ __ mov(eax, GlobalObjectOperand());
+ __ mov(ecx, var->name());
+ Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+ __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
+ context()->Plug(eax);
+ break;
+ }
- context()->Plug(eax);
+ case Variable::PARAMETER:
+ case Variable::LOCAL:
+ case Variable::CONTEXT: {
+ Comment cmnt(masm_, var->IsContextSlot()
+ ? "Context variable"
+ : "Stack variable");
+ if (var->mode() != Variable::LET && var->mode() != Variable::CONST) {
+ context()->Plug(var);
+ } else {
+ // Let and const need a read barrier.
+ Label done;
+ GetVar(eax, var);
+ __ cmp(eax, isolate()->factory()->the_hole_value());
+ __ j(not_equal, &done, Label::kNear);
+ if (var->mode() == Variable::LET) {
+ __ push(Immediate(var->name()));
+ __ CallRuntime(Runtime::kThrowReferenceError, 1);
+ } else { // Variable::CONST
+ __ mov(eax, isolate()->factory()->undefined_value());
+ }
+ __ bind(&done);
+ context()->Plug(eax);
+ }
+ break;
+ }
- } else {
- Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
- ? "Context slot"
- : "Stack slot");
- if (var->mode() == Variable::CONST) {
- // Constants may be the hole value if they have not been initialized.
- // Unhole them.
- Label done;
- MemOperand slot_operand = EmitSlotSearch(slot, eax);
- __ mov(eax, slot_operand);
- __ cmp(eax, isolate()->factory()->the_hole_value());
- __ j(not_equal, &done, Label::kNear);
- __ mov(eax, isolate()->factory()->undefined_value());
+ case Variable::LOOKUP: {
+ Label done, slow;
+ // Generate code for loading from variables potentially shadowed
+ // by eval-introduced variables.
+ EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done);
+ __ bind(&slow);
+ Comment cmnt(masm_, "Lookup variable");
+ __ push(esi); // Context.
+ __ push(Immediate(var->name()));
+ __ CallRuntime(Runtime::kLoadContextSlot, 2);
__ bind(&done);
context()->Plug(eax);
- } else {
- context()->Plug(slot);
+ break;
}
}
}
@@ -1812,14 +1806,8 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
void FullCodeGenerator::EmitVariableAssignment(Variable* var,
Token::Value op) {
- ASSERT(var != NULL);
- ASSERT(var->is_global() || var->AsSlot() != NULL);
-
- if (var->is_global()) {
- ASSERT(!var->is_this());
- // Assignment to a global variable. Use inline caching for the
- // assignment. Right-hand-side value is passed in eax, variable name in
- // ecx, and the global object on the stack.
+ if (var->IsUnallocated()) {
+ // Global var, const, or let.
__ mov(ecx, var->name());
__ mov(edx, GlobalObjectOperand());
Handle<Code> ic = is_strict_mode()
@@ -1828,66 +1816,79 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
__ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
} else if (op == Token::INIT_CONST) {
- // Like var declarations, const declarations are hoisted to function
- // scope. However, unlike var initializers, const initializers are able
- // to drill a hole to that function context, even from inside a 'with'
- // context. We thus bypass the normal static scope lookup.
- Slot* slot = var->AsSlot();
- Label skip;
- switch (slot->type()) {
- case Slot::PARAMETER:
- // No const parameters.
- UNREACHABLE();
- break;
- case Slot::LOCAL:
- __ mov(edx, Operand(ebp, SlotOffset(slot)));
- __ cmp(edx, isolate()->factory()->the_hole_value());
- __ j(not_equal, &skip);
- __ mov(Operand(ebp, SlotOffset(slot)), eax);
- break;
- case Slot::CONTEXT:
- case Slot::LOOKUP:
- __ push(eax);
- __ push(esi);
- __ push(Immediate(var->name()));
- __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
- break;
+ // Const initializers need a write barrier.
+ ASSERT(!var->IsParameter()); // No const parameters.
+ if (var->IsStackLocal()) {
+ Label skip;
+ __ mov(edx, StackOperand(var));
+ __ cmp(edx, isolate()->factory()->the_hole_value());
+ __ j(not_equal, &skip);
+ __ mov(StackOperand(var), eax);
+ __ bind(&skip);
+ } else {
+ ASSERT(var->IsContextSlot() || var->IsLookupSlot());
+ // Like var declarations, const declarations are hoisted to function
+ // scope. However, unlike var initializers, const initializers are
+ // able to drill a hole to that function context, even from inside a
+ // 'with' context. We thus bypass the normal static scope lookup for
+ // var->IsContextSlot().
+ __ push(eax);
+ __ push(esi);
+ __ push(Immediate(var->name()));
+ __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
}
- __ bind(&skip);
- } else if (var->mode() != Variable::CONST) {
- // Perform the assignment for non-const variables. Const assignments
- // are simply skipped.
- Slot* slot = var->AsSlot();
- switch (slot->type()) {
- case Slot::PARAMETER:
- case Slot::LOCAL:
- // Perform the assignment.
- __ mov(Operand(ebp, SlotOffset(slot)), eax);
- break;
-
- case Slot::CONTEXT: {
- MemOperand target = EmitSlotSearch(slot, ecx);
- // Perform the assignment and issue the write barrier.
- __ mov(target, eax);
- // The value of the assignment is in eax. RecordWrite clobbers its
- // register arguments.
+ } else if (var->mode() == Variable::LET && op != Token::INIT_LET) {
+ // Non-initializing assignment to let variable needs a write barrier.
+ if (var->IsLookupSlot()) {
+ __ push(eax); // Value.
+ __ push(esi); // Context.
+ __ push(Immediate(var->name()));
+ __ push(Immediate(Smi::FromInt(strict_mode_flag())));
+ __ CallRuntime(Runtime::kStoreContextSlot, 4);
+ } else {
+ ASSERT(var->IsStackAllocated() || var->IsContextSlot());
+ Label assign;
+ MemOperand location = VarOperand(var, ecx);
+ __ mov(edx, location);
+ __ cmp(edx, isolate()->factory()->the_hole_value());
+ __ j(not_equal, &assign, Label::kNear);
+ __ push(Immediate(var->name()));
+ __ CallRuntime(Runtime::kThrowReferenceError, 1);
+ __ bind(&assign);
+ __ mov(location, eax);
+ if (var->IsContextSlot()) {
__ mov(edx, eax);
- int offset = Context::SlotOffset(slot->index());
- __ RecordWrite(ecx, offset, edx, ebx);
- break;
+ __ RecordWrite(ecx, Context::SlotOffset(var->index()), edx, ebx);
}
+ }
- case Slot::LOOKUP:
- // Call the runtime for the assignment.
- __ push(eax); // Value.
- __ push(esi); // Context.
- __ push(Immediate(var->name()));
- __ push(Immediate(Smi::FromInt(strict_mode_flag())));
- __ CallRuntime(Runtime::kStoreContextSlot, 4);
- break;
+ } else if (var->mode() != Variable::CONST) {
+ // Assignment to var or initializing assignment to let.
+ if (var->IsStackAllocated() || var->IsContextSlot()) {
+ MemOperand location = VarOperand(var, ecx);
+ if (FLAG_debug_code && op == Token::INIT_LET) {
+ // Check for an uninitialized let binding.
+ __ mov(edx, location);
+ __ cmp(edx, isolate()->factory()->the_hole_value());
+ __ Check(equal, "Let binding re-initialization.");
+ }
+ // Perform the assignment.
+ __ mov(location, eax);
+ if (var->IsContextSlot()) {
+ __ mov(edx, eax);
+ __ RecordWrite(ecx, Context::SlotOffset(var->index()), edx, ebx);
+ }
+ } else {
+ ASSERT(var->IsLookupSlot());
+ __ push(eax); // Value.
+ __ push(esi); // Context.
+ __ push(Immediate(var->name()));
+ __ push(Immediate(Smi::FromInt(strict_mode_flag())));
+ __ CallRuntime(Runtime::kStoreContextSlot, 4);
}
}
+ // Non-initializing assignments to consts are ignored.
}
@@ -2094,8 +2095,13 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
// Push the receiver of the enclosing function.
__ push(Operand(ebp, (2 + info_->scope()->num_parameters()) * kPointerSize));
- // Push the strict mode flag.
- __ push(Immediate(Smi::FromInt(strict_mode_flag())));
+ // Push the strict mode flag. In harmony mode every eval call
+ // is a strict mode eval call.
+ StrictModeFlag strict_mode = strict_mode_flag();
+ if (FLAG_harmony_block_scoping) {
+ strict_mode = kStrictMode;
+ }
+ __ push(Immediate(Smi::FromInt(strict_mode)));
__ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
? Runtime::kResolvePossiblyDirectEvalNoLookup
@@ -2111,18 +2117,18 @@ void FullCodeGenerator::VisitCall(Call* expr) {
#endif
Comment cmnt(masm_, "[ Call");
- Expression* fun = expr->expression();
- Variable* var = fun->AsVariableProxy()->AsVariable();
+ Expression* callee = expr->expression();
+ VariableProxy* proxy = callee->AsVariableProxy();
+ Property* property = callee->AsProperty();
- if (var != NULL && var->is_possibly_eval()) {
+ if (proxy != NULL && proxy->var()->is_possibly_eval()) {
// In a call to eval, we first call %ResolvePossiblyDirectEval to
- // resolve the function we need to call and the receiver of the
- // call. Then we call the resolved function using the given
- // arguments.
+ // resolve the function we need to call and the receiver of the call.
+ // Then we call the resolved function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
{ PreservePositionScope pos_scope(masm()->positions_recorder());
- VisitForStackValue(fun);
+ VisitForStackValue(callee);
// Reserved receiver slot.
__ push(Immediate(isolate()->factory()->undefined_value()));
increment_stack_height();
@@ -2132,15 +2138,14 @@ void FullCodeGenerator::VisitCall(Call* expr) {
}
// If we know that eval can only be shadowed by eval-introduced
- // variables we attempt to load the global eval function directly
- // in generated code. If we succeed, there is no need to perform a
+ // variables we attempt to load the global eval function directly in
+ // generated code. If we succeed, there is no need to perform a
// context lookup in the runtime system.
Label done;
- if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) {
+ Variable* var = proxy->var();
+ if (!var->IsUnallocated() && var->mode() == Variable::DYNAMIC_GLOBAL) {
Label slow;
- EmitLoadGlobalSlotCheckExtensions(var->AsSlot(),
- NOT_INSIDE_TYPEOF,
- &slow);
+ EmitLoadGlobalCheckExtensions(var, NOT_INSIDE_TYPEOF, &slow);
// Push the function and resolve eval.
__ push(eax);
EmitResolvePossiblyDirectEval(SKIP_CONTEXT_LOOKUP, arg_count);
@@ -2148,13 +2153,11 @@ void FullCodeGenerator::VisitCall(Call* expr) {
__ bind(&slow);
}
- // Push copy of the function (found below the arguments) and
+ // Push a copy of the function (found below the arguments) and
// resolve eval.
__ push(Operand(esp, (arg_count + 1) * kPointerSize));
EmitResolvePossiblyDirectEval(PERFORM_CONTEXT_LOOKUP, arg_count);
- if (done.is_linked()) {
- __ bind(&done);
- }
+ __ bind(&done);
// The runtime call returns a pair of values in eax (function) and
// edx (receiver). Touch up the stack with the right values.
@@ -2171,75 +2174,67 @@ void FullCodeGenerator::VisitCall(Call* expr) {
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
decrement_stack_height(arg_count + 1); // Function is left on the stack.
context()->DropAndPlug(1, eax);
- } else if (var != NULL && !var->is_this() && var->is_global()) {
+
+ } else if (proxy != NULL && proxy->var()->IsUnallocated()) {
// Push global object as receiver for the call IC.
__ push(GlobalObjectOperand());
increment_stack_height();
- EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
- } else if (var != NULL && var->AsSlot() != NULL &&
- var->AsSlot()->type() == Slot::LOOKUP) {
+ EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
+
+ } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
// Call to a lookup slot (dynamically introduced variable).
Label slow, done;
-
{ PreservePositionScope scope(masm()->positions_recorder());
- // Generate code for loading from variables potentially shadowed
- // by eval-introduced variables.
- EmitDynamicLoadFromSlotFastCase(var->AsSlot(),
- NOT_INSIDE_TYPEOF,
- &slow,
- &done);
+ // Generate code for loading from variables potentially shadowed by
+ // eval-introduced variables.
+ EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
}
-
__ bind(&slow);
- // Call the runtime to find the function to call (returned in eax)
- // and the object holding it (returned in edx).
+ // Call the runtime to find the function to call (returned in eax) and
+ // the object holding it (returned in edx).
__ push(context_register());
- __ push(Immediate(var->name()));
+ __ push(Immediate(proxy->name()));
__ CallRuntime(Runtime::kLoadContextSlot, 2);
__ push(eax); // Function.
- increment_stack_height();
__ push(edx); // Receiver.
- increment_stack_height();
+ increment_stack_height(2);
- // If fast case code has been generated, emit code to push the
- // function and receiver and have the slow path jump around this
- // code.
+ // If fast case code has been generated, emit code to push the function
+ // and receiver and have the slow path jump around this code.
if (done.is_linked()) {
Label call;
- __ jmp(&call);
+ __ jmp(&call, Label::kNear);
__ bind(&done);
- // Push function. Stack height already incremented in slow case above.
+ // Push function. Stack height already incremented in slow case
+ // above.
__ push(eax);
- // The receiver is implicitly the global receiver. Indicate this
- // by passing the hole to the call function stub.
+ // The receiver is implicitly the global receiver. Indicate this by
+ // passing the hole to the call function stub.
__ push(Immediate(isolate()->factory()->the_hole_value()));
__ bind(&call);
}
- // The receiver is either the global receiver or an object found
- // by LoadContextSlot. That object could be the hole if the
- // receiver is implicitly the global object.
+ // The receiver is either the global receiver or an object found by
+ // LoadContextSlot. That object could be the hole if the receiver is
+ // implicitly the global object.
EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT);
- } else if (fun->AsProperty() != NULL) {
- // Call to an object property.
- Property* prop = fun->AsProperty();
- Literal* key = prop->key()->AsLiteral();
- if (key != NULL && key->handle()->IsSymbol()) {
- // Call to a named property, use call IC.
- { PreservePositionScope scope(masm()->positions_recorder());
- VisitForStackValue(prop->obj());
- }
- EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
+
+ } else if (property != NULL) {
+ { PreservePositionScope scope(masm()->positions_recorder());
+ VisitForStackValue(property->obj());
+ }
+ if (property->key()->IsPropertyName()) {
+ EmitCallWithIC(expr,
+ property->key()->AsLiteral()->handle(),
+ RelocInfo::CODE_TARGET);
} else {
- // Call to a keyed property.
- { PreservePositionScope scope(masm()->positions_recorder());
- VisitForStackValue(prop->obj());
- }
- EmitKeyedCallWithIC(expr, prop->key());
+ EmitKeyedCallWithIC(expr, property->key());
}
+
} else {
+ // Call to an arbitrary expression not handled specially above.
{ PreservePositionScope scope(masm()->positions_recorder());
- VisitForStackValue(fun);
+ VisitForStackValue(callee);
}
// Load global receiver object.
__ mov(ebx, GlobalObjectOperand());
@@ -3199,7 +3194,7 @@ void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
Label done, not_found;
// tmp now holds finger offset as a smi.
- ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
+ STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
__ mov(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
__ cmp(key, CodeGenerator::FixedArrayElementOperand(cache, tmp));
__ j(not_equal, &not_found);
@@ -3611,31 +3606,32 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
switch (expr->op()) {
case Token::DELETE: {
Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
- Property* prop = expr->expression()->AsProperty();
- Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
+ Property* property = expr->expression()->AsProperty();
+ VariableProxy* proxy = expr->expression()->AsVariableProxy();
- if (prop != NULL) {
- VisitForStackValue(prop->obj());
- VisitForStackValue(prop->key());
+ if (property != NULL) {
+ VisitForStackValue(property->obj());
+ VisitForStackValue(property->key());
__ push(Immediate(Smi::FromInt(strict_mode_flag())));
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
decrement_stack_height(2);
context()->Plug(eax);
- } else if (var != NULL) {
+ } else if (proxy != NULL) {
+ Variable* var = proxy->var();
// Delete of an unqualified identifier is disallowed in strict mode
- // but "delete this" is.
+ // but "delete this" is allowed.
ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this());
- if (var->is_global()) {
+ if (var->IsUnallocated()) {
__ push(GlobalObjectOperand());
__ push(Immediate(var->name()));
__ push(Immediate(Smi::FromInt(kNonStrictMode)));
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(eax);
- } else if (var->AsSlot() != NULL &&
- var->AsSlot()->type() != Slot::LOOKUP) {
- // Result of deleting non-global, non-dynamic variables is false.
- // The subexpression does not have side effects.
- context()->Plug(false);
+ } else if (var->IsStackAllocated() || var->IsContextSlot()) {
+ // Result of deleting non-global variables is false. 'this' is
+ // not really a variable, though we implement it as one. The
+ // subexpression does not have side effects.
+ context()->Plug(var->is_this());
} else {
// Non-global variable. Call the runtime to try to delete from the
// context where the variable was introduced.
@@ -3932,7 +3928,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
ASSERT(!context()->IsEffect());
ASSERT(!context()->IsTest());
- if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
+ if (proxy != NULL && proxy->var()->IsUnallocated()) {
Comment cmnt(masm_, "Global variable");
__ mov(eax, GlobalObjectOperand());
__ mov(ecx, Immediate(proxy->name()));
@@ -3942,15 +3938,12 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
__ call(ic);
PrepareForBailout(expr, TOS_REG);
context()->Plug(eax);
- } else if (proxy != NULL &&
- proxy->var()->AsSlot() != NULL &&
- proxy->var()->AsSlot()->type() == Slot::LOOKUP) {
+ } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
Label done, slow;
// Generate code for loading from variables potentially shadowed
// by eval-introduced variables.
- Slot* slot = proxy->var()->AsSlot();
- EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done);
+ EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done);
__ bind(&slow);
__ push(esi);
@@ -4242,8 +4235,8 @@ void FullCodeGenerator::EnterFinallyBlock() {
ASSERT(!result_register().is(edx));
__ pop(edx);
__ sub(Operand(edx), Immediate(masm_->CodeObject()));
- ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
- ASSERT_EQ(0, kSmiTag);
+ STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
+ STATIC_ASSERT(kSmiTag == 0);
__ SmiTag(edx);
__ push(edx);
// Store result register while executing finally block.
@@ -4264,6 +4257,34 @@ void FullCodeGenerator::ExitFinallyBlock() {
#undef __
+#define __ ACCESS_MASM(masm())
+
+FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
+ int* stack_depth,
+ int* context_length) {
+ // The macros used here must preserve the result register.
+
+ // Because the handler block contains the context of the finally
+ // code, we can restore it directly from there for the finally code
+ // rather than iteratively unwinding contexts via their previous
+ // links.
+ __ Drop(*stack_depth); // Down to the handler block.
+ if (*context_length > 0) {
+ // Restore the context to its dedicated register and the stack.
+ __ mov(esi, Operand(esp, StackHandlerConstants::kContextOffset));
+ __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
+ }
+ __ PopTryHandler();
+ __ call(finally_entry_);
+
+ *stack_depth = 0;
+ *context_length = 0;
+ return previous_;
+}
+
+
+#undef __
+
} } // namespace v8::internal
#endif // V8_TARGET_ARCH_IA32
diff --git a/deps/v8/src/ia32/ic-ia32.cc b/deps/v8/src/ia32/ic-ia32.cc
index 5f143b104f..7d3ead2eac 100644
--- a/deps/v8/src/ia32/ic-ia32.cc
+++ b/deps/v8/src/ia32/ic-ia32.cc
@@ -324,7 +324,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm,
__ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset));
__ j(above_equal, out_of_range);
// Fast case: Do the load.
- ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0));
+ STATIC_ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0));
__ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize));
__ cmp(Operand(scratch), Immediate(FACTORY->the_hole_value()));
// In case the loaded value is the_hole we have to consult GetProperty
@@ -358,7 +358,7 @@ static void GenerateKeyStringCheck(MacroAssembler* masm,
__ j(zero, index_string);
// Is the string a symbol?
- ASSERT(kSymbolTag != 0);
+ STATIC_ASSERT(kSymbolTag != 0);
__ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask);
__ j(zero, not_symbol);
}
diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.cc b/deps/v8/src/ia32/lithium-codegen-ia32.cc
index 5f670387f6..31e9dd82e2 100644
--- a/deps/v8/src/ia32/lithium-codegen-ia32.cc
+++ b/deps/v8/src/ia32/lithium-codegen-ia32.cc
@@ -194,14 +194,14 @@ bool LCodeGen::GeneratePrologue() {
// Copy parameters into context if necessary.
int num_parameters = scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) {
- Slot* slot = scope()->parameter(i)->AsSlot();
- if (slot != NULL && slot->type() == Slot::CONTEXT) {
+ Variable* var = scope()->parameter(i);
+ if (var->IsContextSlot()) {
int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(num_parameters - 1 - i) * kPointerSize;
// Load parameter from stack.
__ mov(eax, Operand(ebp, parameter_offset));
// Store it in the context.
- int context_offset = Context::SlotOffset(slot->index());
+ int context_offset = Context::SlotOffset(var->index());
__ mov(Operand(esi, context_offset), eax);
// Update the write barrier. This clobbers all involved
// registers, so we have to use a third register to avoid
@@ -3175,7 +3175,6 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
void LCodeGen::DoStoreKeyedFastDoubleElement(
LStoreKeyedFastDoubleElement* instr) {
XMMRegister value = ToDoubleRegister(instr->value());
- Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
Label have_value;
__ ucomisd(value, value);
@@ -3234,8 +3233,6 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
// Dispatch on the indirect string shape: slice or cons.
Label cons_string;
- const uint32_t kSlicedNotConsMask = kSlicedStringTag & ~kConsStringTag;
- ASSERT(IsPowerOf2(kSlicedNotConsMask) && kSlicedNotConsMask != 0);
__ test(result, Immediate(kSlicedNotConsMask));
__ j(zero, &cons_string, Label::kNear);
@@ -3271,7 +3268,8 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
// Dispatch on the encoding: ASCII or two-byte.
Label ascii_string;
- STATIC_ASSERT(kAsciiStringTag != 0);
+ STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
+ STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
__ test(result, Immediate(kStringEncodingMask));
__ j(not_zero, &ascii_string, Label::kNear);
diff --git a/deps/v8/src/ia32/macro-assembler-ia32.cc b/deps/v8/src/ia32/macro-assembler-ia32.cc
index 9df5cad915..6d3ce2bcd9 100644
--- a/deps/v8/src/ia32/macro-assembler-ia32.cc
+++ b/deps/v8/src/ia32/macro-assembler-ia32.cc
@@ -148,7 +148,7 @@ void MacroAssembler::RecordWrite(Register object,
Label done;
// Skip barrier if writing a smi.
- ASSERT_EQ(0, kSmiTag);
+ STATIC_ASSERT(kSmiTag == 0);
JumpIfSmi(value, &done, Label::kNear);
InNewSpace(object, value, equal, &done, Label::kNear);
@@ -166,8 +166,8 @@ void MacroAssembler::RecordWrite(Register object,
// Array access: calculate the destination address in the same manner as
// KeyedStoreIC::GenerateGeneric. Multiply a smi by 2 to get an offset
// into an array of words.
- ASSERT_EQ(1, kSmiTagSize);
- ASSERT_EQ(0, kSmiTag);
+ STATIC_ASSERT(kSmiTagSize == 1);
+ STATIC_ASSERT(kSmiTag == 0);
lea(dst, Operand(object, dst, times_half_pointer_size,
FixedArray::kHeaderSize - kHeapObjectTag));
}
@@ -193,7 +193,7 @@ void MacroAssembler::RecordWrite(Register object,
Label done;
// Skip barrier if writing a smi.
- ASSERT_EQ(0, kSmiTag);
+ STATIC_ASSERT(kSmiTag == 0);
JumpIfSmi(value, &done, Label::kNear);
InNewSpace(object, value, equal, &done);
@@ -326,7 +326,7 @@ Condition MacroAssembler::IsObjectStringType(Register heap_object,
Register instance_type) {
mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
- ASSERT(kNotStringTag != 0);
+ STATIC_ASSERT(kNotStringTag != 0);
test(instance_type, Immediate(kIsNotStringMask));
return zero;
}
@@ -1172,7 +1172,7 @@ void MacroAssembler::AllocateAsciiString(Register result,
}
-void MacroAssembler::AllocateConsString(Register result,
+void MacroAssembler::AllocateTwoByteConsString(Register result,
Register scratch1,
Register scratch2,
Label* gc_required) {
@@ -1208,6 +1208,42 @@ void MacroAssembler::AllocateAsciiConsString(Register result,
}
+void MacroAssembler::AllocateTwoByteSlicedString(Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required) {
+ // Allocate heap number in new space.
+ AllocateInNewSpace(SlicedString::kSize,
+ result,
+ scratch1,
+ scratch2,
+ gc_required,
+ TAG_OBJECT);
+
+ // Set the map. The other fields are left uninitialized.
+ mov(FieldOperand(result, HeapObject::kMapOffset),
+ Immediate(isolate()->factory()->sliced_string_map()));
+}
+
+
+void MacroAssembler::AllocateAsciiSlicedString(Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required) {
+ // Allocate heap number in new space.
+ AllocateInNewSpace(SlicedString::kSize,
+ result,
+ scratch1,
+ scratch2,
+ gc_required,
+ TAG_OBJECT);
+
+ // Set the map. The other fields are left uninitialized.
+ mov(FieldOperand(result, HeapObject::kMapOffset),
+ Immediate(isolate()->factory()->sliced_ascii_string_map()));
+}
+
+
// Copy memory, byte-by-byte, from source to destination. Not optimized for
// long or aligned copies. The contents of scratch and length are destroyed.
// Source and destination are incremented by length.
@@ -2166,7 +2202,7 @@ void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register object1,
Register scratch2,
Label* failure) {
// Check that both objects are not smis.
- ASSERT_EQ(0, kSmiTag);
+ STATIC_ASSERT(kSmiTag == 0);
mov(scratch1, Operand(object1));
and_(scratch1, Operand(object2));
JumpIfSmi(scratch1, failure);
diff --git a/deps/v8/src/ia32/macro-assembler-ia32.h b/deps/v8/src/ia32/macro-assembler-ia32.h
index d79df5ea55..1906644c35 100644
--- a/deps/v8/src/ia32/macro-assembler-ia32.h
+++ b/deps/v8/src/ia32/macro-assembler-ia32.h
@@ -275,8 +275,8 @@ class MacroAssembler: public Assembler {
// Smi tagging support.
void SmiTag(Register reg) {
- ASSERT(kSmiTag == 0);
- ASSERT(kSmiTagSize == 1);
+ STATIC_ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTagSize == 1);
add(reg, Operand(reg));
}
void SmiUntag(Register reg) {
@@ -285,9 +285,9 @@ class MacroAssembler: public Assembler {
// Modifies the register even if it does not contain a Smi!
void SmiUntag(Register reg, Label* is_smi) {
- ASSERT(kSmiTagSize == 1);
+ STATIC_ASSERT(kSmiTagSize == 1);
sar(reg, kSmiTagSize);
- ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTag == 0);
j(not_carry, is_smi);
}
@@ -437,7 +437,7 @@ class MacroAssembler: public Assembler {
// Allocate a raw cons string object. Only the map field of the result is
// initialized.
- void AllocateConsString(Register result,
+ void AllocateTwoByteConsString(Register result,
Register scratch1,
Register scratch2,
Label* gc_required);
@@ -446,6 +446,17 @@ class MacroAssembler: public Assembler {
Register scratch2,
Label* gc_required);
+ // Allocate a raw sliced string object. Only the map field of the result is
+ // initialized.
+ void AllocateTwoByteSlicedString(Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required);
+ void AllocateAsciiSlicedString(Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required);
+
// Copy memory, byte-by-byte, from source to destination. Not optimized for
// long or aligned copies.
// The contents of index and scratch are destroyed.
diff --git a/deps/v8/src/ia32/regexp-macro-assembler-ia32.cc b/deps/v8/src/ia32/regexp-macro-assembler-ia32.cc
index 7d7de0ef44..d175d9e036 100644
--- a/deps/v8/src/ia32/regexp-macro-assembler-ia32.cc
+++ b/deps/v8/src/ia32/regexp-macro-assembler-ia32.cc
@@ -1080,7 +1080,7 @@ int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address,
MaybeObject* result = Execution::HandleStackGuardInterrupt();
if (*code_handle != re_code) { // Return address no longer valid
- int delta = *code_handle - re_code;
+ int delta = code_handle->address() - re_code->address();
// Overwrite the return address on the stack.
*return_address += delta;
}
diff --git a/deps/v8/src/ia32/stub-cache-ia32.cc b/deps/v8/src/ia32/stub-cache-ia32.cc
index 4a37b07c71..621a9bbfa2 100644
--- a/deps/v8/src/ia32/stub-cache-ia32.cc
+++ b/deps/v8/src/ia32/stub-cache-ia32.cc
@@ -273,7 +273,7 @@ static void GenerateStringCheck(MacroAssembler* masm,
// Check that the object is a string.
__ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
__ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
- ASSERT(kNotStringTag != 0);
+ STATIC_ASSERT(kNotStringTag != 0);
__ test(scratch, Immediate(kNotStringTag));
__ j(not_zero, non_string_object);
}
diff --git a/deps/v8/src/isolate.cc b/deps/v8/src/isolate.cc
index 09cbc8a1e6..d366902977 100644
--- a/deps/v8/src/isolate.cc
+++ b/deps/v8/src/isolate.cc
@@ -1409,7 +1409,6 @@ Isolate::Isolate()
global_handles_(NULL),
context_switcher_(NULL),
thread_manager_(NULL),
- ast_sentinels_(NULL),
string_tracker_(NULL),
regexp_stack_(NULL),
embedder_data_(NULL) {
@@ -1546,9 +1545,6 @@ Isolate::~Isolate() {
delete regexp_stack_;
regexp_stack_ = NULL;
- delete ast_sentinels_;
- ast_sentinels_ = NULL;
-
delete descriptor_lookup_cache_;
descriptor_lookup_cache_ = NULL;
delete context_slot_cache_;
@@ -1710,7 +1706,6 @@ bool Isolate::Init(Deserializer* des) {
bootstrapper_ = new Bootstrapper();
handle_scope_implementer_ = new HandleScopeImplementer(this);
stub_cache_ = new StubCache(this);
- ast_sentinels_ = new AstSentinels();
regexp_stack_ = new RegExpStack();
regexp_stack_->isolate_ = this;
diff --git a/deps/v8/src/isolate.h b/deps/v8/src/isolate.h
index 5bb504d2da..7c690d26ba 100644
--- a/deps/v8/src/isolate.h
+++ b/deps/v8/src/isolate.h
@@ -47,7 +47,6 @@
namespace v8 {
namespace internal {
-class AstSentinels;
class Bootstrapper;
class CodeGenerator;
class CodeRange;
@@ -878,8 +877,6 @@ class Isolate {
return &objects_string_input_buffer_;
}
- AstSentinels* ast_sentinels() { return ast_sentinels_; }
-
RuntimeState* runtime_state() { return &runtime_state_; }
StaticResource<SafeStringInputBuffer>* compiler_safe_string_input_buffer() {
@@ -1138,7 +1135,6 @@ class Isolate {
GlobalHandles* global_handles_;
ContextSwitcher* context_switcher_;
ThreadManager* thread_manager_;
- AstSentinels* ast_sentinels_;
RuntimeState runtime_state_;
StaticResource<SafeStringInputBuffer> compiler_safe_string_input_buffer_;
Builtins builtins_;
diff --git a/deps/v8/src/json.js b/deps/v8/src/json.js
index 8fd410fa4d..a491bcc151 100644
--- a/deps/v8/src/json.js
+++ b/deps/v8/src/json.js
@@ -337,11 +337,12 @@ function JSONStringify(value, replacer, space) {
return JSONSerialize('', {'': value}, replacer, new InternalArray(), "", gap);
}
-function SetupJSON() {
+function SetUpJSON() {
+ %CheckIsBootstrapping();
InstallFunctions($JSON, DONT_ENUM, $Array(
"parse", JSONParse,
"stringify", JSONStringify
));
}
-SetupJSON();
+SetUpJSON()
diff --git a/deps/v8/src/jsregexp.cc b/deps/v8/src/jsregexp.cc
index 4ca83a4769..3ebfbdfc98 100644
--- a/deps/v8/src/jsregexp.cc
+++ b/deps/v8/src/jsregexp.cc
@@ -2661,7 +2661,8 @@ int TextNode::GreedyLoopTextLength() {
// this alternative and back to this choice node. If there are variable
// length nodes or other complications in the way then return a sentinel
// value indicating that a greedy loop cannot be constructed.
-int ChoiceNode::GreedyLoopTextLength(GuardedAlternative* alternative) {
+int ChoiceNode::GreedyLoopTextLengthForAlternative(
+ GuardedAlternative* alternative) {
int length = 0;
RegExpNode* node = alternative->node();
// Later we will generate code for all these text nodes using recursion
@@ -2700,7 +2701,8 @@ void LoopChoiceNode::AddContinueAlternative(GuardedAlternative alt) {
void LoopChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
if (trace->stop_node() == this) {
- int text_length = GreedyLoopTextLength(&(alternatives_->at(0)));
+ int text_length =
+ GreedyLoopTextLengthForAlternative(&(alternatives_->at(0)));
ASSERT(text_length != kNodeIsTooComplexForGreedyLoops);
// Update the counter-based backtracking info on the stack. This is an
// optimization for greedy loops (see below).
@@ -2893,7 +2895,7 @@ void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
Trace* current_trace = trace;
- int text_length = GreedyLoopTextLength(&(alternatives_->at(0)));
+ int text_length = GreedyLoopTextLengthForAlternative(&(alternatives_->at(0)));
bool greedy_loop = false;
Label greedy_loop_label;
Trace counter_backtrack_trace;
diff --git a/deps/v8/src/jsregexp.h b/deps/v8/src/jsregexp.h
index 13f9e2ea06..3bd5e00893 100644
--- a/deps/v8/src/jsregexp.h
+++ b/deps/v8/src/jsregexp.h
@@ -1071,7 +1071,7 @@ class ChoiceNode: public RegExpNode {
virtual bool try_to_emit_quick_check_for_alternative(int i) { return true; }
protected:
- int GreedyLoopTextLength(GuardedAlternative* alternative);
+ int GreedyLoopTextLengthForAlternative(GuardedAlternative* alternative);
ZoneList<GuardedAlternative>* alternatives_;
private:
diff --git a/deps/v8/src/liveedit.cc b/deps/v8/src/liveedit.cc
index 0b01e8af15..07c9fdde05 100644
--- a/deps/v8/src/liveedit.cc
+++ b/deps/v8/src/liveedit.cc
@@ -860,8 +860,7 @@ class FunctionInfoListener {
int j = 0;
for (int i = 0; i < list.length(); i++) {
Variable* var1 = list[i];
- Slot* slot = var1->AsSlot();
- if (slot != NULL && slot->type() == Slot::CONTEXT) {
+ if (var1->IsContextSlot()) {
if (j != i) {
list[j] = var1;
}
@@ -873,7 +872,7 @@ class FunctionInfoListener {
for (int k = 1; k < j; k++) {
int l = k;
for (int m = k + 1; m < j; m++) {
- if (list[l]->AsSlot()->index() > list[m]->AsSlot()->index()) {
+ if (list[l]->index() > list[m]->index()) {
l = m;
}
}
@@ -887,7 +886,7 @@ class FunctionInfoListener {
SetElementNonStrict(
scope_info_list,
scope_info_length,
- Handle<Smi>(Smi::FromInt(list[i]->AsSlot()->index())));
+ Handle<Smi>(Smi::FromInt(list[i]->index())));
scope_info_length++;
}
SetElementNonStrict(scope_info_list,
diff --git a/deps/v8/src/macros.py b/deps/v8/src/macros.py
index 5ba7ac3afa..e3d1e03871 100644
--- a/deps/v8/src/macros.py
+++ b/deps/v8/src/macros.py
@@ -122,7 +122,7 @@ macro IS_SPEC_OBJECT(arg) = (%_IsSpecObject(arg));
# Inline macros. Use %IS_VAR to make sure arg is evaluated only once.
macro NUMBER_IS_NAN(arg) = (!%_IsSmi(%IS_VAR(arg)) && !(arg == arg));
-macro NUMBER_IS_FINITE(arg) = (%_IsSmi(%IS_VAR(arg)) || arg - arg == 0);
+macro NUMBER_IS_FINITE(arg) = (%_IsSmi(%IS_VAR(arg)) || ((arg == arg) && (arg != 1/0) && (arg != -1/0)));
macro TO_INTEGER(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : %NumberToInteger(ToNumber(arg)));
macro TO_INTEGER_MAP_MINUS_ZERO(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : %NumberToIntegerMapMinusZero(ToNumber(arg)));
macro TO_INT32(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : (arg >> 0));
@@ -170,7 +170,7 @@ macro CAPTURE(index) = (3 + (index));
const CAPTURE0 = 3;
const CAPTURE1 = 4;
-# PropertyDescriptor return value indices - must match
+# PropertyDescriptor return value indices - must match
# PropertyDescriptorIndices in runtime.cc.
const IS_ACCESSOR_INDEX = 0;
const VALUE_INDEX = 1;
@@ -179,3 +179,17 @@ const SETTER_INDEX = 3;
const WRITABLE_INDEX = 4;
const ENUMERABLE_INDEX = 5;
const CONFIGURABLE_INDEX = 6;
+
+# For messages.js
+# Matches Script::Type from objects.h
+const TYPE_NATIVE = 0;
+const TYPE_EXTENSION = 1;
+const TYPE_NORMAL = 2;
+
+# Matches Script::CompilationType from objects.h
+const COMPILATION_TYPE_HOST = 0;
+const COMPILATION_TYPE_EVAL = 1;
+const COMPILATION_TYPE_JSON = 2;
+
+# Matches Messages::kNoLineNumberInfo from v8.h
+const kNoLineNumberInfo = 0;
diff --git a/deps/v8/src/math.js b/deps/v8/src/math.js
index 70b8c57cae..b5a6d18117 100644
--- a/deps/v8/src/math.js
+++ b/deps/v8/src/math.js
@@ -38,7 +38,7 @@ const $abs = MathAbs;
function MathConstructor() {}
%FunctionSetInstanceClassName(MathConstructor, 'Math');
const $Math = new MathConstructor();
-$Math.__proto__ = global.Object.prototype;
+$Math.__proto__ = $Object.prototype;
%SetProperty(global, "Math", $Math, DONT_ENUM);
// ECMA 262 - 15.8.2.1
@@ -195,8 +195,9 @@ function MathTan(x) {
// -------------------------------------------------------------------
-function SetupMath() {
- // Setup math constants.
+function SetUpMath() {
+ %CheckIsBootstrapping();
+ // Set up math constants.
// ECMA-262, section 15.8.1.1.
%OptimizeObjectForAddingMultipleProperties($Math, 8);
%SetProperty($Math,
@@ -236,7 +237,7 @@ function SetupMath() {
DONT_ENUM | DONT_DELETE | READ_ONLY);
%ToFastProperties($Math);
- // Setup non-enumerable functions of the Math object and
+ // Set up non-enumerable functions of the Math object and
// set their names.
InstallFunctionsOnHiddenPrototype($Math, DONT_ENUM, $Array(
"random", MathRandom,
@@ -258,7 +259,6 @@ function SetupMath() {
"max", MathMax,
"min", MathMin
));
-};
-
+}
-SetupMath();
+SetUpMath();
diff --git a/deps/v8/src/messages.js b/deps/v8/src/messages.js
index cbbb70eb1a..3c85d9416a 100644
--- a/deps/v8/src/messages.js
+++ b/deps/v8/src/messages.js
@@ -28,27 +28,14 @@
// -------------------------------------------------------------------
//
-// Matches Script::Type from objects.h
-var TYPE_NATIVE = 0;
-var TYPE_EXTENSION = 1;
-var TYPE_NORMAL = 2;
-
-// Matches Script::CompilationType from objects.h
-var COMPILATION_TYPE_HOST = 0;
-var COMPILATION_TYPE_EVAL = 1;
-var COMPILATION_TYPE_JSON = 2;
-
-// Matches Messages::kNoLineNumberInfo from v8.h
-var kNoLineNumberInfo = 0;
-
// If this object gets passed to an error constructor the error will
// get an accessor for .message that constructs a descriptive error
// message on access.
-var kAddMessageAccessorsMarker = { };
+const kAddMessageAccessorsMarker = { };
-var kMessages = 0;
-
-var kReplacementMarkers = [ "%0", "%1", "%2", "%3" ];
+// This will be lazily initialized when first needed (and forcibly
+// overwritten even though it's const).
+const kMessages = 0;
function FormatString(format, message) {
var args = %MessageGetArguments(message);
@@ -56,14 +43,16 @@ function FormatString(format, message) {
var arg_num = 0;
for (var i = 0; i < format.length; i++) {
var str = format[i];
- for (arg_num = 0; arg_num < kReplacementMarkers.length; arg_num++) {
- if (str == kReplacementMarkers[arg_num]) {
+ if (str.length == 2 && %_StringCharCodeAt(str, 0) == 0x25) {
+ // Two-char string starts with "%".
+ var arg_num = (%_StringCharCodeAt(str, 1) - 0x30) >>> 0;
+ if (arg_num < 4) {
+ // str is one of %0, %1, %2 or %3.
try {
str = ToDetailString(args[arg_num]);
} catch (e) {
str = "#<error>";
}
- break;
}
}
result += str;
@@ -102,18 +91,16 @@ function ToStringCheckErrorObject(obj) {
function ToDetailString(obj) {
- if (obj != null && IS_OBJECT(obj) &&
- obj.toString === $Object.prototype.toString) {
+ if (obj != null && IS_OBJECT(obj) && obj.toString === ObjectToString) {
var constructor = obj.constructor;
- if (!constructor) return ToStringCheckErrorObject(obj);
- var constructorName = constructor.name;
- if (!constructorName || !IS_STRING(constructorName)) {
- return ToStringCheckErrorObject(obj);
+ if (typeof constructor == "function") {
+ var constructorName = constructor.name;
+ if (IS_STRING(constructorName) && constructorName !== "") {
+ return "#<" + constructorName + ">";
+ }
}
- return "#<" + constructorName + ">";
- } else {
- return ToStringCheckErrorObject(obj);
}
+ return ToStringCheckErrorObject(obj);
}
@@ -129,10 +116,11 @@ function MakeGenericError(constructor, type, args) {
/**
- * Setup the Script function and constructor.
+ * Set up the Script function and constructor.
*/
%FunctionSetInstanceClassName(Script, 'Script');
-%SetProperty(Script.prototype, 'constructor', Script, DONT_ENUM);
+%SetProperty(Script.prototype, 'constructor', Script,
+ DONT_ENUM | DONT_DELETE | READ_ONLY);
%SetCode(Script, function(x) {
// Script objects can only be created by the VM.
throw new $Error("Not supported");
@@ -142,116 +130,132 @@ function MakeGenericError(constructor, type, args) {
// Helper functions; called from the runtime system.
function FormatMessage(message) {
if (kMessages === 0) {
- kMessages = {
+ var messagesDictionary = [
// Error
- cyclic_proto: ["Cyclic __proto__ value"],
- code_gen_from_strings: ["Code generation from strings disallowed for this context"],
+ "cyclic_proto", ["Cyclic __proto__ value"],
+ "code_gen_from_strings", ["Code generation from strings disallowed for this context"],
// TypeError
- unexpected_token: ["Unexpected token ", "%0"],
- unexpected_token_number: ["Unexpected number"],
- unexpected_token_string: ["Unexpected string"],
- unexpected_token_identifier: ["Unexpected identifier"],
- unexpected_reserved: ["Unexpected reserved word"],
- unexpected_strict_reserved: ["Unexpected strict mode reserved word"],
- unexpected_eos: ["Unexpected end of input"],
- malformed_regexp: ["Invalid regular expression: /", "%0", "/: ", "%1"],
- unterminated_regexp: ["Invalid regular expression: missing /"],
- regexp_flags: ["Cannot supply flags when constructing one RegExp from another"],
- incompatible_method_receiver: ["Method ", "%0", " called on incompatible receiver ", "%1"],
- invalid_lhs_in_assignment: ["Invalid left-hand side in assignment"],
- invalid_lhs_in_for_in: ["Invalid left-hand side in for-in"],
- invalid_lhs_in_postfix_op: ["Invalid left-hand side expression in postfix operation"],
- invalid_lhs_in_prefix_op: ["Invalid left-hand side expression in prefix operation"],
- multiple_defaults_in_switch: ["More than one default clause in switch statement"],
- newline_after_throw: ["Illegal newline after throw"],
- redeclaration: ["%0", " '", "%1", "' has already been declared"],
- no_catch_or_finally: ["Missing catch or finally after try"],
- unknown_label: ["Undefined label '", "%0", "'"],
- uncaught_exception: ["Uncaught ", "%0"],
- stack_trace: ["Stack Trace:\n", "%0"],
- called_non_callable: ["%0", " is not a function"],
- undefined_method: ["Object ", "%1", " has no method '", "%0", "'"],
- property_not_function: ["Property '", "%0", "' of object ", "%1", " is not a function"],
- cannot_convert_to_primitive: ["Cannot convert object to primitive value"],
- not_constructor: ["%0", " is not a constructor"],
- not_defined: ["%0", " is not defined"],
- non_object_property_load: ["Cannot read property '", "%0", "' of ", "%1"],
- non_object_property_store: ["Cannot set property '", "%0", "' of ", "%1"],
- non_object_property_call: ["Cannot call method '", "%0", "' of ", "%1"],
- with_expression: ["%0", " has no properties"],
- illegal_invocation: ["Illegal invocation"],
- no_setter_in_callback: ["Cannot set property ", "%0", " of ", "%1", " which has only a getter"],
- apply_non_function: ["Function.prototype.apply was called on ", "%0", ", which is a ", "%1", " and not a function"],
- apply_wrong_args: ["Function.prototype.apply: Arguments list has wrong type"],
- invalid_in_operator_use: ["Cannot use 'in' operator to search for '", "%0", "' in ", "%1"],
- instanceof_function_expected: ["Expecting a function in instanceof check, but got ", "%0"],
- instanceof_nonobject_proto: ["Function has non-object prototype '", "%0", "' in instanceof check"],
- null_to_object: ["Cannot convert null to object"],
- reduce_no_initial: ["Reduce of empty array with no initial value"],
- getter_must_be_callable: ["Getter must be a function: ", "%0"],
- setter_must_be_callable: ["Setter must be a function: ", "%0"],
- value_and_accessor: ["Invalid property. A property cannot both have accessors and be writable or have a value: ", "%0"],
- proto_object_or_null: ["Object prototype may only be an Object or null"],
- property_desc_object: ["Property description must be an object: ", "%0"],
- redefine_disallowed: ["Cannot redefine property: ", "%0"],
- define_disallowed: ["Cannot define property:", "%0", ", object is not extensible."],
- non_extensible_proto: ["%0", " is not extensible"],
- handler_non_object: ["Proxy.", "%0", " called with non-object as handler"],
- handler_trap_missing: ["Proxy handler ", "%0", " has no '", "%1", "' trap"],
- handler_trap_must_be_callable: ["Proxy handler ", "%0", " has non-callable '", "%1", "' trap"],
- handler_returned_false: ["Proxy handler ", "%0", " returned false for '", "%1", "' trap"],
- handler_returned_undefined: ["Proxy handler ", "%0", " returned undefined for '", "%1", "' trap"],
- proxy_prop_not_configurable: ["Trap ", "%1", " of proxy handler ", "%0", " returned non-configurable descriptor for property ", "%2"],
- proxy_non_object_prop_names: ["Trap ", "%1", " returned non-object ", "%0"],
- proxy_repeated_prop_name: ["Trap ", "%1", " returned repeated property name ", "%2"],
- invalid_weakmap_key: ["Invalid value used as weak map key"],
+ "unexpected_token", ["Unexpected token ", "%0"],
+ "unexpected_token_number", ["Unexpected number"],
+ "unexpected_token_string", ["Unexpected string"],
+ "unexpected_token_identifier", ["Unexpected identifier"],
+ "unexpected_reserved", ["Unexpected reserved word"],
+ "unexpected_strict_reserved", ["Unexpected strict mode reserved word"],
+ "unexpected_eos", ["Unexpected end of input"],
+ "malformed_regexp", ["Invalid regular expression: /", "%0", "/: ", "%1"],
+ "unterminated_regexp", ["Invalid regular expression: missing /"],
+ "regexp_flags", ["Cannot supply flags when constructing one RegExp from another"],
+ "incompatible_method_receiver", ["Method ", "%0", " called on incompatible receiver ", "%1"],
+ "invalid_lhs_in_assignment", ["Invalid left-hand side in assignment"],
+ "invalid_lhs_in_for_in", ["Invalid left-hand side in for-in"],
+ "invalid_lhs_in_postfix_op", ["Invalid left-hand side expression in postfix operation"],
+ "invalid_lhs_in_prefix_op", ["Invalid left-hand side expression in prefix operation"],
+ "multiple_defaults_in_switch", ["More than one default clause in switch statement"],
+ "newline_after_throw", ["Illegal newline after throw"],
+ "redeclaration", ["%0", " '", "%1", "' has already been declared"],
+ "no_catch_or_finally", ["Missing catch or finally after try"],
+ "unknown_label", ["Undefined label '", "%0", "'"],
+ "uncaught_exception", ["Uncaught ", "%0"],
+ "stack_trace", ["Stack Trace:\n", "%0"],
+ "called_non_callable", ["%0", " is not a function"],
+ "undefined_method", ["Object ", "%1", " has no method '", "%0", "'"],
+ "property_not_function", ["Property '", "%0", "' of object ", "%1", " is not a function"],
+ "cannot_convert_to_primitive", ["Cannot convert object to primitive value"],
+ "not_constructor", ["%0", " is not a constructor"],
+ "not_defined", ["%0", " is not defined"],
+ "non_object_property_load", ["Cannot read property '", "%0", "' of ", "%1"],
+ "non_object_property_store", ["Cannot set property '", "%0", "' of ", "%1"],
+ "non_object_property_call", ["Cannot call method '", "%0", "' of ", "%1"],
+ "with_expression", ["%0", " has no properties"],
+ "illegal_invocation", ["Illegal invocation"],
+ "no_setter_in_callback", ["Cannot set property ", "%0", " of ", "%1", " which has only a getter"],
+ "apply_non_function", ["Function.prototype.apply was called on ", "%0", ", which is a ", "%1", " and not a function"],
+ "apply_wrong_args", ["Function.prototype.apply: Arguments list has wrong type"],
+ "invalid_in_operator_use", ["Cannot use 'in' operator to search for '", "%0", "' in ", "%1"],
+ "instanceof_function_expected", ["Expecting a function in instanceof check, but got ", "%0"],
+ "instanceof_nonobject_proto", ["Function has non-object prototype '", "%0", "' in instanceof check"],
+ "null_to_object", ["Cannot convert null to object"],
+ "reduce_no_initial", ["Reduce of empty array with no initial value"],
+ "getter_must_be_callable", ["Getter must be a function: ", "%0"],
+ "setter_must_be_callable", ["Setter must be a function: ", "%0"],
+ "value_and_accessor", ["Invalid property. A property cannot both have accessors and be writable or have a value, ", "%0"],
+ "proto_object_or_null", ["Object prototype may only be an Object or null"],
+ "property_desc_object", ["Property description must be an object: ", "%0"],
+ "redefine_disallowed", ["Cannot redefine property: ", "%0"],
+ "define_disallowed", ["Cannot define property:", "%0", ", object is not extensible."],
+ "non_extensible_proto", ["%0", " is not extensible"],
+ "handler_non_object", ["Proxy.", "%0", " called with non-object as handler"],
+ "handler_trap_missing", ["Proxy handler ", "%0", " has no '", "%1", "' trap"],
+ "handler_trap_must_be_callable", ["Proxy handler ", "%0", " has non-callable '", "%1", "' trap"],
+ "handler_returned_false", ["Proxy handler ", "%0", " returned false for '", "%1", "' trap"],
+ "handler_returned_undefined", ["Proxy handler ", "%0", " returned undefined for '", "%1", "' trap"],
+ "proxy_prop_not_configurable", ["Trap ", "%1", " of proxy handler ", "%0", " returned non-configurable descriptor for property ", "%2"],
+ "proxy_non_object_prop_names", ["Trap ", "%1", " returned non-object ", "%0"],
+ "proxy_repeated_prop_name", ["Trap ", "%1", " returned repeated property name ", "%2"],
+ "invalid_weakmap_key", ["Invalid value used as weak map key"],
// RangeError
- invalid_array_length: ["Invalid array length"],
- stack_overflow: ["Maximum call stack size exceeded"],
+ "invalid_array_length", ["Invalid array length"],
+ "stack_overflow", ["Maximum call stack size exceeded"],
// SyntaxError
- unable_to_parse: ["Parse error"],
- invalid_regexp_flags: ["Invalid flags supplied to RegExp constructor '", "%0", "'"],
- invalid_regexp: ["Invalid RegExp pattern /", "%0", "/"],
- illegal_break: ["Illegal break statement"],
- illegal_continue: ["Illegal continue statement"],
- illegal_return: ["Illegal return statement"],
- error_loading_debugger: ["Error loading debugger"],
- no_input_to_regexp: ["No input to ", "%0"],
- invalid_json: ["String '", "%0", "' is not valid JSON"],
- circular_structure: ["Converting circular structure to JSON"],
- obj_ctor_property_non_object: ["Object.", "%0", " called on non-object"],
- called_on_null_or_undefined: ["%0", " called on null or undefined"],
- array_indexof_not_defined: ["Array.getIndexOf: Argument undefined"],
- object_not_extensible: ["Can't add property ", "%0", ", object is not extensible"],
- illegal_access: ["Illegal access"],
- invalid_preparser_data: ["Invalid preparser data for function ", "%0"],
- strict_mode_with: ["Strict mode code may not include a with statement"],
- strict_catch_variable: ["Catch variable may not be eval or arguments in strict mode"],
- too_many_arguments: ["Too many arguments in function call (only 32766 allowed)"],
- too_many_parameters: ["Too many parameters in function definition (only 32766 allowed)"],
- too_many_variables: ["Too many variables declared (only 32767 allowed)"],
- strict_param_name: ["Parameter name eval or arguments is not allowed in strict mode"],
- strict_param_dupe: ["Strict mode function may not have duplicate parameter names"],
- strict_var_name: ["Variable name may not be eval or arguments in strict mode"],
- strict_function_name: ["Function name may not be eval or arguments in strict mode"],
- strict_octal_literal: ["Octal literals are not allowed in strict mode."],
- strict_duplicate_property: ["Duplicate data property in object literal not allowed in strict mode"],
- accessor_data_property: ["Object literal may not have data and accessor property with the same name"],
- accessor_get_set: ["Object literal may not have multiple get/set accessors with the same name"],
- strict_lhs_assignment: ["Assignment to eval or arguments is not allowed in strict mode"],
- strict_lhs_postfix: ["Postfix increment/decrement may not have eval or arguments operand in strict mode"],
- strict_lhs_prefix: ["Prefix increment/decrement may not have eval or arguments operand in strict mode"],
- strict_reserved_word: ["Use of future reserved word in strict mode"],
- strict_delete: ["Delete of an unqualified identifier in strict mode."],
- strict_delete_property: ["Cannot delete property '", "%0", "' of ", "%1"],
- strict_const: ["Use of const in strict mode."],
- strict_function: ["In strict mode code, functions can only be declared at top level or immediately within another function." ],
- strict_read_only_property: ["Cannot assign to read only property '", "%0", "' of ", "%1"],
- strict_cannot_assign: ["Cannot assign to read only '", "%0", "' in strict mode"],
- strict_poison_pill: ["'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them"],
- strict_caller: ["Illegal access to a strict mode caller function."],
- unprotected_let: ["Illegal let declaration in unprotected statement context."],
- };
+ "unable_to_parse", ["Parse error"],
+ "invalid_regexp_flags", ["Invalid flags supplied to RegExp constructor '", "%0", "'"],
+ "invalid_regexp", ["Invalid RegExp pattern /", "%0", "/"],
+ "illegal_break", ["Illegal break statement"],
+ "illegal_continue", ["Illegal continue statement"],
+ "illegal_return", ["Illegal return statement"],
+ "error_loading_debugger", ["Error loading debugger"],
+ "no_input_to_regexp", ["No input to ", "%0"],
+ "invalid_json", ["String '", "%0", "' is not valid JSON"],
+ "circular_structure", ["Converting circular structure to JSON"],
+ "obj_ctor_property_non_object", ["Object.", "%0", " called on non-object"],
+ "called_on_null_or_undefined", ["%0", " called on null or undefined"],
+ "array_indexof_not_defined", ["Array.getIndexOf: Argument undefined"],
+ "object_not_extensible", ["Can't add property ", "%0", ", object is not extensible"],
+ "illegal_access", ["Illegal access"],
+ "invalid_preparser_data", ["Invalid preparser data for function ", "%0"],
+ "strict_mode_with", ["Strict mode code may not include a with statement"],
+ "strict_catch_variable", ["Catch variable may not be eval or arguments in strict mode"],
+ "too_many_arguments", ["Too many arguments in function call (only 32766 allowed)"],
+ "too_many_parameters", ["Too many parameters in function definition (only 32766 allowed)"],
+ "too_many_variables", ["Too many variables declared (only 32767 allowed)"],
+ "strict_param_name", ["Parameter name eval or arguments is not allowed in strict mode"],
+ "strict_param_dupe", ["Strict mode function may not have duplicate parameter names"],
+ "strict_var_name", ["Variable name may not be eval or arguments in strict mode"],
+ "strict_function_name", ["Function name may not be eval or arguments in strict mode"],
+ "strict_octal_literal", ["Octal literals are not allowed in strict mode."],
+ "strict_duplicate_property", ["Duplicate data property in object literal not allowed in strict mode"],
+ "accessor_data_property", ["Object literal may not have data and accessor property with the same name"],
+ "accessor_get_set", ["Object literal may not have multiple get/set accessors with the same name"],
+ "strict_lhs_assignment", ["Assignment to eval or arguments is not allowed in strict mode"],
+ "strict_lhs_postfix", ["Postfix increment/decrement may not have eval or arguments operand in strict mode"],
+ "strict_lhs_prefix", ["Prefix increment/decrement may not have eval or arguments operand in strict mode"],
+ "strict_reserved_word", ["Use of future reserved word in strict mode"],
+ "strict_delete", ["Delete of an unqualified identifier in strict mode."],
+ "strict_delete_property", ["Cannot delete property '", "%0", "' of ", "%1"],
+ "strict_const", ["Use of const in strict mode."],
+ "strict_function", ["In strict mode code, functions can only be declared at top level or immediately within another function." ],
+ "strict_read_only_property", ["Cannot assign to read only property '", "%0", "' of ", "%1"],
+ "strict_cannot_assign", ["Cannot assign to read only '", "%0", "' in strict mode"],
+ "strict_poison_pill", ["'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them"],
+ "strict_caller", ["Illegal access to a strict mode caller function."],
+ "unprotected_let", ["Illegal let declaration in unprotected statement context."],
+ ];
+ var messages = { __proto__ : null };
+ var desc = new PropertyDescriptor();
+ desc.setConfigurable(false);
+ desc.setEnumerable(false);
+ desc.setWritable(false);
+ for (var i = 0; i < messagesDictionary.length; i += 2) {
+ var key = messagesDictionary[i];
+ var format = messagesDictionary[i + 1];
+ ObjectFreeze(format);
+ desc.setValue(format);
+ DefineOwnProperty(messages, key, desc);
+ }
+ %PreventExtensions(messages);
+ %IgnoreAttributesAndSetProperty(builtins, "kMessages",
+ messages,
+ DONT_DELETE | DONT_ENUM | READ_ONLY);
}
var message_type = %MessageGetType(message);
var format = kMessages[message_type];
@@ -317,7 +321,7 @@ function MakeError(type, args) {
* @return {number} 0 if input too small, -1 if input too large,
else the line number.
*/
-Script.prototype.lineFromPosition = function(position) {
+function ScriptLineFromPosition(position) {
var lower = 0;
var upper = this.lineCount() - 1;
var line_ends = this.line_ends;
@@ -356,8 +360,8 @@ Script.prototype.lineFromPosition = function(position) {
* @return {SourceLocation}
* If line is negative or not in the source null is returned.
*/
-Script.prototype.locationFromPosition = function (position,
- include_resource_offset) {
+function ScriptLocationFromPosition(position,
+ include_resource_offset) {
var line = this.lineFromPosition(position);
if (line == -1) return null;
@@ -365,7 +369,9 @@ Script.prototype.locationFromPosition = function (position,
var line_ends = this.line_ends;
var start = line == 0 ? 0 : line_ends[line - 1] + 1;
var end = line_ends[line];
- if (end > 0 && %_CallFunction(this.source, end - 1, StringCharAt) == '\r') end--;
+ if (end > 0 && %_CallFunction(this.source, end - 1, StringCharAt) == '\r') {
+ end--;
+ }
var column = position - start;
// Adjust according to the offset within the resource.
@@ -390,11 +396,12 @@ Script.prototype.locationFromPosition = function (position,
* @param {number} opt_line The line within the source. Default value is 0
* @param {number} opt_column The column in within the line. Default value is 0
* @param {number} opt_offset_position The offset from the begining of the
- * source from where the line and column calculation starts. Default value is 0
+ * source from where the line and column calculation starts.
+ * Default value is 0
* @return {SourceLocation}
* If line is negative or not in the source null is returned.
*/
-Script.prototype.locationFromLine = function (opt_line, opt_column, opt_offset_position) {
+function ScriptLocationFromLine(opt_line, opt_column, opt_offset_position) {
// Default is the first line in the script. Lines in the script is relative
// to the offset within the resource.
var line = 0;
@@ -436,7 +443,7 @@ Script.prototype.locationFromLine = function (opt_line, opt_column, opt_offset_p
* @return {SourceSlice} The source slice or null of the parameters where
* invalid
*/
-Script.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
+function ScriptSourceSlice(opt_from_line, opt_to_line) {
var from_line = IS_UNDEFINED(opt_from_line) ? this.line_offset : opt_from_line;
var to_line = IS_UNDEFINED(opt_to_line) ? this.line_offset + this.lineCount() : opt_to_line
@@ -463,7 +470,7 @@ Script.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
}
-Script.prototype.sourceLine = function (opt_line) {
+function ScriptSourceLine(opt_line) {
// Default is the first line in the script. Lines in the script are relative
// to the offset within the resource.
var line = 0;
@@ -489,7 +496,7 @@ Script.prototype.sourceLine = function (opt_line) {
* @return {number}
* Number of source lines.
*/
-Script.prototype.lineCount = function() {
+function ScriptLineCount() {
// Return number of source lines.
return this.line_ends.length;
};
@@ -505,9 +512,10 @@ Script.prototype.lineCount = function() {
* @return {?string} script name if present, value for //@ sourceURL comment
* otherwise.
*/
-Script.prototype.nameOrSourceURL = function() {
- if (this.name)
+function ScriptNameOrSourceURL() {
+ if (this.name) {
return this.name;
+ }
// TODO(608): the spaces in a regexp below had to be escaped as \040
// because this file is being processed by js2c whose handling of spaces
// in regexps is broken. Also, ['"] are excluded from allowed URLs to
@@ -533,6 +541,20 @@ Script.prototype.nameOrSourceURL = function() {
}
+SetUpLockedPrototype(Script,
+ $Array("source", "name", "line_ends", "line_offset", "column_offset"),
+ $Array(
+ "lineFromPosition", ScriptLineFromPosition,
+ "locationFromPosition", ScriptLocationFromPosition,
+ "locationFromLine", ScriptLocationFromLine,
+ "sourceSlice", ScriptSourceSlice,
+ "sourceLine", ScriptSourceLine,
+ "lineCount", ScriptLineCount,
+ "nameOrSourceURL", ScriptNameOrSourceURL
+ )
+);
+
+
/**
* Class for source location. A source location is a position within some
* source with the following properties:
@@ -563,8 +585,6 @@ function SourceLocation(script, position, line, column, start, end) {
this.end = end;
}
-SourceLocation.prototype.__proto__ = null;
-
const kLineLengthLimit = 78;
/**
@@ -575,7 +595,7 @@ const kLineLengthLimit = 78;
* @param {number} opt_before The number of characters to prefer before the
* position with a default value of 10 less that the limit
*/
-SourceLocation.prototype.restrict = function (opt_limit, opt_before) {
+function SourceLocationRestrict(opt_limit, opt_before) {
// Find the actual limit to use.
var limit;
var before;
@@ -622,11 +642,20 @@ SourceLocation.prototype.restrict = function (opt_limit, opt_before) {
* @return {String}
* Source text for this location.
*/
-SourceLocation.prototype.sourceText = function () {
+function SourceLocationSourceText() {
return %_CallFunction(this.script.source, this.start, this.end, StringSubstring);
};
+SetUpLockedPrototype(SourceLocation,
+ $Array("script", "position", "line", "column", "start", "end"),
+ $Array(
+ "restrict", SourceLocationRestrict,
+ "sourceText", SourceLocationSourceText
+ )
+);
+
+
/**
* Class for a source slice. A source slice is a part of a script source with
* the following properties:
@@ -653,20 +682,23 @@ function SourceSlice(script, from_line, to_line, from_position, to_position) {
this.to_position = to_position;
}
-SourceSlice.prototype.__proto__ = null;
-
/**
* Get the source text for a SourceSlice
* @return {String} Source text for this slice. The last line will include
* the line terminating characters (if any)
*/
-SourceSlice.prototype.sourceText = function () {
+function SourceSliceSourceText() {
return %_CallFunction(this.script.source,
this.from_position,
this.to_position,
StringSubstring);
};
+SetUpLockedPrototype(SourceSlice,
+ $Array("script", "from_line", "to_line", "from_position", "to_position"),
+ $Array("sourceText", SourceSliceSourceText)
+);
+
// Returns the offset of the given position within the containing
// line.
@@ -721,13 +753,11 @@ function CallSite(receiver, fun, pos) {
this.pos = pos;
}
-CallSite.prototype.__proto__ = null;
-
-CallSite.prototype.getThis = function () {
+function CallSiteGetThis() {
return this.receiver;
};
-CallSite.prototype.getTypeName = function () {
+function CallSiteGetTypeName() {
var constructor = this.receiver.constructor;
if (!constructor) {
return %_CallFunction(this.receiver, ObjectToString);
@@ -739,33 +769,33 @@ CallSite.prototype.getTypeName = function () {
return constructorName;
};
-CallSite.prototype.isToplevel = function () {
+function CallSiteIsToplevel() {
if (this.receiver == null) {
return true;
}
return IS_GLOBAL(this.receiver);
};
-CallSite.prototype.isEval = function () {
+function CallSiteIsEval() {
var script = %FunctionGetScript(this.fun);
return script && script.compilation_type == COMPILATION_TYPE_EVAL;
};
-CallSite.prototype.getEvalOrigin = function () {
+function CallSiteGetEvalOrigin() {
var script = %FunctionGetScript(this.fun);
return FormatEvalOrigin(script);
};
-CallSite.prototype.getScriptNameOrSourceURL = function () {
+function CallSiteGetScriptNameOrSourceURL() {
var script = %FunctionGetScript(this.fun);
return script ? script.nameOrSourceURL() : null;
};
-CallSite.prototype.getFunction = function () {
+function CallSiteGetFunction() {
return this.fun;
};
-CallSite.prototype.getFunctionName = function () {
+function CallSiteGetFunctionName() {
// See if the function knows its own name
var name = this.fun.name;
if (name) {
@@ -781,7 +811,7 @@ CallSite.prototype.getFunctionName = function () {
return null;
};
-CallSite.prototype.getMethodName = function () {
+function CallSiteGetMethodName() {
// See if we can find a unique property on the receiver that holds
// this function.
var ownName = this.fun.name;
@@ -811,12 +841,12 @@ CallSite.prototype.getMethodName = function () {
return null;
};
-CallSite.prototype.getFileName = function () {
+function CallSiteGetFileName() {
var script = %FunctionGetScript(this.fun);
return script ? script.name : null;
};
-CallSite.prototype.getLineNumber = function () {
+function CallSiteGetLineNumber() {
if (this.pos == -1) {
return null;
}
@@ -828,7 +858,7 @@ CallSite.prototype.getLineNumber = function () {
return location ? location.line + 1 : null;
};
-CallSite.prototype.getColumnNumber = function () {
+function CallSiteGetColumnNumber() {
if (this.pos == -1) {
return null;
}
@@ -840,16 +870,16 @@ CallSite.prototype.getColumnNumber = function () {
return location ? location.column + 1: null;
};
-CallSite.prototype.isNative = function () {
+function CallSiteIsNative() {
var script = %FunctionGetScript(this.fun);
return script ? (script.type == TYPE_NATIVE) : false;
};
-CallSite.prototype.getPosition = function () {
+function CallSiteGetPosition() {
return this.pos;
};
-CallSite.prototype.isConstructor = function () {
+function CallSiteIsConstructor() {
var constructor = this.receiver ? this.receiver.constructor : null;
if (!constructor) {
return false;
@@ -857,6 +887,25 @@ CallSite.prototype.isConstructor = function () {
return this.fun === constructor;
};
+SetUpLockedPrototype(CallSite, $Array("receiver", "fun", "pos"), $Array(
+ "getThis", CallSiteGetThis,
+ "getTypeName", CallSiteGetTypeName,
+ "isToplevel", CallSiteIsToplevel,
+ "isEval", CallSiteIsEval,
+ "getEvalOrigin", CallSiteGetEvalOrigin,
+ "getScriptNameOrSourceURL", CallSiteGetScriptNameOrSourceURL,
+ "getFunction", CallSiteGetFunction,
+ "getFunctionName", CallSiteGetFunctionName,
+ "getMethodName", CallSiteGetMethodName,
+ "getFileName", CallSiteGetFileName,
+ "getLineNumber", CallSiteGetLineNumber,
+ "getColumnNumber", CallSiteGetColumnNumber,
+ "isNative", CallSiteIsNative,
+ "getPosition", CallSiteGetPosition,
+ "isConstructor", CallSiteIsConstructor
+));
+
+
function FormatEvalOrigin(script) {
var sourceURL = script.nameOrSourceURL();
if (sourceURL) {
@@ -998,63 +1047,6 @@ function FormatRawStackTrace(error, raw_stack) {
}
}
-function DefineError(f) {
- // Store the error function in both the global object
- // and the runtime object. The function is fetched
- // from the runtime object when throwing errors from
- // within the runtime system to avoid strange side
- // effects when overwriting the error functions from
- // user code.
- var name = f.name;
- %SetProperty(global, name, f, DONT_ENUM);
- this['$' + name] = f;
- // Configure the error function.
- if (name == 'Error') {
- // The prototype of the Error object must itself be an error.
- // However, it can't be an instance of the Error object because
- // it hasn't been properly configured yet. Instead we create a
- // special not-a-true-error-but-close-enough object.
- function ErrorPrototype() {}
- %FunctionSetPrototype(ErrorPrototype, $Object.prototype);
- %FunctionSetInstanceClassName(ErrorPrototype, 'Error');
- %FunctionSetPrototype(f, new ErrorPrototype());
- } else {
- %FunctionSetPrototype(f, new $Error());
- }
- %FunctionSetInstanceClassName(f, 'Error');
- %SetProperty(f.prototype, 'constructor', f, DONT_ENUM);
- // The name property on the prototype of error objects is not
- // specified as being read-one and dont-delete. However, allowing
- // overwriting allows leaks of error objects between script blocks
- // in the same context in a browser setting. Therefore we fix the
- // name.
- %SetProperty(f.prototype, "name", name, DONT_ENUM | DONT_DELETE | READ_ONLY);
- %SetCode(f, function(m) {
- if (%_IsConstructCall()) {
- // Define all the expected properties directly on the error
- // object. This avoids going through getters and setters defined
- // on prototype objects.
- %IgnoreAttributesAndSetProperty(this, 'stack', void 0, DONT_ENUM);
- %IgnoreAttributesAndSetProperty(this, 'arguments', void 0, DONT_ENUM);
- %IgnoreAttributesAndSetProperty(this, 'type', void 0, DONT_ENUM);
- if (m === kAddMessageAccessorsMarker) {
- // DefineOneShotAccessor always inserts a message property and
- // ignores setters.
- DefineOneShotAccessor(this, 'message', function (obj) {
- return FormatMessage(%NewMessageObject(obj.type, obj.arguments));
- });
- } else if (!IS_UNDEFINED(m)) {
- %IgnoreAttributesAndSetProperty(this,
- 'message',
- ToString(m),
- DONT_ENUM);
- }
- captureStackTrace(this, f);
- } else {
- return new f(m);
- }
- });
-}
function captureStackTrace(obj, cons_opt) {
var stackTraceLimit = $Error.stackTraceLimit;
@@ -1070,52 +1062,100 @@ function captureStackTrace(obj, cons_opt) {
});
};
-$Math.__proto__ = global.Object.prototype;
-// DefineError is a native function. Use explicit receiver. Otherwise
-// the receiver will be 'undefined'.
-this.DefineError(function Error() { });
-this.DefineError(function TypeError() { });
-this.DefineError(function RangeError() { });
-this.DefineError(function SyntaxError() { });
-this.DefineError(function ReferenceError() { });
-this.DefineError(function EvalError() { });
-this.DefineError(function URIError() { });
+function SetUpError() {
+ // Define special error type constructors.
+
+ function DefineError(f) {
+ // Store the error function in both the global object
+ // and the runtime object. The function is fetched
+ // from the runtime object when throwing errors from
+ // within the runtime system to avoid strange side
+ // effects when overwriting the error functions from
+ // user code.
+ var name = f.name;
+ %SetProperty(global, name, f, DONT_ENUM);
+ %SetProperty(builtins, '$' + name, f, DONT_ENUM | DONT_DELETE | READ_ONLY);
+ // Configure the error function.
+ if (name == 'Error') {
+ // The prototype of the Error object must itself be an error.
+ // However, it can't be an instance of the Error object because
+ // it hasn't been properly configured yet. Instead we create a
+ // special not-a-true-error-but-close-enough object.
+ function ErrorPrototype() {}
+ %FunctionSetPrototype(ErrorPrototype, $Object.prototype);
+ %FunctionSetInstanceClassName(ErrorPrototype, 'Error');
+ %FunctionSetPrototype(f, new ErrorPrototype());
+ } else {
+ %FunctionSetPrototype(f, new $Error());
+ }
+ %FunctionSetInstanceClassName(f, 'Error');
+ %SetProperty(f.prototype, 'constructor', f, DONT_ENUM);
+ // The name property on the prototype of error objects is not
+ // specified as being read-one and dont-delete. However, allowing
+ // overwriting allows leaks of error objects between script blocks
+ // in the same context in a browser setting. Therefore we fix the
+ // name.
+ %SetProperty(f.prototype, "name", name,
+ DONT_ENUM | DONT_DELETE | READ_ONLY) ;
+ %SetCode(f, function(m) {
+ if (%_IsConstructCall()) {
+ // Define all the expected properties directly on the error
+ // object. This avoids going through getters and setters defined
+ // on prototype objects.
+ %IgnoreAttributesAndSetProperty(this, 'stack', void 0, DONT_ENUM);
+ %IgnoreAttributesAndSetProperty(this, 'arguments', void 0, DONT_ENUM);
+ %IgnoreAttributesAndSetProperty(this, 'type', void 0, DONT_ENUM);
+ if (m === kAddMessageAccessorsMarker) {
+ // DefineOneShotAccessor always inserts a message property and
+ // ignores setters.
+ DefineOneShotAccessor(this, 'message', function (obj) {
+ return FormatMessage(%NewMessageObject(obj.type, obj.arguments));
+ });
+ } else if (!IS_UNDEFINED(m)) {
+ %IgnoreAttributesAndSetProperty(this,
+ 'message',
+ ToString(m),
+ DONT_ENUM);
+ }
+ captureStackTrace(this, f);
+ } else {
+ return new f(m);
+ }
+ });
+ }
-$Error.captureStackTrace = captureStackTrace;
+ DefineError(function Error() { });
+ DefineError(function TypeError() { });
+ DefineError(function RangeError() { });
+ DefineError(function SyntaxError() { });
+ DefineError(function ReferenceError() { });
+ DefineError(function EvalError() { });
+ DefineError(function URIError() { });
+}
-// Setup extra properties of the Error.prototype object.
-function setErrorMessage() {
- var desc = {value: '',
- enumerable: false,
- configurable: true,
- writable: true };
- DefineOwnProperty($Error.prototype,
- 'message',
- ToPropertyDescriptor(desc),
- true);
+SetUpError();
-}
+$Error.captureStackTrace = captureStackTrace;
-setErrorMessage();
+%SetProperty($Error.prototype, 'message', '', DONT_ENUM);
// Global list of error objects visited during errorToString. This is
// used to detect cycles in error toString formatting.
-var visited_errors = new $Array();
-var cyclic_error_marker = new $Object();
+const visited_errors = new InternalArray();
+const cyclic_error_marker = new $Object();
-function errorToStringDetectCycle() {
- if (!%PushIfAbsent(visited_errors, this)) throw cyclic_error_marker;
+function errorToStringDetectCycle(error) {
+ if (!%PushIfAbsent(visited_errors, error)) throw cyclic_error_marker;
try {
- var type = this.type;
- if (type && !%_CallFunction(this, "message", ObjectHasOwnProperty)) {
- var formatted = FormatMessage(%NewMessageObject(type, this.arguments));
- return this.name + ": " + formatted;
+ var type = error.type;
+ var hasMessage = %_CallFunction(error, "message", ObjectHasOwnProperty);
+ if (type && !hasMessage) {
+ var formatted = FormatMessage(%NewMessageObject(type, error.arguments));
+ return error.name + ": " + formatted;
}
- var message = %_CallFunction(this, "message", ObjectHasOwnProperty)
- ? (": " + this.message)
- : "";
- return this.name + message;
+ var message = hasMessage ? (": " + error.message) : "";
+ return error.name + message;
} finally {
visited_errors.length = visited_errors.length - 1;
}
@@ -1131,7 +1171,7 @@ function errorToString() {
function isCyclicErrorMarker(o) { return o === cyclic_error_marker; }
try {
- return %_CallFunction(this, errorToStringDetectCycle);
+ return errorToStringDetectCycle(this);
} catch(e) {
// If this error message was encountered already return the empty
// string for it instead of recursively formatting it.
diff --git a/deps/v8/src/mips/assembler-mips.cc b/deps/v8/src/mips/assembler-mips.cc
index 51642e05c3..f30f38bb75 100644
--- a/deps/v8/src/mips/assembler-mips.cc
+++ b/deps/v8/src/mips/assembler-mips.cc
@@ -49,11 +49,47 @@ bool CpuFeatures::initialized_ = false;
unsigned CpuFeatures::supported_ = 0;
unsigned CpuFeatures::found_by_runtime_probing_ = 0;
+
+// Get the CPU features enabled by the build. For cross compilation the
+// preprocessor symbols CAN_USE_FPU_INSTRUCTIONS
+// can be defined to enable FPU instructions when building the
+// snapshot.
+static uint64_t CpuFeaturesImpliedByCompiler() {
+ uint64_t answer = 0;
+#ifdef CAN_USE_FPU_INSTRUCTIONS
+ answer |= 1u << FPU;
+#endif // def CAN_USE_FPU_INSTRUCTIONS
+
+#ifdef __mips__
+ // If the compiler is allowed to use FPU then we can use FPU too in our code
+ // generation even when generating snapshots. This won't work for cross
+ // compilation.
+#if(defined(__mips_hard_float) && __mips_hard_float != 0)
+ answer |= 1u << FPU;
+#endif // defined(__mips_hard_float) && __mips_hard_float != 0
+#endif // def __mips__
+
+ return answer;
+}
+
+
void CpuFeatures::Probe() {
ASSERT(!initialized_);
#ifdef DEBUG
initialized_ = true;
#endif
+
+ // Get the features implied by the OS and the compiler settings. This is the
+ // minimal set of features which is also allowed for generated code in the
+ // snapshot.
+ supported_ |= OS::CpuFeaturesImpliedByPlatform();
+ supported_ |= CpuFeaturesImpliedByCompiler();
+
+ if (Serializer::enabled()) {
+ // No probing for features if we might serialize (generate snapshot).
+ return;
+ }
+
// If the compiler is allowed to use fpu then we can use fpu too in our
// code generation.
#if !defined(__mips__)
@@ -62,11 +98,7 @@ void CpuFeatures::Probe() {
supported_ |= 1u << FPU;
}
#else
- if (Serializer::enabled()) {
- supported_ |= OS::CpuFeaturesImpliedByPlatform();
- return; // No features if we might serialize.
- }
-
+ // Probe for additional features not already known to be available.
if (OS::MipsCpuHasFeature(FPU)) {
// This implementation also sets the FPU flags if
// runtime detection of FPU returns true.
@@ -780,10 +812,10 @@ void Assembler::bind(Label* L) {
void Assembler::next(Label* L) {
ASSERT(L->is_linked());
int link = target_at(L->pos());
- ASSERT(link > 0 || link == kEndOfChain);
if (link == kEndOfChain) {
L->Unuse();
- } else if (link > 0) {
+ } else {
+ ASSERT(link >= 0);
L->link_to(link);
}
}
diff --git a/deps/v8/src/mips/builtins-mips.cc b/deps/v8/src/mips/builtins-mips.cc
index 1555653f0a..d77230448f 100644
--- a/deps/v8/src/mips/builtins-mips.cc
+++ b/deps/v8/src/mips/builtins-mips.cc
@@ -210,7 +210,7 @@ static void AllocateJSArray(MacroAssembler* masm,
// Allocate the JSArray object together with space for a FixedArray with the
// requested number of elements.
__ bind(&not_empty);
- ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
+ STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
__ li(elements_array_end,
(JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize);
__ sra(scratch1, array_size, kSmiTagSize);
@@ -261,7 +261,7 @@ static void AllocateJSArray(MacroAssembler* masm,
// Length of the FixedArray is the number of pre-allocated elements if
// the actual JSArray has length 0 and the size of the JSArray for non-empty
// JSArrays. The length of a FixedArray is stored as a smi.
- ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTag == 0);
__ li(at, Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
__ movz(array_size, at, array_size);
@@ -273,7 +273,7 @@ static void AllocateJSArray(MacroAssembler* masm,
// result: JSObject
// elements_array_storage: elements array element storage
// array_size: smi-tagged size of elements array
- ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
+ STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
__ sll(elements_array_end, array_size, kPointerSizeLog2 - kSmiTagSize);
__ Addu(elements_array_end, elements_array_storage, elements_array_end);
@@ -336,14 +336,14 @@ static void ArrayNativeCode(MacroAssembler* masm,
__ bind(&argc_one_or_more);
__ Branch(&argc_two_or_more, ne, a0, Operand(1));
- ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTag == 0);
__ lw(a2, MemOperand(sp)); // Get the argument from the stack.
__ And(a3, a2, Operand(kIntptrSignBit | kSmiTagMask));
__ Branch(call_generic_code, eq, a3, Operand(zero_reg));
// Handle construction of an empty array of a certain size. Bail out if size
// is too large to actually allocate an elements array.
- ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTag == 0);
__ Branch(call_generic_code, Ugreater_equal, a2,
Operand(JSObject::kInitialMaxFastElementArray << kSmiTagSize));
@@ -576,7 +576,7 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
// Is it a String?
__ lw(a2, FieldMemOperand(a0, HeapObject::kMapOffset));
__ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset));
- ASSERT(kNotStringTag != 0);
+ STATIC_ASSERT(kNotStringTag != 0);
__ And(t0, a3, Operand(kIsNotStringMask));
__ Branch(&convert_argument, ne, t0, Operand(zero_reg));
__ mov(argument, a0);
diff --git a/deps/v8/src/mips/code-stubs-mips.cc b/deps/v8/src/mips/code-stubs-mips.cc
index 2526a6a28b..1d528946c3 100644
--- a/deps/v8/src/mips/code-stubs-mips.cc
+++ b/deps/v8/src/mips/code-stubs-mips.cc
@@ -3538,7 +3538,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
const int kNumInstructionsToJump = 6;
masm->Addu(ra, ra, kNumInstructionsToJump * kPointerSize);
masm->sw(ra, MemOperand(sp)); // This spot was reserved in EnterExitFrame.
- masm->Subu(sp, sp, StandardFrameConstants::kCArgsSlotsSize);
+ masm->Subu(sp, sp, kCArgsSlotsSize);
// Stack is still aligned.
// Call the C routine.
@@ -3551,7 +3551,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
}
// Restore stack (remove arg slots).
- __ Addu(sp, sp, StandardFrameConstants::kCArgsSlotsSize);
+ __ Addu(sp, sp, kCArgsSlotsSize);
if (always_allocate) {
// It's okay to clobber a2 and a3 here. v0 & v1 contain result.
@@ -3695,9 +3695,19 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
// Save callee saved registers on the stack.
__ MultiPush(kCalleeSaved | ra.bit());
+ if (CpuFeatures::IsSupported(FPU)) {
+ CpuFeatures::Scope scope(FPU);
+ // Save callee-saved FPU registers.
+ __ MultiPushFPU(kCalleeSavedFPU);
+ }
+
// Load argv in s0 register.
- __ lw(s0, MemOperand(sp, (kNumCalleeSaved + 1) * kPointerSize +
- StandardFrameConstants::kCArgsSlotsSize));
+ int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize;
+ if (CpuFeatures::IsSupported(FPU)) {
+ offset_to_argv += kNumCalleeSavedFPU * kDoubleSize;
+ }
+
+ __ lw(s0, MemOperand(sp, offset_to_argv + kCArgsSlotsSize));
// We build an EntryFrame.
__ li(t3, Operand(-1)); // Push a bad frame pointer to fail if it is used.
@@ -3829,6 +3839,12 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
// Reset the stack to the callee saved registers.
__ addiu(sp, sp, -EntryFrameConstants::kCallerFPOffset);
+ if (CpuFeatures::IsSupported(FPU)) {
+ CpuFeatures::Scope scope(FPU);
+ // Restore callee-saved fpu registers.
+ __ MultiPopFPU(kCalleeSavedFPU);
+ }
+
// Restore callee saved registers from the stack.
__ MultiPop(kCalleeSaved | ra.bit());
// Return.
@@ -4527,9 +4543,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
__ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
__ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
// First check for flat string.
- __ And(at, a0, Operand(kIsNotStringMask | kStringRepresentationMask));
+ __ And(a1, a0, Operand(kIsNotStringMask | kStringRepresentationMask));
STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
- __ Branch(&seq_string, eq, at, Operand(zero_reg));
+ __ Branch(&seq_string, eq, a1, Operand(zero_reg));
// subject: Subject string
// a0: instance type if Subject string
@@ -4541,10 +4557,10 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// a sequential string or an external string.
// In the case of a sliced string its offset has to be taken into account.
Label cons_string, check_encoding;
- STATIC_ASSERT((kConsStringTag < kExternalStringTag));
- STATIC_ASSERT((kSlicedStringTag > kExternalStringTag));
- __ Branch(&cons_string, lt, at, Operand(kExternalStringTag));
- __ Branch(&runtime, eq, at, Operand(kExternalStringTag));
+ STATIC_ASSERT(kConsStringTag < kExternalStringTag);
+ STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
+ __ Branch(&cons_string, lt, a1, Operand(kExternalStringTag));
+ __ Branch(&runtime, eq, a1, Operand(kExternalStringTag));
// String is sliced.
__ lw(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset));
@@ -4652,7 +4668,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// frame. Therefore we have to use fp, which points exactly to two pointer
// sizes below the previous sp. (Because creating a new stack frame pushes
// the previous fp onto the stack and moves up sp by 2 * kPointerSize.)
- __ lw(a0, MemOperand(fp, kSubjectOffset + 2 * kPointerSize));
+ __ lw(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize));
// If slice offset is not 0, load the length from the original sliced string.
// Argument 4, a3: End of string data
// Argument 3, a2: Start of string data
@@ -4662,7 +4678,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
__ sllv(t1, a1, a3);
__ addu(a2, t0, t1);
- __ lw(t2, FieldMemOperand(a0, String::kLengthOffset));
+ __ lw(t2, FieldMemOperand(subject, String::kLengthOffset));
__ sra(t2, t2, kSmiTagSize);
__ sllv(t1, t2, a3);
__ addu(a3, t0, t1);
@@ -4670,7 +4686,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// Already there
// Argument 1 (a0): Subject string.
- // Already there
+ __ mov(a0, subject);
// Locate the code entry and call it.
__ Addu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag));
@@ -4688,13 +4704,13 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
Label success;
__ Branch(&success, eq,
- subject, Operand(NativeRegExpMacroAssembler::SUCCESS));
+ v0, Operand(NativeRegExpMacroAssembler::SUCCESS));
Label failure;
__ Branch(&failure, eq,
- subject, Operand(NativeRegExpMacroAssembler::FAILURE));
+ v0, Operand(NativeRegExpMacroAssembler::FAILURE));
// If not exception it can only be retry. Handle that in the runtime system.
__ Branch(&runtime, ne,
- subject, Operand(NativeRegExpMacroAssembler::EXCEPTION));
+ v0, Operand(NativeRegExpMacroAssembler::EXCEPTION));
// Result must now be exception. If there is no pending exception already a
// stack overflow (on the backtrack stack) was detected in RegExp code but
// haven't created the exception yet. Handle that in the runtime system.
@@ -4705,16 +4721,16 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
__ li(a2, Operand(ExternalReference(Isolate::k_pending_exception_address,
masm->isolate())));
__ lw(v0, MemOperand(a2, 0));
- __ Branch(&runtime, eq, subject, Operand(a1));
+ __ Branch(&runtime, eq, v0, Operand(a1));
__ sw(a1, MemOperand(a2, 0)); // Clear pending exception.
// Check if the exception is a termination. If so, throw as uncatchable.
__ LoadRoot(a0, Heap::kTerminationExceptionRootIndex);
Label termination_exception;
- __ Branch(&termination_exception, eq, subject, Operand(a0));
+ __ Branch(&termination_exception, eq, v0, Operand(a0));
- __ Throw(subject); // Expects thrown value in v0.
+ __ Throw(v0); // Expects thrown value in v0.
__ bind(&termination_exception);
__ ThrowUncatchable(TERMINATION, v0); // Expects thrown value in v0.
@@ -5025,8 +5041,8 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
// Handle non-flat strings.
__ And(result_, result_, Operand(kStringRepresentationMask));
- STATIC_ASSERT((kConsStringTag < kExternalStringTag));
- STATIC_ASSERT((kSlicedStringTag > kExternalStringTag));
+ STATIC_ASSERT(kConsStringTag < kExternalStringTag);
+ STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
__ Branch(&sliced_string, gt, result_, Operand(kExternalStringTag));
__ Branch(&call_runtime_, eq, result_, Operand(kExternalStringTag));
@@ -5062,7 +5078,8 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
// Check for 1-byte or 2-byte string.
__ bind(&flat_string);
- STATIC_ASSERT(kAsciiStringTag != 0);
+ STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
+ STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
__ And(t0, result_, Operand(kStringEncodingMask));
__ Branch(&ascii_string, ne, t0, Operand(zero_reg));
@@ -5625,11 +5642,6 @@ void SubStringStub::Generate(MacroAssembler* masm) {
Register to = t2;
Register from = t3;
- if (FLAG_string_slices) {
- __ nop(); // Jumping as first instruction would crash the code generation.
- __ jmp(&sub_string_runtime);
- }
-
// Check bounds and smi-ness.
__ lw(to, MemOperand(sp, kToOffset));
__ lw(from, MemOperand(sp, kFromOffset));
@@ -5653,7 +5665,8 @@ void SubStringStub::Generate(MacroAssembler* masm) {
// Special handling of sub-strings of length 1 and 2. One character strings
// are handled in the runtime system (looked up in the single character
- // cache). Two character strings are looked for in the symbol cache.
+ // cache). Two character strings are looked for in the symbol cache in
+ // generated code.
__ Branch(&sub_string_runtime, lt, a2, Operand(2));
// Both to and from are smis.
@@ -5665,19 +5678,32 @@ void SubStringStub::Generate(MacroAssembler* masm) {
// t5: to index (untagged smi)
// Make sure first argument is a sequential (or flat) string.
- __ lw(t1, MemOperand(sp, kStringOffset));
- __ Branch(&sub_string_runtime, eq, t1, Operand(kSmiTagMask));
+ __ lw(v0, MemOperand(sp, kStringOffset));
+ __ Branch(&sub_string_runtime, eq, v0, Operand(kSmiTagMask));
- __ lw(a1, FieldMemOperand(t1, HeapObject::kMapOffset));
+ __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
__ lbu(a1, FieldMemOperand(a1, Map::kInstanceTypeOffset));
- __ And(t4, a1, Operand(kIsNotStringMask));
+ __ And(t4, v0, Operand(kIsNotStringMask));
__ Branch(&sub_string_runtime, ne, t4, Operand(zero_reg));
+ // Short-cut for the case of trivial substring.
+ Label return_v0;
+ // v0: original string
+ // a2: result string length
+ __ lw(t0, FieldMemOperand(v0, String::kLengthOffset));
+ __ sra(t0, t0, 1);
+ __ Branch(&return_v0, eq, a2, Operand(t0));
+
+ Label create_slice;
+ if (FLAG_string_slices) {
+ __ Branch(&create_slice, ge, a2, Operand(SlicedString::kMinLength));
+ }
+
+ // v0: original string
// a1: instance type
// a2: result string length
// a3: from index (untagged smi)
- // t1: string
// t2: (a.k.a. to): to (smi)
// t3: (a.k.a. from): from offset (smi)
// t5: to index (untagged smi)
@@ -5686,8 +5712,9 @@ void SubStringStub::Generate(MacroAssembler* masm) {
__ And(t0, a1, Operand(kStringRepresentationMask));
STATIC_ASSERT(kSeqStringTag < kConsStringTag);
STATIC_ASSERT(kConsStringTag < kExternalStringTag);
+ STATIC_ASSERT(kConsStringTag < kSlicedStringTag);
- // External strings go to runtime.
+ // Slices and external strings go to runtime.
__ Branch(&sub_string_runtime, gt, t0, Operand(kConsStringTag));
// Sequential strings are handled directly.
@@ -5696,32 +5723,32 @@ void SubStringStub::Generate(MacroAssembler* masm) {
// Cons string. Try to recurse (once) on the first substring.
// (This adds a little more generality than necessary to handle flattened
// cons strings, but not much).
- __ lw(t1, FieldMemOperand(t1, ConsString::kFirstOffset));
- __ lw(t0, FieldMemOperand(t1, HeapObject::kMapOffset));
+ __ lw(v0, FieldMemOperand(v0, ConsString::kFirstOffset));
+ __ lw(t0, FieldMemOperand(v0, HeapObject::kMapOffset));
__ lbu(a1, FieldMemOperand(t0, Map::kInstanceTypeOffset));
STATIC_ASSERT(kSeqStringTag == 0);
- // Cons and External strings go to runtime.
+ // Cons, slices and external strings go to runtime.
__ Branch(&sub_string_runtime, ne, a1, Operand(kStringRepresentationMask));
// Definitly a sequential string.
__ bind(&seq_string);
+ // v0: original string
// a1: instance type
// a2: result string length
// a3: from index (untagged smi)
- // t1: string
// t2: (a.k.a. to): to (smi)
// t3: (a.k.a. from): from offset (smi)
// t5: to index (untagged smi)
- __ lw(t0, FieldMemOperand(t1, String::kLengthOffset));
+ __ lw(t0, FieldMemOperand(v0, String::kLengthOffset));
__ Branch(&sub_string_runtime, lt, t0, Operand(to)); // Fail if to > length.
to = no_reg;
+ // v0: original string or left hand side of the original cons string.
// a1: instance type
// a2: result string length
// a3: from index (untagged smi)
- // t1: string
// t3: (a.k.a. from): from offset (smi)
// t5: to index (untagged smi)
@@ -5737,84 +5764,147 @@ void SubStringStub::Generate(MacroAssembler* masm) {
// Sub string of length 2 requested.
// Get the two characters forming the sub string.
- __ Addu(t1, t1, Operand(a3));
- __ lbu(a3, FieldMemOperand(t1, SeqAsciiString::kHeaderSize));
- __ lbu(t0, FieldMemOperand(t1, SeqAsciiString::kHeaderSize + 1));
+ __ Addu(v0, v0, Operand(a3));
+ __ lbu(a3, FieldMemOperand(v0, SeqAsciiString::kHeaderSize));
+ __ lbu(t0, FieldMemOperand(v0, SeqAsciiString::kHeaderSize + 1));
// Try to lookup two character string in symbol table.
Label make_two_character_string;
StringHelper::GenerateTwoCharacterSymbolTableProbe(
masm, a3, t0, a1, t1, t2, t3, t4, &make_two_character_string);
Counters* counters = masm->isolate()->counters();
- __ IncrementCounter(counters->sub_string_native(), 1, a3, t0);
- __ Addu(sp, sp, Operand(3 * kPointerSize));
- __ Ret();
-
+ __ jmp(&return_v0);
// a2: result string length.
// a3: two characters combined into halfword in little endian byte order.
__ bind(&make_two_character_string);
__ AllocateAsciiString(v0, a2, t0, t1, t4, &sub_string_runtime);
__ sh(a3, FieldMemOperand(v0, SeqAsciiString::kHeaderSize));
- __ IncrementCounter(counters->sub_string_native(), 1, a3, t0);
- __ Addu(sp, sp, Operand(3 * kPointerSize));
- __ Ret();
+ __ jmp(&return_v0);
__ bind(&result_longer_than_two);
+ // Locate 'from' character of string.
+ __ Addu(t1, v0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
+ __ sra(t4, from, 1);
+ __ Addu(t1, t1, t4);
+
// Allocate the result.
__ AllocateAsciiString(v0, a2, t4, t0, a1, &sub_string_runtime);
- // v0: result string.
- // a2: result string length.
+ // v0: result string
+ // a2: result string length
// a3: from index (untagged smi)
- // t1: string.
+ // t1: first character of substring to copy
// t3: (a.k.a. from): from offset (smi)
// Locate first character of result.
__ Addu(a1, v0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
- // Locate 'from' character of string.
- __ Addu(t1, t1, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
- __ Addu(t1, t1, Operand(a3));
- // v0: result string.
- // a1: first character of result string.
- // a2: result string length.
- // t1: first character of sub string to copy.
+ // v0: result string
+ // a1: first character of result string
+ // a2: result string length
+ // t1: first character of substring to copy
STATIC_ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0);
StringHelper::GenerateCopyCharactersLong(
masm, a1, t1, a2, a3, t0, t2, t3, t4, COPY_ASCII | DEST_ALWAYS_ALIGNED);
- __ IncrementCounter(counters->sub_string_native(), 1, a3, t0);
- __ Addu(sp, sp, Operand(3 * kPointerSize));
- __ Ret();
+ __ jmp(&return_v0);
__ bind(&non_ascii_flat);
- // a2: result string length.
- // t1: string.
+ // a2: result string length
+ // t1: string
// t3: (a.k.a. from): from offset (smi)
// Check for flat two byte string.
+ // Locate 'from' character of string.
+ __ Addu(t1, v0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
+ // As "from" is a smi it is 2 times the value which matches the size of a two
+ // byte character.
+ STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
+ __ Addu(t1, t1, Operand(from));
+
// Allocate the result.
__ AllocateTwoByteString(v0, a2, a1, a3, t0, &sub_string_runtime);
- // v0: result string.
- // a2: result string length.
- // t1: string.
+ // v0: result string
+ // a2: result string length
+ // t1: first character of substring to copy
// Locate first character of result.
__ Addu(a1, v0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
- // Locate 'from' character of string.
- __ Addu(t1, t1, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
- // As "from" is a smi it is 2 times the value which matches the size of a two
- // byte character.
- __ Addu(t1, t1, Operand(from));
+
from = no_reg;
// v0: result string.
// a1: first character of result.
// a2: result length.
- // t1: first character of string to copy.
+ // t1: first character of substring to copy.
STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
StringHelper::GenerateCopyCharactersLong(
masm, a1, t1, a2, a3, t0, t2, t3, t4, DEST_ALWAYS_ALIGNED);
+ __ jmp(&return_v0);
+
+ if (FLAG_string_slices) {
+ __ bind(&create_slice);
+ // v0: original string
+ // a1: instance type
+ // a2: length
+ // a3: from index (untagged smi)
+ // t2 (a.k.a. to): to (smi)
+ // t3 (a.k.a. from): from offset (smi)
+ Label allocate_slice, sliced_string, seq_string;
+ STATIC_ASSERT(kSeqStringTag == 0);
+ __ And(t4, a1, Operand(kStringRepresentationMask));
+ __ Branch(&seq_string, eq, t4, Operand(zero_reg));
+ STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
+ STATIC_ASSERT(kIsIndirectStringMask != 0);
+ __ And(t4, a1, Operand(kIsIndirectStringMask));
+ // External string. Jump to runtime.
+ __ Branch(&sub_string_runtime, eq, t4, Operand(zero_reg));
+
+ __ And(t4, a1, Operand(kSlicedNotConsMask));
+ __ Branch(&sliced_string, ne, t4, Operand(zero_reg));
+ // Cons string. Check whether it is flat, then fetch first part.
+ __ lw(t1, FieldMemOperand(v0, ConsString::kSecondOffset));
+ __ LoadRoot(t5, Heap::kEmptyStringRootIndex);
+ __ Branch(&sub_string_runtime, ne, t1, Operand(t5));
+ __ lw(t1, FieldMemOperand(v0, ConsString::kFirstOffset));
+ __ jmp(&allocate_slice);
+
+ __ bind(&sliced_string);
+ // Sliced string. Fetch parent and correct start index by offset.
+ __ lw(t1, FieldMemOperand(v0, SlicedString::kOffsetOffset));
+ __ addu(t3, t3, t1);
+ __ lw(t1, FieldMemOperand(v0, SlicedString::kParentOffset));
+ __ jmp(&allocate_slice);
+
+ __ bind(&seq_string);
+ // Sequential string. Just move string to the right register.
+ __ mov(t1, v0);
+
+ __ bind(&allocate_slice);
+ // a1: instance type of original string
+ // a2: length
+ // t1: underlying subject string
+ // t3 (a.k.a. from): from offset (smi)
+ // Allocate new sliced string. At this point we do not reload the instance
+ // type including the string encoding because we simply rely on the info
+ // provided by the original string. It does not matter if the original
+ // string's encoding is wrong because we always have to recheck encoding of
+ // the newly created string's parent anyways due to externalized strings.
+ Label two_byte_slice, set_slice_header;
+ STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
+ STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
+ __ And(t4, a1, Operand(kStringEncodingMask));
+ __ Branch(&two_byte_slice, eq, t4, Operand(zero_reg));
+ __ AllocateAsciiSlicedString(v0, a2, a3, t0, &sub_string_runtime);
+ __ jmp(&set_slice_header);
+ __ bind(&two_byte_slice);
+ __ AllocateTwoByteSlicedString(v0, a2, a3, t0, &sub_string_runtime);
+ __ bind(&set_slice_header);
+ __ sw(t3, FieldMemOperand(v0, SlicedString::kOffsetOffset));
+ __ sw(t1, FieldMemOperand(v0, SlicedString::kParentOffset));
+ }
+
+ __ bind(&return_v0);
__ IncrementCounter(counters->sub_string_native(), 1, a3, t0);
__ Addu(sp, sp, Operand(3 * kPointerSize));
__ Ret();
diff --git a/deps/v8/src/mips/constants-mips.h b/deps/v8/src/mips/constants-mips.h
index 6bf2570ebd..ede9688a68 100644
--- a/deps/v8/src/mips/constants-mips.h
+++ b/deps/v8/src/mips/constants-mips.h
@@ -743,11 +743,9 @@ class Instruction {
// -----------------------------------------------------------------------------
// MIPS assembly various constants.
-
-static const int kArgsSlotsSize = 4 * Instruction::kInstrSize;
-static const int kArgsSlotsNum = 4;
// C/C++ argument slots size.
-static const int kCArgsSlotsSize = 4 * Instruction::kInstrSize;
+static const int kCArgSlotCount = 4;
+static const int kCArgsSlotsSize = kCArgSlotCount * Instruction::kInstrSize;
// JS argument slots size.
static const int kJSArgsSlotsSize = 0 * Instruction::kInstrSize;
// Assembly builtins argument slots size.
diff --git a/deps/v8/src/mips/frames-mips.h b/deps/v8/src/mips/frames-mips.h
index 1899843a19..798ef23b2e 100644
--- a/deps/v8/src/mips/frames-mips.h
+++ b/deps/v8/src/mips/frames-mips.h
@@ -30,7 +30,6 @@
#ifndef V8_MIPS_FRAMES_MIPS_H_
#define V8_MIPS_FRAMES_MIPS_H_
-
namespace v8 {
namespace internal {
@@ -40,13 +39,22 @@ namespace internal {
static const int kNumRegs = 32;
static const RegList kJSCallerSaved =
- 1 << 2 | // v0
- 1 << 4 | // a0
- 1 << 5 | // a1
- 1 << 6 | // a2
- 1 << 7; // a3
-
-static const int kNumJSCallerSaved = 5;
+ 1 << 2 | // v0
+ 1 << 3 | // v1
+ 1 << 4 | // a0
+ 1 << 5 | // a1
+ 1 << 6 | // a2
+ 1 << 7 | // a3
+ 1 << 8 | // t0
+ 1 << 9 | // t1
+ 1 << 10 | // t2
+ 1 << 11 | // t3
+ 1 << 12 | // t4
+ 1 << 13 | // t5
+ 1 << 14 | // t6
+ 1 << 15; // t7
+
+static const int kNumJSCallerSaved = 14;
// Return the code of the n-th caller-saved register available to JavaScript
@@ -56,19 +64,31 @@ int JSCallerSavedCode(int n);
// Callee-saved registers preserved when switching from C to JavaScript.
static const RegList kCalleeSaved =
- // Saved temporaries.
- 1 << 16 | 1 << 17 | 1 << 18 | 1 << 19 |
- 1 << 20 | 1 << 21 | 1 << 22 | 1 << 23 |
- // fp.
- 1 << 30;
+ 1 << 16 | // s0
+ 1 << 17 | // s1
+ 1 << 18 | // s2
+ 1 << 19 | // s3
+ 1 << 20 | // s4
+ 1 << 21 | // s5
+ 1 << 22 | // s6 (roots in Javascript code)
+ 1 << 23 | // s7 (cp in Javascript code)
+ 1 << 30; // fp/s8
static const int kNumCalleeSaved = 9;
+static const RegList kCalleeSavedFPU =
+ 1 << 20 | // f20
+ 1 << 22 | // f22
+ 1 << 24 | // f24
+ 1 << 26 | // f26
+ 1 << 28 | // f28
+ 1 << 30; // f30
+static const int kNumCalleeSavedFPU = 6;
// Number of registers for which space is reserved in safepoints. Must be a
// multiple of 8.
// TODO(mips): Only 8 registers may actually be sufficient. Revisit.
-static const int kNumSafepointRegisters = 16;
+static const int kNumSafepointRegisters = 24;
// Define the list of registers actually saved at safepoints.
// Note that the number of saved registers may be smaller than the reserved
@@ -82,37 +102,37 @@ typedef Object* JSCallerSavedBuffer[kNumJSCallerSaved];
static const int kUndefIndex = -1;
// Map with indexes on stack that corresponds to codes of saved registers.
static const int kSafepointRegisterStackIndexMap[kNumRegs] = {
- kUndefIndex,
- kUndefIndex,
- 0, // v0
- kUndefIndex,
- 1, // a0
- 2, // a1
- 3, // a2
- 4, // a3
- kUndefIndex,
- kUndefIndex,
- kUndefIndex,
- kUndefIndex,
- kUndefIndex,
- kUndefIndex,
- kUndefIndex,
- kUndefIndex,
- 5, // Saved temporaries.
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- kUndefIndex,
- kUndefIndex,
- kUndefIndex,
- kUndefIndex,
- 13, // gp
- 14, // sp
- 15, // fp
+ kUndefIndex, // zero_reg
+ kUndefIndex, // at
+ 0, // v0
+ 1, // v1
+ 2, // a0
+ 3, // a1
+ 4, // a2
+ 5, // a3
+ 6, // t0
+ 7, // t1
+ 8, // t2
+ 9, // t3
+ 10, // t4
+ 11, // t5
+ 12, // t6
+ 13, // t7
+ 14, // s0
+ 15, // s1
+ 16, // s2
+ 17, // s3
+ 18, // s4
+ 19, // s5
+ 20, // s6
+ 21, // s7
+ kUndefIndex, // t8
+ kUndefIndex, // t9
+ kUndefIndex, // k0
+ kUndefIndex, // k1
+ kUndefIndex, // gp
+ kUndefIndex, // sp
+ 22, // fp
kUndefIndex
};
@@ -174,9 +194,6 @@ class StandardFrameConstants : public AllStatic {
static const int kRArgsSlotsSize = 4 * kPointerSize;
static const int kRegularArgsSlotsSize = kRArgsSlotsSize;
- // C/C++ argument slots size.
- static const int kCArgSlotCount = 4;
- static const int kCArgsSlotsSize = kCArgSlotCount * kPointerSize;
// JS argument slots size.
static const int kJSArgsSlotsSize = 0 * kPointerSize;
// Assembly builtins argument slots size.
diff --git a/deps/v8/src/mips/full-codegen-mips.cc b/deps/v8/src/mips/full-codegen-mips.cc
index cf48ccfd4f..385e57ae66 100644
--- a/deps/v8/src/mips/full-codegen-mips.cc
+++ b/deps/v8/src/mips/full-codegen-mips.cc
@@ -200,7 +200,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
// Copy any necessary parameters into the context.
int num_parameters = info->scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) {
- Slot* slot = scope()->parameter(i)->AsSlot();
+ Slot* slot = scope()->parameter(i)->rewrite();
if (slot != NULL && slot->type() == Slot::CONTEXT) {
int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(num_parameters - 1 - i) * kPointerSize;
@@ -252,7 +252,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
ArgumentsAccessStub stub(type);
__ CallStub(&stub);
- Move(arguments->AsSlot(), v0, a1, a2);
+ Move(arguments->rewrite(), v0, a1, a2);
}
if (FLAG_trace) {
@@ -266,6 +266,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
scope()->VisitIllegalRedeclaration(this);
} else {
+ PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
{ Comment cmnt(masm_, "[ Declarations");
// For named function expressions, declare the function name as a
// constant.
@@ -276,7 +277,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
}
{ Comment cmnt(masm_, "[ Stack check");
- PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
+ PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS);
Label ok;
__ LoadRoot(t0, Heap::kStackLimitRootIndex);
__ Branch(&ok, hs, sp, Operand(t0));
@@ -632,6 +633,7 @@ MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
return ContextOperand(scratch, slot->index());
}
case Slot::LOOKUP:
+ case Slot::GLOBAL:
UNREACHABLE();
}
UNREACHABLE();
@@ -690,22 +692,23 @@ void FullCodeGenerator::Move(Slot* dst,
}
-void FullCodeGenerator::EmitDeclaration(Variable* variable,
+void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
Variable::Mode mode,
FunctionLiteral* function) {
Comment cmnt(masm_, "[ Declaration");
+ Variable* variable = proxy->var();
ASSERT(variable != NULL); // Must have been resolved.
- Slot* slot = variable->AsSlot();
+ Slot* slot = variable->rewrite();
ASSERT(slot != NULL);
switch (slot->type()) {
case Slot::PARAMETER:
case Slot::LOCAL:
- if (mode == Variable::CONST) {
- __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
- __ sw(t0, MemOperand(fp, SlotOffset(slot)));
- } else if (function != NULL) {
+ if (function != NULL) {
VisitForAccumulatorValue(function);
__ sw(result_register(), MemOperand(fp, SlotOffset(slot)));
+ } else if (mode == Variable::CONST || mode == Variable::LET) {
+ __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
+ __ sw(t0, MemOperand(fp, SlotOffset(slot)));
}
break;
@@ -726,17 +729,19 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
__ Check(ne, "Declaration in catch context.",
a1, Operand(t0));
}
- if (mode == Variable::CONST) {
- __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
- __ sw(at, ContextOperand(cp, slot->index()));
- // No write barrier since the_hole_value is in old space.
- } else if (function != NULL) {
+ if (function != NULL) {
VisitForAccumulatorValue(function);
__ sw(result_register(), ContextOperand(cp, slot->index()));
int offset = Context::SlotOffset(slot->index());
// We know that we have written a function, which is not a smi.
__ mov(a1, cp);
__ RecordWrite(a1, Operand(offset), a2, result_register());
+ PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+ } else if (mode == Variable::CONST || mode == Variable::LET) {
+ __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
+ __ sw(at, ContextOperand(cp, slot->index()));
+ // No write barrier since the_hole_value is in old space.
+ PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
}
break;
@@ -752,13 +757,13 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
// Note: For variables we must not push an initial value (such as
// 'undefined') because we may have a (legal) redeclaration and we
// must not destroy the current value.
- if (mode == Variable::CONST) {
- __ LoadRoot(a0, Heap::kTheHoleValueRootIndex);
- __ Push(cp, a2, a1, a0);
- } else if (function != NULL) {
+ if (function != NULL) {
__ Push(cp, a2, a1);
// Push initial value for function declaration.
VisitForStackValue(function);
+ } else if (mode == Variable::CONST || mode == Variable::LET) {
+ __ LoadRoot(a0, Heap::kTheHoleValueRootIndex);
+ __ Push(cp, a2, a1, a0);
} else {
ASSERT(Smi::FromInt(0) == 0);
// No initial value!
@@ -768,23 +773,25 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
__ CallRuntime(Runtime::kDeclareContextSlot, 4);
break;
}
+
+ case Slot::GLOBAL:
+ UNREACHABLE();
}
}
void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
- EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
+ EmitDeclaration(decl->proxy(), decl->mode(), decl->fun());
}
void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals.
// The context is the first argument.
- __ li(a2, Operand(pairs));
- __ li(a1, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
- __ li(a0, Operand(Smi::FromInt(strict_mode_flag())));
- __ Push(cp, a2, a1, a0);
- __ CallRuntime(Runtime::kDeclareGlobals, 4);
+ __ li(a1, Operand(pairs));
+ __ li(a0, Operand(Smi::FromInt(DeclareGlobalsFlags())));
+ __ Push(cp, a1, a0);
+ __ CallRuntime(Runtime::kDeclareGlobals, 3);
// Return value is ignored.
}
@@ -1189,7 +1196,7 @@ void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow);
__ Branch(done);
} else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
- Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot();
+ Slot* potential_slot = slot->var()->local_if_not_shadowed()->rewrite();
Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
if (potential_slot != NULL) {
// Generate fast case for locals that rewrite to slots.
@@ -1215,7 +1222,7 @@ void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
// variables. Then load the argument from the arguments
// object using keyed load.
__ lw(a1,
- ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(),
+ ContextSlotOperandCheckExtensions(obj_proxy->var()->rewrite(),
slow));
__ li(a0, Operand(key_literal->handle()));
Handle<Code> ic =
@@ -1236,7 +1243,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
// Three cases: non-this global variables, lookup slots, and all other
// types of slots.
- Slot* slot = var->AsSlot();
+ Slot* slot = var->rewrite();
ASSERT((var->is_global() && !var->is_this()) == (slot == NULL));
if (slot == NULL) {
@@ -1279,9 +1286,22 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
__ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
__ movz(v0, a0, at); // Conditional move.
context()->Plug(v0);
- } else {
- context()->Plug(slot);
- }
+ } else if (var->mode() == Variable::LET) {
+ // Let bindings may be the hole value if they have not been initialized.
+ // Throw a type error in this case.
+ Label done;
+ MemOperand slot_operand = EmitSlotSearch(slot, a0);
+ __ lw(v0, slot_operand);
+ __ LoadRoot(a1, Heap::kTheHoleValueRootIndex);
+ __ Branch(&done, ne, v0, Operand(a1));
+ __ li(v0, Operand(var->name()));
+ __ push(v0);
+ __ CallRuntime(Runtime::kThrowReferenceError, 1);
+ __ bind(&done);
+ context()->Plug(v0);
+ } else {
+ context()->Plug(slot);
+ }
}
}
@@ -1500,9 +1520,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
// Update the write barrier for the array store with v0 as the scratch
// register.
- __ li(a2, Operand(offset));
- // TODO(PJ): double check this RecordWrite call.
- __ RecordWrite(a1, a2, result_register());
+ __ RecordWrite(a1, Operand(offset), a2, result_register());
PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
}
@@ -1822,7 +1840,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
void FullCodeGenerator::EmitVariableAssignment(Variable* var,
Token::Value op) {
ASSERT(var != NULL);
- ASSERT(var->is_global() || var->AsSlot() != NULL);
+ ASSERT(var->is_global() || var->rewrite() != NULL);
if (var->is_global()) {
ASSERT(!var->is_this());
@@ -1842,7 +1860,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
// scope. However, unlike var initializers, const initializers are able
// to drill a hole to that function context, even from inside a 'with'
// context. We thus bypass the normal static scope lookup.
- Slot* slot = var->AsSlot();
+ Slot* slot = var->rewrite();
Label skip;
switch (slot->type()) {
case Slot::PARAMETER:
@@ -1863,13 +1881,65 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
__ Push(cp, a0); // Context and name.
__ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
break;
+ case Slot::GLOBAL:
+ UNREACHABLE();
}
__ bind(&skip);
+ } else if (var->mode() == Variable::LET && op != Token::INIT_LET) {
+ // Perform the assignment for non-const variables. Const assignments
+ // are simply skipped.
+ Slot* slot = var->AsSlot();
+ switch (slot->type()) {
+ case Slot::PARAMETER:
+ case Slot::LOCAL: {
+ Label assign;
+ // Check for an initialized let binding.
+ __ lw(a1, MemOperand(fp, SlotOffset(slot)));
+ __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
+ __ Branch(&assign, ne, a1, Operand(t0));
+ __ li(a1, Operand(var->name()));
+ __ push(a1);
+ __ CallRuntime(Runtime::kThrowReferenceError, 1);
+ // Perform the assignment.
+ __ bind(&assign);
+ __ sw(result_register(), MemOperand(fp, SlotOffset(slot)));
+ break;
+ }
+ case Slot::CONTEXT: {
+ // Let variables may be the hole value if they have not been
+ // initialized. Throw a type error in this case.
+ Label assign;
+ MemOperand target = EmitSlotSearch(slot, a1);
+ // Check for an initialized let binding.
+ __ lw(a3, target);
+ __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
+ __ Branch(&assign, ne, a3, Operand(t0));
+ __ li(a3, Operand(var->name()));
+ __ push(a3);
+ __ CallRuntime(Runtime::kThrowReferenceError, 1);
+ // Perform the assignment.
+ __ bind(&assign);
+ __ sw(result_register(), target);
+ // RecordWrite may destroy all its register arguments.
+ __ mov(a3, result_register());
+ int offset = Context::SlotOffset(slot->index());
+ __ RecordWrite(a1, Operand(offset), a2, a3);
+ break;
+ }
+ case Slot::LOOKUP:
+ // Call the runtime for the assignment.
+ __ push(v0); // Value.
+ __ li(a1, Operand(slot->var()->name()));
+ __ li(a0, Operand(Smi::FromInt(strict_mode_flag())));
+ __ Push(cp, a1, a0); // Context, name, strict mode.
+ __ CallRuntime(Runtime::kStoreContextSlot, 4);
+ break;
+ }
} else if (var->mode() != Variable::CONST) {
// Perform the assignment for non-const variables. Const assignments
// are simply skipped.
- Slot* slot = var->AsSlot();
+ Slot* slot = var->rewrite();
switch (slot->type()) {
case Slot::PARAMETER:
case Slot::LOCAL:
@@ -1896,6 +1966,9 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
__ Push(cp, a1, a0); // Context, name, strict mode.
__ CallRuntime(Runtime::kStoreContextSlot, 4);
break;
+
+ case Slot::GLOBAL:
+ UNREACHABLE();
}
}
}
@@ -2115,8 +2188,13 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
int receiver_offset = 2 + info_->scope()->num_parameters();
__ lw(a1, MemOperand(fp, receiver_offset * kPointerSize));
__ push(a1);
- // Push the strict mode flag.
- __ li(a1, Operand(Smi::FromInt(strict_mode_flag())));
+ // Push the strict mode flag. In harmony mode every eval call
+ // is a strict mode eval call.
+ StrictModeFlag strict_mode = strict_mode_flag();
+ if (FLAG_harmony_block_scoping) {
+ strict_mode = kStrictMode;
+ }
+ __ li(a1, Operand(Smi::FromInt(strict_mode)));
__ push(a1);
__ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
@@ -2158,9 +2236,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
// in generated code. If we succeed, there is no need to perform a
// context lookup in the runtime system.
Label done;
- if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) {
+ if (var->rewrite() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) {
Label slow;
- EmitLoadGlobalSlotCheckExtensions(var->AsSlot(),
+ EmitLoadGlobalSlotCheckExtensions(var->rewrite(),
NOT_INSIDE_TYPEOF,
&slow);
// Push the function and resolve eval.
@@ -2198,15 +2276,15 @@ void FullCodeGenerator::VisitCall(Call* expr) {
__ lw(a0, GlobalObjectOperand());
__ push(a0);
EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
- } else if (var != NULL && var->AsSlot() != NULL &&
- var->AsSlot()->type() == Slot::LOOKUP) {
+ } else if (var != NULL && var->rewrite() != NULL &&
+ var->rewrite()->type() == Slot::LOOKUP) {
// Call to a lookup slot (dynamically introduced variable).
Label slow, done;
{ PreservePositionScope scope(masm()->positions_recorder());
// Generate code for loading from variables potentially shadowed
// by eval-introduced variables.
- EmitDynamicLoadFromSlotFastCase(var->AsSlot(),
+ EmitDynamicLoadFromSlotFastCase(var->rewrite(),
NOT_INSIDE_TYPEOF,
&slow,
&done);
@@ -3208,7 +3286,7 @@ void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
Label done, not_found;
- ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
+ STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
__ lw(a2, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset));
// a2 now holds finger offset as a smi.
__ Addu(a3, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
@@ -3611,8 +3689,8 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
__ Push(a2, a1, a0);
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(v0);
- } else if (var->AsSlot() != NULL &&
- var->AsSlot()->type() != Slot::LOOKUP) {
+ } else if (var->rewrite() != NULL &&
+ var->rewrite()->type() != Slot::LOOKUP) {
// Result of deleting non-global, non-dynamic variables is false.
// The subexpression does not have side effects.
context()->Plug(false);
@@ -3902,13 +3980,13 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
PrepareForBailout(expr, TOS_REG);
context()->Plug(v0);
} else if (proxy != NULL &&
- proxy->var()->AsSlot() != NULL &&
- proxy->var()->AsSlot()->type() == Slot::LOOKUP) {
+ proxy->var()->rewrite() != NULL &&
+ proxy->var()->rewrite()->type() == Slot::LOOKUP) {
Label done, slow;
// Generate code for loading from variables potentially shadowed
// by eval-introduced variables.
- Slot* slot = proxy->var()->AsSlot();
+ Slot* slot = proxy->var()->rewrite();
EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done);
__ bind(&slow);
@@ -4203,7 +4281,7 @@ void FullCodeGenerator::EnterFinallyBlock() {
// Cook return address in link register to stack (smi encoded Code* delta).
__ Subu(a1, ra, Operand(masm_->CodeObject()));
ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
- ASSERT_EQ(0, kSmiTag);
+ STATIC_ASSERT(0 == kSmiTag);
__ Addu(a1, a1, Operand(a1)); // Convert to smi.
__ push(a1);
}
@@ -4224,6 +4302,34 @@ void FullCodeGenerator::ExitFinallyBlock() {
#undef __
+#define __ ACCESS_MASM(masm())
+
+FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
+ int* stack_depth,
+ int* context_length) {
+ // The macros used here must preserve the result register.
+
+ // Because the handler block contains the context of the finally
+ // code, we can restore it directly from there for the finally code
+ // rather than iteratively unwinding contexts via their previous
+ // links.
+ __ Drop(*stack_depth); // Down to the handler block.
+ if (*context_length > 0) {
+ // Restore the context to its dedicated register and the stack.
+ __ lw(cp, MemOperand(sp, StackHandlerConstants::kContextOffset));
+ __ sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+ }
+ __ PopTryHandler();
+ __ Call(finally_entry_);
+
+ *stack_depth = 0;
+ *context_length = 0;
+ return previous_;
+}
+
+
+#undef __
+
} } // namespace v8::internal
#endif // V8_TARGET_ARCH_MIPS
diff --git a/deps/v8/src/mips/ic-mips.cc b/deps/v8/src/mips/ic-mips.cc
index 85cb916488..5ef35548d6 100644
--- a/deps/v8/src/mips/ic-mips.cc
+++ b/deps/v8/src/mips/ic-mips.cc
@@ -338,7 +338,7 @@ static void GenerateFastArrayLoad(MacroAssembler* masm,
__ Addu(scratch1, elements,
Operand(FixedArray::kHeaderSize - kHeapObjectTag));
// The key is a smi.
- ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
+ STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
__ sll(at, key, kPointerSizeLog2 - kSmiTagSize);
__ addu(at, at, scratch1);
__ lw(scratch2, MemOperand(at));
@@ -372,7 +372,7 @@ static void GenerateKeyStringCheck(MacroAssembler* masm,
// Is the string a symbol?
// map: key map
__ lbu(hash, FieldMemOperand(map, Map::kInstanceTypeOffset));
- ASSERT(kSymbolTag != 0);
+ STATIC_ASSERT(kSymbolTag != 0);
__ And(at, hash, Operand(kIsSymbolMask));
__ Branch(not_symbol, eq, at, Operand(zero_reg));
}
@@ -1269,7 +1269,7 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
__ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset));
__ Branch(&slow, hs, key, Operand(t0));
// Calculate key + 1 as smi.
- ASSERT_EQ(0, kSmiTag);
+ STATIC_ASSERT(0 == kSmiTag);
__ Addu(t3, key, Operand(Smi::FromInt(1)));
__ sw(t3, FieldMemOperand(receiver, JSArray::kLengthOffset));
__ Branch(&fast);
diff --git a/deps/v8/src/mips/macro-assembler-mips.cc b/deps/v8/src/mips/macro-assembler-mips.cc
index 8e4b8ef973..1a37d65927 100644
--- a/deps/v8/src/mips/macro-assembler-mips.cc
+++ b/deps/v8/src/mips/macro-assembler-mips.cc
@@ -703,52 +703,114 @@ void MacroAssembler::li(Register rd, Operand j, bool gen2instr) {
void MacroAssembler::MultiPush(RegList regs) {
- int16_t NumSaved = 0;
- int16_t NumToPush = NumberOfBitsSet(regs);
+ int16_t num_to_push = NumberOfBitsSet(regs);
+ int16_t stack_offset = num_to_push * kPointerSize;
- addiu(sp, sp, -4 * NumToPush);
+ Subu(sp, sp, Operand(stack_offset));
for (int16_t i = kNumRegisters; i > 0; i--) {
if ((regs & (1 << i)) != 0) {
- sw(ToRegister(i), MemOperand(sp, 4 * (NumToPush - ++NumSaved)));
+ stack_offset -= kPointerSize;
+ sw(ToRegister(i), MemOperand(sp, stack_offset));
}
}
}
void MacroAssembler::MultiPushReversed(RegList regs) {
- int16_t NumSaved = 0;
- int16_t NumToPush = NumberOfBitsSet(regs);
+ int16_t num_to_push = NumberOfBitsSet(regs);
+ int16_t stack_offset = num_to_push * kPointerSize;
- addiu(sp, sp, -4 * NumToPush);
+ Subu(sp, sp, Operand(stack_offset));
for (int16_t i = 0; i < kNumRegisters; i++) {
if ((regs & (1 << i)) != 0) {
- sw(ToRegister(i), MemOperand(sp, 4 * (NumToPush - ++NumSaved)));
+ stack_offset -= kPointerSize;
+ sw(ToRegister(i), MemOperand(sp, stack_offset));
}
}
}
void MacroAssembler::MultiPop(RegList regs) {
- int16_t NumSaved = 0;
+ int16_t stack_offset = 0;
for (int16_t i = 0; i < kNumRegisters; i++) {
if ((regs & (1 << i)) != 0) {
- lw(ToRegister(i), MemOperand(sp, 4 * (NumSaved++)));
+ lw(ToRegister(i), MemOperand(sp, stack_offset));
+ stack_offset += kPointerSize;
}
}
- addiu(sp, sp, 4 * NumSaved);
+ addiu(sp, sp, stack_offset);
}
void MacroAssembler::MultiPopReversed(RegList regs) {
- int16_t NumSaved = 0;
+ int16_t stack_offset = 0;
for (int16_t i = kNumRegisters; i > 0; i--) {
if ((regs & (1 << i)) != 0) {
- lw(ToRegister(i), MemOperand(sp, 4 * (NumSaved++)));
+ lw(ToRegister(i), MemOperand(sp, stack_offset));
+ stack_offset += kPointerSize;
}
}
- addiu(sp, sp, 4 * NumSaved);
+ addiu(sp, sp, stack_offset);
+}
+
+
+void MacroAssembler::MultiPushFPU(RegList regs) {
+ CpuFeatures::Scope scope(FPU);
+ int16_t num_to_push = NumberOfBitsSet(regs);
+ int16_t stack_offset = num_to_push * kDoubleSize;
+
+ Subu(sp, sp, Operand(stack_offset));
+ for (int16_t i = kNumRegisters; i > 0; i--) {
+ if ((regs & (1 << i)) != 0) {
+ stack_offset -= kDoubleSize;
+ sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
+ }
+ }
+}
+
+
+void MacroAssembler::MultiPushReversedFPU(RegList regs) {
+ CpuFeatures::Scope scope(FPU);
+ int16_t num_to_push = NumberOfBitsSet(regs);
+ int16_t stack_offset = num_to_push * kDoubleSize;
+
+ Subu(sp, sp, Operand(stack_offset));
+ for (int16_t i = 0; i < kNumRegisters; i++) {
+ if ((regs & (1 << i)) != 0) {
+ stack_offset -= kDoubleSize;
+ sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
+ }
+ }
+}
+
+
+void MacroAssembler::MultiPopFPU(RegList regs) {
+ CpuFeatures::Scope scope(FPU);
+ int16_t stack_offset = 0;
+
+ for (int16_t i = 0; i < kNumRegisters; i++) {
+ if ((regs & (1 << i)) != 0) {
+ ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
+ stack_offset += kDoubleSize;
+ }
+ }
+ addiu(sp, sp, stack_offset);
+}
+
+
+void MacroAssembler::MultiPopReversedFPU(RegList regs) {
+ CpuFeatures::Scope scope(FPU);
+ int16_t stack_offset = 0;
+
+ for (int16_t i = kNumRegisters; i > 0; i--) {
+ if ((regs & (1 << i)) != 0) {
+ ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
+ stack_offset += kDoubleSize;
+ }
+ }
+ addiu(sp, sp, stack_offset);
}
@@ -1557,12 +1619,14 @@ void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs,
b(offset);
break;
case eq:
+ ASSERT(!scratch.is(rs));
r2 = scratch;
li(r2, rt);
offset = shifted_branch_offset(L, false);
beq(rs, r2, offset);
break;
case ne:
+ ASSERT(!scratch.is(rs));
r2 = scratch;
li(r2, rt);
offset = shifted_branch_offset(L, false);
@@ -1574,6 +1638,7 @@ void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs,
offset = shifted_branch_offset(L, false);
bgtz(rs, offset);
} else {
+ ASSERT(!scratch.is(rs));
r2 = scratch;
li(r2, rt);
slt(scratch, r2, rs);
@@ -1590,6 +1655,7 @@ void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs,
offset = shifted_branch_offset(L, false);
beq(scratch, zero_reg, offset);
} else {
+ ASSERT(!scratch.is(rs));
r2 = scratch;
li(r2, rt);
slt(scratch, rs, r2);
@@ -1606,6 +1672,7 @@ void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs,
offset = shifted_branch_offset(L, false);
bne(scratch, zero_reg, offset);
} else {
+ ASSERT(!scratch.is(rs));
r2 = scratch;
li(r2, rt);
slt(scratch, rs, r2);
@@ -1618,6 +1685,7 @@ void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs,
offset = shifted_branch_offset(L, false);
blez(rs, offset);
} else {
+ ASSERT(!scratch.is(rs));
r2 = scratch;
li(r2, rt);
slt(scratch, r2, rs);
@@ -1631,6 +1699,7 @@ void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs,
offset = shifted_branch_offset(L, false);
bgtz(rs, offset);
} else {
+ ASSERT(!scratch.is(rs));
r2 = scratch;
li(r2, rt);
sltu(scratch, r2, rs);
@@ -1647,6 +1716,7 @@ void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs,
offset = shifted_branch_offset(L, false);
beq(scratch, zero_reg, offset);
} else {
+ ASSERT(!scratch.is(rs));
r2 = scratch;
li(r2, rt);
sltu(scratch, rs, r2);
@@ -1663,6 +1733,7 @@ void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs,
offset = shifted_branch_offset(L, false);
bne(scratch, zero_reg, offset);
} else {
+ ASSERT(!scratch.is(rs));
r2 = scratch;
li(r2, rt);
sltu(scratch, rs, r2);
@@ -1675,6 +1746,7 @@ void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs,
offset = shifted_branch_offset(L, false);
b(offset);
} else {
+ ASSERT(!scratch.is(rs));
r2 = scratch;
li(r2, rt);
sltu(scratch, r2, rs);
@@ -2743,6 +2815,46 @@ void MacroAssembler::AllocateAsciiConsString(Register result,
}
+void MacroAssembler::AllocateTwoByteSlicedString(Register result,
+ Register length,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required) {
+ AllocateInNewSpace(SlicedString::kSize,
+ result,
+ scratch1,
+ scratch2,
+ gc_required,
+ TAG_OBJECT);
+
+ InitializeNewString(result,
+ length,
+ Heap::kSlicedStringMapRootIndex,
+ scratch1,
+ scratch2);
+}
+
+
+void MacroAssembler::AllocateAsciiSlicedString(Register result,
+ Register length,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required) {
+ AllocateInNewSpace(SlicedString::kSize,
+ result,
+ scratch1,
+ scratch2,
+ gc_required,
+ TAG_OBJECT);
+
+ InitializeNewString(result,
+ length,
+ Heap::kSlicedAsciiStringMapRootIndex,
+ scratch1,
+ scratch2);
+}
+
+
// Allocates a heap number or jumps to the label if the young space is full and
// a scavenge is needed.
void MacroAssembler::AllocateHeapNumber(Register result,
@@ -4141,11 +4253,9 @@ void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
// mips, even though those argument slots are not normally used.
// Remaining arguments are pushed on the stack, above (higher address than)
// the argument slots.
- ASSERT(StandardFrameConstants::kCArgsSlotsSize % kPointerSize == 0);
int stack_passed_arguments = ((num_arguments <= kRegisterPassedArguments) ?
0 : num_arguments - kRegisterPassedArguments) +
- (StandardFrameConstants::kCArgsSlotsSize /
- kPointerSize);
+ kCArgSlotCount;
if (frame_alignment > kPointerSize) {
// Make stack end at alignment and make room for num_arguments - 4 words
// and the original value of sp.
@@ -4217,11 +4327,9 @@ void MacroAssembler::CallCFunctionHelper(Register function,
Call(function);
- ASSERT(StandardFrameConstants::kCArgsSlotsSize % kPointerSize == 0);
int stack_passed_arguments = ((num_arguments <= kRegisterPassedArguments) ?
0 : num_arguments - kRegisterPassedArguments) +
- (StandardFrameConstants::kCArgsSlotsSize /
- kPointerSize);
+ kCArgSlotCount;
if (OS::ActivationFrameAlignment() > kPointerSize) {
lw(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
diff --git a/deps/v8/src/mips/macro-assembler-mips.h b/deps/v8/src/mips/macro-assembler-mips.h
index 0fcf6f1d85..5dd012e93e 100644
--- a/deps/v8/src/mips/macro-assembler-mips.h
+++ b/deps/v8/src/mips/macro-assembler-mips.h
@@ -362,6 +362,16 @@ class MacroAssembler: public Assembler {
Register scratch1,
Register scratch2,
Label* gc_required);
+ void AllocateTwoByteSlicedString(Register result,
+ Register length,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required);
+ void AllocateAsciiSlicedString(Register result,
+ Register length,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required);
// Allocates a heap number or jumps to the gc_required label if the young
// space is full and a scavenge is needed. All registers are clobbered also
@@ -442,6 +452,9 @@ class MacroAssembler: public Assembler {
void MultiPush(RegList regs);
void MultiPushReversed(RegList regs);
+ void MultiPushFPU(RegList regs);
+ void MultiPushReversedFPU(RegList regs);
+
// Lower case push() for compatibility with arch-independent code.
void push(Register src) {
Addu(sp, sp, Operand(-kPointerSize));
@@ -487,6 +500,9 @@ class MacroAssembler: public Assembler {
void MultiPop(RegList regs);
void MultiPopReversed(RegList regs);
+ void MultiPopFPU(RegList regs);
+ void MultiPopReversedFPU(RegList regs);
+
// Lower case pop() for compatibility with arch-independent code.
void pop(Register dst) {
lw(dst, MemOperand(sp, 0));
@@ -1197,10 +1213,9 @@ static inline MemOperand FieldMemOperand(Register object, int offset) {
// Generate a MemOperand for storing arguments 5..N on the stack
// when calling CallCFunction().
static inline MemOperand CFunctionArgumentOperand(int index) {
- ASSERT(index > StandardFrameConstants::kCArgSlotCount);
+ ASSERT(index > kCArgSlotCount);
// Argument 5 takes the slot just past the four Arg-slots.
- int offset =
- (index - 5) * kPointerSize + StandardFrameConstants::kCArgsSlotsSize;
+ int offset = (index - 5) * kPointerSize + kCArgsSlotsSize;
return MemOperand(sp, offset);
}
diff --git a/deps/v8/src/mips/regexp-macro-assembler-mips.cc b/deps/v8/src/mips/regexp-macro-assembler-mips.cc
index 45d3963972..63e836f22f 100644
--- a/deps/v8/src/mips/regexp-macro-assembler-mips.cc
+++ b/deps/v8/src/mips/regexp-macro-assembler-mips.cc
@@ -1050,7 +1050,7 @@ int RegExpMacroAssemblerMIPS::CheckStackGuardState(Address* return_address,
MaybeObject* result = Execution::HandleStackGuardInterrupt();
if (*code_handle != re_code) { // Return address no longer valid.
- int delta = *code_handle - re_code;
+ int delta = code_handle->address() - re_code->address();
// Overwrite the return address on the stack.
*return_address += delta;
}
diff --git a/deps/v8/src/mips/simulator-mips.cc b/deps/v8/src/mips/simulator-mips.cc
index 30e12e75b1..7628237037 100644
--- a/deps/v8/src/mips/simulator-mips.cc
+++ b/deps/v8/src/mips/simulator-mips.cc
@@ -1409,20 +1409,11 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
int32_t arg1 = get_register(a1);
int32_t arg2 = get_register(a2);
int32_t arg3 = get_register(a3);
- int32_t arg4 = 0;
- int32_t arg5 = 0;
- // Need to check if sp is valid before assigning arg4, arg5.
- // This is a fix for cctest test-api/CatchStackOverflow which causes
- // the stack to overflow. For some reason arm doesn't need this
- // stack check here.
int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
- int32_t* stack = reinterpret_cast<int32_t*>(stack_);
- if (stack_pointer >= stack && stack_pointer < stack + stack_size_ - 5) {
- // Args 4 and 5 are on the stack after the reserved space for args 0..3.
- arg4 = stack_pointer[4];
- arg5 = stack_pointer[5];
- }
+ // Args 4 and 5 are on the stack after the reserved space for args 0..3.
+ int32_t arg4 = stack_pointer[4];
+ int32_t arg5 = stack_pointer[5];
bool fp_call =
(redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
@@ -2725,7 +2716,7 @@ int32_t Simulator::Call(byte* entry, int argument_count, ...) {
// Store remaining arguments on stack, from low to high memory.
intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
for (int i = 4; i < argument_count; i++) {
- stack_argument[i - 4 + kArgsSlotsNum] = va_arg(parameters, int32_t);
+ stack_argument[i - 4 + kCArgSlotCount] = va_arg(parameters, int32_t);
}
va_end(parameters);
set_register(sp, entry_stack);
diff --git a/deps/v8/src/mips/stub-cache-mips.cc b/deps/v8/src/mips/stub-cache-mips.cc
index c17a658d1d..d0f06e4710 100644
--- a/deps/v8/src/mips/stub-cache-mips.cc
+++ b/deps/v8/src/mips/stub-cache-mips.cc
@@ -3501,7 +3501,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
// We are not untagging smi key and instead work with it
// as if it was premultiplied by 2.
- ASSERT((kSmiTag == 0) && (kSmiTagSize == 1));
+ STATIC_ASSERT((kSmiTag == 0) && (kSmiTagSize == 1));
Register value = a2;
switch (elements_kind) {
@@ -4213,7 +4213,7 @@ void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
// Load the result and make sure it's not the hole.
__ Addu(a3, a2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
- ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
+ STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
__ sll(t0, a0, kPointerSizeLog2 - kSmiTagSize);
__ Addu(t0, t0, a3);
__ lw(t0, MemOperand(t0));
@@ -4344,7 +4344,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
__ Addu(scratch,
elements_reg, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
- ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
+ STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
__ sll(scratch2, key_reg, kPointerSizeLog2 - kSmiTagSize);
__ Addu(scratch3, scratch2, scratch);
__ sw(value_reg, MemOperand(scratch3));
diff --git a/deps/v8/src/mksnapshot.cc b/deps/v8/src/mksnapshot.cc
index 4f5fe96a90..a791dbba28 100644
--- a/deps/v8/src/mksnapshot.cc
+++ b/deps/v8/src/mksnapshot.cc
@@ -29,8 +29,6 @@
#include <bzlib.h>
#endif
#include <signal.h>
-#include <string>
-#include <map>
#include "v8.h"
@@ -86,16 +84,6 @@ class CounterCollection {
};
-// We statically allocate a set of local counters to be used if we
-// don't want to store the stats in a memory-mapped file
-static CounterCollection local_counters;
-
-
-typedef std::map<std::string, int*> CounterMap;
-typedef std::map<std::string, int*>::iterator CounterMapIterator;
-static CounterMap counter_table_;
-
-
class Compressor {
public:
virtual ~Compressor() {}
diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h
index b4c6a3a03e..588b0f63a8 100644
--- a/deps/v8/src/objects-inl.h
+++ b/deps/v8/src/objects-inl.h
@@ -171,7 +171,7 @@ bool Object::IsSymbol() {
// Because the symbol tag is non-zero and no non-string types have the
// symbol bit set we can test for symbols with a very simple test
// operation.
- ASSERT(kSymbolTag != 0);
+ STATIC_ASSERT(kSymbolTag != 0);
ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
return (type & kIsSymbolMask) != 0;
}
@@ -256,7 +256,7 @@ StringShape::StringShape(InstanceType t)
bool StringShape::IsSymbol() {
ASSERT(valid());
- ASSERT(kSymbolTag != 0);
+ STATIC_ASSERT(kSymbolTag != 0);
return (type_ & kIsSymbolMask) != 0;
}
@@ -1749,9 +1749,15 @@ bool FixedDoubleArray::is_the_hole(int index) {
void FixedDoubleArray::Initialize(FixedDoubleArray* from) {
int old_length = from->length();
ASSERT(old_length < length());
- OS::MemCopy(FIELD_ADDR(this, kHeaderSize),
- FIELD_ADDR(from, kHeaderSize),
- old_length * kDoubleSize);
+ if (old_length * kDoubleSize >= OS::kMinComplexMemCopy) {
+ OS::MemCopy(FIELD_ADDR(this, kHeaderSize),
+ FIELD_ADDR(from, kHeaderSize),
+ old_length * kDoubleSize);
+ } else {
+ for (int i = 0; i < old_length; ++i) {
+ set(i, from->get_scalar(i));
+ }
+ }
int offset = kHeaderSize + old_length * kDoubleSize;
for (int current = from->length(); current < length(); ++current) {
WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc
index 0a9598cfd8..76b57d86aa 100644
--- a/deps/v8/src/objects.cc
+++ b/deps/v8/src/objects.cc
@@ -7009,7 +7009,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint(FILE* out) {
JSFunction* function =
JSFunction::cast(LiteralArray()->get(function_id));
unsigned height = iterator.Next();
- PrintF(out, "{ast_id=%d, \nfunction=", ast_id);
+ PrintF(out, "{ast_id=%d, function=", ast_id);
function->PrintName(out);
PrintF(out, ", height=%u}", height);
break;
diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h
index 6c8888bf14..53ba981c85 100644
--- a/deps/v8/src/objects.h
+++ b/deps/v8/src/objects.h
@@ -496,6 +496,11 @@ STATIC_ASSERT(
STATIC_ASSERT(
(kSlicedStringTag & kIsIndirectStringMask) == kIsIndirectStringTag);
+// Use this mask to distinguish between cons and slice only after making
+// sure that the string is one of the two (an indirect string).
+const uint32_t kSlicedNotConsMask = kSlicedStringTag & ~kConsStringTag;
+STATIC_ASSERT(IS_POWER_OF_TWO(kSlicedNotConsMask) && kSlicedNotConsMask != 0);
+
// If bit 7 is clear, then bit 3 indicates whether this two-byte
// string actually contains ascii data.
const uint32_t kAsciiDataHintMask = 0x08;
diff --git a/deps/v8/src/parser.cc b/deps/v8/src/parser.cc
index 844dd7060c..056133449c 100644
--- a/deps/v8/src/parser.cc
+++ b/deps/v8/src/parser.cc
@@ -30,6 +30,7 @@
#include "api.h"
#include "ast-inl.h"
#include "bootstrapper.h"
+#include "char-predicates-inl.h"
#include "codegen.h"
#include "compiler.h"
#include "func-name-inferrer.h"
@@ -532,7 +533,7 @@ LexicalScope::LexicalScope(Parser* parser, Scope* scope, Isolate* isolate)
parser->top_scope_ = scope;
parser->lexical_scope_ = this;
parser->with_nesting_level_ = 0;
- isolate->set_ast_node_id(AstNode::kFunctionEntryId + 1);
+ isolate->set_ast_node_id(AstNode::kDeclarationsId + 1);
}
@@ -647,6 +648,11 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
if (ok && top_scope_->is_strict_mode()) {
CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok);
}
+
+ if (ok && harmony_block_scoping_) {
+ CheckConflictingVarDeclarations(scope, &ok);
+ }
+
if (ok) {
result = new(zone()) FunctionLiteral(
isolate(),
@@ -1343,14 +1349,32 @@ VariableProxy* Parser::Declare(Handle<String> name,
// Declare the name.
var = declaration_scope->DeclareLocal(name, mode);
} else {
- // The name was declared before; check for conflicting re-declarations.
- // We have a conflict if either of the declarations is not a var. There
- // is similar code in runtime.cc in the Declare functions.
+ // The name was declared in this scope before; check for conflicting
+ // re-declarations. We have a conflict if either of the declarations is
+ // not a var. There is similar code in runtime.cc in the Declare
+ // functions. The function CheckNonConflictingScope checks for conflicting
+ // var and let bindings from different scopes whereas this is a check for
+ // conflicting declarations within the same scope. This check also covers
+ //
+ // function () { let x; { var x; } }
+ //
+ // because the var declaration is hoisted to the function scope where 'x'
+ // is already bound.
if ((mode != Variable::VAR) || (var->mode() != Variable::VAR)) {
// We only have vars, consts and lets in declarations.
ASSERT(var->mode() == Variable::VAR ||
var->mode() == Variable::CONST ||
var->mode() == Variable::LET);
+ if (harmony_block_scoping_) {
+ // In harmony mode we treat re-declarations as early errors. See
+ // ES5 16 for a definition of early errors.
+ SmartPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
+ const char* elms[2] = { "Variable", *c_string };
+ Vector<const char*> args(elms, 2);
+ ReportMessage("redeclaration", args);
+ *ok = false;
+ return NULL;
+ }
const char* type = (var->mode() == Variable::VAR) ? "var" :
(var->mode() == Variable::CONST) ? "const" : "let";
Handle<String> type_string =
@@ -1379,8 +1403,10 @@ VariableProxy* Parser::Declare(Handle<String> name,
// semantic issue as long as we keep the source order, but it may be
// a performance issue since it may lead to repeated
// Runtime::DeclareContextSlot() calls.
- VariableProxy* proxy = declaration_scope->NewUnresolved(name, false);
- declaration_scope->AddDeclaration(new(zone()) Declaration(proxy, mode, fun));
+ VariableProxy* proxy = declaration_scope->NewUnresolved(
+ name, false, scanner().location().beg_pos);
+ declaration_scope->AddDeclaration(
+ new(zone()) Declaration(proxy, mode, fun, top_scope_));
// For global const variables we bind the proxy to a variable.
if (mode == Variable::CONST && declaration_scope->is_global_scope()) {
@@ -1534,9 +1560,6 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
Scope* block_scope = NewScope(top_scope_,
Scope::BLOCK_SCOPE,
inside_with());
- body->set_block_scope(block_scope);
- block_scope->DeclareLocal(isolate()->factory()->block_scope_symbol(),
- Variable::VAR);
if (top_scope_->is_strict_mode()) {
block_scope->EnableStrictMode();
}
@@ -1559,21 +1582,11 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
}
}
Expect(Token::RBRACE, CHECK_OK);
-
- // Create exit block.
- Block* exit = new(zone()) Block(isolate(), NULL, 1, false);
- exit->AddStatement(new(zone()) ExitContextStatement());
-
- // Create a try-finally statement.
- TryFinallyStatement* try_finally =
- new(zone()) TryFinallyStatement(body, exit);
- try_finally->set_escaping_targets(collector.targets());
top_scope_ = saved_scope;
- // Create a result block.
- Block* result = new(zone()) Block(isolate(), NULL, 1, false);
- result->AddStatement(try_finally);
- return result;
+ block_scope = block_scope->FinalizeBlockScope();
+ body->set_block_scope(block_scope);
+ return body;
}
@@ -1609,7 +1622,13 @@ Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
// ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
Variable::Mode mode = Variable::VAR;
+ // True if the binding needs initialization. 'let' and 'const' declared
+ // bindings are created uninitialized by their declaration nodes and
+ // need initialization. 'var' declared bindings are always initialized
+ // immediately by their declaration nodes.
+ bool needs_init = false;
bool is_const = false;
+ Token::Value init_op = Token::INIT_VAR;
if (peek() == Token::VAR) {
Consume(Token::VAR);
} else if (peek() == Token::CONST) {
@@ -1621,6 +1640,8 @@ Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
}
mode = Variable::CONST;
is_const = true;
+ needs_init = true;
+ init_op = Token::INIT_CONST;
} else if (peek() == Token::LET) {
Consume(Token::LET);
if (var_context != kSourceElement &&
@@ -1631,6 +1652,8 @@ Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
return NULL;
}
mode = Variable::LET;
+ needs_init = true;
+ init_op = Token::INIT_LET;
} else {
UNREACHABLE(); // by current callers
}
@@ -1732,9 +1755,8 @@ Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
}
}
- // Make sure that 'const c' actually initializes 'c' to undefined
- // even though it seems like a stupid thing to do.
- if (value == NULL && is_const) {
+ // Make sure that 'const x' and 'let x' initialize 'x' to undefined.
+ if (value == NULL && needs_init) {
value = GetLiteralUndefined();
}
@@ -1811,23 +1833,25 @@ Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
block->AddStatement(new(zone()) ExpressionStatement(initialize));
}
- // Add an assignment node to the initialization statement block if
- // we still have a pending initialization value. We must distinguish
- // between variables and constants: Variable initializations are simply
+ // Add an assignment node to the initialization statement block if we still
+ // have a pending initialization value. We must distinguish between
+ // different kinds of declarations: 'var' initializations are simply
// assignments (with all the consequences if they are inside a 'with'
// statement - they may change a 'with' object property). Constant
// initializations always assign to the declared constant which is
// always at the function scope level. This is only relevant for
// dynamically looked-up variables and constants (the start context
// for constant lookups is always the function context, while it is
- // the top context for variables). Sigh...
+ // the top context for var declared variables). Sigh...
+ // For 'let' declared variables the initialization is in the same scope
+ // as the declaration. Thus dynamic lookups are unnecessary even if the
+ // block scope is inside a with.
if (value != NULL) {
- Token::Value op = (is_const ? Token::INIT_CONST : Token::INIT_VAR);
- bool in_with = is_const ? false : inside_with();
+ bool in_with = mode == Variable::VAR ? inside_with() : false;
VariableProxy* proxy =
initialization_scope->NewUnresolved(name, in_with);
Assignment* assignment =
- new(zone()) Assignment(isolate(), op, proxy, value, position);
+ new(zone()) Assignment(isolate(), init_op, proxy, value, position);
if (block) {
block->AddStatement(new(zone()) ExpressionStatement(assignment));
}
@@ -2199,7 +2223,9 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
if (top_scope_->is_strict_mode()) {
catch_scope->EnableStrictMode();
}
- catch_variable = catch_scope->DeclareLocal(name, Variable::VAR);
+ Variable::Mode mode = harmony_block_scoping_
+ ? Variable::LET : Variable::VAR;
+ catch_variable = catch_scope->DeclareLocal(name, mode);
catch_block = new(zone()) Block(isolate(), NULL, 2, false);
Scope* saved_scope = top_scope_;
@@ -3728,7 +3754,10 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
reserved_loc = scanner().location();
}
- top_scope_->DeclareParameter(param_name);
+ top_scope_->DeclareParameter(param_name,
+ harmony_block_scoping_
+ ? Variable::LET
+ : Variable::VAR);
num_parameters++;
if (num_parameters > kMaxNumFunctionParameters) {
ReportMessageAt(scanner().location(), "too_many_parameters",
@@ -3855,6 +3884,10 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
}
}
+ if (harmony_block_scoping_) {
+ CheckConflictingVarDeclarations(scope, CHECK_OK);
+ }
+
FunctionLiteral* function_literal =
new(zone()) FunctionLiteral(isolate(),
function_name,
@@ -4061,6 +4094,25 @@ void Parser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
}
+void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
+ Declaration* decl = scope->CheckConflictingVarDeclarations();
+ if (decl != NULL) {
+ // In harmony mode we treat conflicting variable bindinds as early
+ // errors. See ES5 16 for a definition of early errors.
+ Handle<String> name = decl->proxy()->name();
+ SmartPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
+ const char* elms[2] = { "Variable", *c_string };
+ Vector<const char*> args(elms, 2);
+ int position = decl->proxy()->position();
+ Scanner::Location location = position == RelocInfo::kNoPosition
+ ? Scanner::Location::invalid()
+ : Scanner::Location(position, position + 1);
+ ReportMessageAt(location, "redeclaration", args);
+ *ok = false;
+ }
+}
+
+
// This function reads an identifier name and determines whether or not it
// is 'get' or 'set'.
Handle<String> Parser::ParseIdentifierNameOrGetOrSet(bool* is_get,
diff --git a/deps/v8/src/parser.h b/deps/v8/src/parser.h
index 686dac85af..381ff27143 100644
--- a/deps/v8/src/parser.h
+++ b/deps/v8/src/parser.h
@@ -645,6 +645,17 @@ class Parser {
// Strict mode octal literal validation.
void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok);
+ // For harmony block scoping mode: Check if the scope has conflicting var/let
+ // declarations from different scopes. It covers for example
+ //
+ // function f() { { { var x; } let x; } }
+ // function g() { { var x; let x; } }
+ //
+ // The var declarations are hoisted to the function scope, but originate from
+ // a scope where the name has also been let bound or the var declaration is
+ // hoisted over such a scope.
+ void CheckConflictingVarDeclarations(Scope* scope, bool* ok);
+
// Parser support
VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
FunctionLiteral* fun,
diff --git a/deps/v8/src/platform-linux.cc b/deps/v8/src/platform-linux.cc
index 362bf47cc1..b152dae9a6 100644
--- a/deps/v8/src/platform-linux.cc
+++ b/deps/v8/src/platform-linux.cc
@@ -130,13 +130,7 @@ void OS::Setup() {
uint64_t OS::CpuFeaturesImpliedByPlatform() {
-#if(defined(__mips_hard_float) && __mips_hard_float != 0)
- // Here gcc is telling us that we are on an MIPS and gcc is assuming that we
- // have FPU instructions. If gcc can assume it then so can we.
- return 1u << FPU;
-#else
return 0; // Linux runs on anything.
-#endif
}
diff --git a/deps/v8/src/prettyprinter.cc b/deps/v8/src/prettyprinter.cc
index b03429341e..2a41592331 100644
--- a/deps/v8/src/prettyprinter.cc
+++ b/deps/v8/src/prettyprinter.cc
@@ -284,28 +284,6 @@ void PrettyPrinter::VisitArrayLiteral(ArrayLiteral* node) {
}
-void PrettyPrinter::VisitSlot(Slot* node) {
- switch (node->type()) {
- case Slot::PARAMETER:
- Print("parameter[%d]", node->index());
- break;
- case Slot::LOCAL:
- Print("local[%d]", node->index());
- break;
- case Slot::CONTEXT:
- Print("context[%d]", node->index());
- break;
- case Slot::LOOKUP:
- Print("lookup[");
- PrintLiteral(node->var()->name(), false);
- Print("]");
- break;
- default:
- UNREACHABLE();
- }
-}
-
-
void PrettyPrinter::VisitVariableProxy(VariableProxy* node) {
PrintLiteral(node->name(), false);
}
@@ -751,7 +729,7 @@ void AstPrinter::VisitDeclaration(Declaration* node) {
if (node->fun() == NULL) {
// var or const declarations
PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()),
- node->proxy()->AsVariable(),
+ node->proxy()->var(),
node->proxy()->name());
} else {
// function declarations
@@ -959,19 +937,26 @@ void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
}
-void AstPrinter::VisitSlot(Slot* node) {
- PrintIndented("SLOT ");
- PrettyPrinter::VisitSlot(node);
- Print("\n");
-}
-
-
void AstPrinter::VisitVariableProxy(VariableProxy* node) {
- PrintLiteralWithModeIndented("VAR PROXY", node->AsVariable(), node->name());
Variable* var = node->var();
- if (var != NULL && var->rewrite() != NULL) {
- IndentedScope indent(this);
- Visit(var->rewrite());
+ PrintLiteralWithModeIndented("VAR PROXY", var, node->name());
+ { IndentedScope indent(this);
+ switch (var->location()) {
+ case Variable::UNALLOCATED:
+ break;
+ case Variable::PARAMETER:
+ Print("parameter[%d]", var->index());
+ break;
+ case Variable::LOCAL:
+ Print("local[%d]", var->index());
+ break;
+ case Variable::CONTEXT:
+ Print("context[%d]", var->index());
+ break;
+ case Variable::LOOKUP:
+ Print("lookup");
+ break;
+ }
}
}
@@ -1287,39 +1272,32 @@ void JsonAstBuilder::VisitConditional(Conditional* expr) {
}
-void JsonAstBuilder::VisitSlot(Slot* expr) {
- TagScope tag(this, "Slot");
+void JsonAstBuilder::VisitVariableProxy(VariableProxy* expr) {
+ TagScope tag(this, "Variable");
{
AttributesScope attributes(this);
- switch (expr->type()) {
- case Slot::PARAMETER:
- AddAttribute("type", "PARAMETER");
+ Variable* var = expr->var();
+ AddAttribute("name", var->name());
+ switch (var->location()) {
+ case Variable::UNALLOCATED:
+ AddAttribute("location", "UNALLOCATED");
break;
- case Slot::LOCAL:
- AddAttribute("type", "LOCAL");
+ case Variable::PARAMETER:
+ AddAttribute("location", "PARAMETER");
+ AddAttribute("index", var->index());
break;
- case Slot::CONTEXT:
- AddAttribute("type", "CONTEXT");
+ case Variable::LOCAL:
+ AddAttribute("location", "LOCAL");
+ AddAttribute("index", var->index());
break;
- case Slot::LOOKUP:
- AddAttribute("type", "LOOKUP");
+ case Variable::CONTEXT:
+ AddAttribute("location", "CONTEXT");
+ AddAttribute("index", var->index());
+ break;
+ case Variable::LOOKUP:
+ AddAttribute("location", "LOOKUP");
break;
}
- AddAttribute("index", expr->index());
- }
-}
-
-
-void JsonAstBuilder::VisitVariableProxy(VariableProxy* expr) {
- if (expr->var()->rewrite() == NULL) {
- TagScope tag(this, "VariableProxy");
- {
- AttributesScope attributes(this);
- AddAttribute("name", expr->name());
- AddAttribute("mode", Variable::Mode2String(expr->var()->mode()));
- }
- } else {
- Visit(expr->var()->rewrite());
}
}
diff --git a/deps/v8/src/prettyprinter.h b/deps/v8/src/prettyprinter.h
index 080081dd30..a26c48e490 100644
--- a/deps/v8/src/prettyprinter.h
+++ b/deps/v8/src/prettyprinter.h
@@ -52,7 +52,6 @@ class PrettyPrinter: public AstVisitor {
// Print a node to stdout.
static void PrintOut(AstNode* node);
- virtual void VisitSlot(Slot* node);
// Individual nodes
#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
AST_NODE_LIST(DECLARE_VISIT)
@@ -87,7 +86,6 @@ class AstPrinter: public PrettyPrinter {
const char* PrintProgram(FunctionLiteral* program);
// Individual nodes
- virtual void VisitSlot(Slot* node);
#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
@@ -163,7 +161,6 @@ class JsonAstBuilder: public PrettyPrinter {
void AddAttribute(const char* name, bool value);
// AST node visit functions.
- virtual void VisitSlot(Slot* node);
#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
diff --git a/deps/v8/src/profile-generator.cc b/deps/v8/src/profile-generator.cc
index db9f8928de..74dfbf445c 100644
--- a/deps/v8/src/profile-generator.cc
+++ b/deps/v8/src/profile-generator.cc
@@ -1195,12 +1195,9 @@ void HeapSnapshot::AllocateEntries(int entries_count,
int children_count,
int retainers_count) {
ASSERT(raw_entries_ == NULL);
- raw_entries_ = NewArray<char>(
- HeapEntry::EntriesSize(entries_count, children_count, retainers_count));
-#ifdef DEBUG
raw_entries_size_ =
HeapEntry::EntriesSize(entries_count, children_count, retainers_count);
-#endif
+ raw_entries_ = NewArray<char>(raw_entries_size_);
}
@@ -2984,10 +2981,19 @@ class OutputStreamWriter {
bool aborted_;
};
+const int HeapSnapshotJSONSerializer::kMaxSerializableSnapshotRawSize =
+ 256 * MB;
+
void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) {
ASSERT(writer_ == NULL);
writer_ = new OutputStreamWriter(stream);
+ HeapSnapshot* original_snapshot = NULL;
+ if (snapshot_->raw_entries_size() >= kMaxSerializableSnapshotRawSize) {
+ // The snapshot is too big. Serialize a fake snapshot.
+ original_snapshot = snapshot_;
+ snapshot_ = CreateFakeSnapshot();
+ }
// Since nodes graph is cyclic, we need the first pass to enumerate
// them. Strings can be serialized in one pass.
EnumerateNodes();
@@ -2995,6 +3001,26 @@ void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) {
delete writer_;
writer_ = NULL;
+
+ if (original_snapshot != NULL) {
+ delete snapshot_;
+ snapshot_ = original_snapshot;
+ }
+}
+
+
+HeapSnapshot* HeapSnapshotJSONSerializer::CreateFakeSnapshot() {
+ HeapSnapshot* result = new HeapSnapshot(snapshot_->collection(),
+ HeapSnapshot::kFull,
+ snapshot_->title(),
+ snapshot_->uid());
+ result->AllocateEntries(2, 1, 0);
+ HeapEntry* root = result->AddRootEntry(1);
+ HeapEntry* message = result->AddEntry(
+ HeapEntry::kString, "The snapshot is too big", 0, 4, 0, 0);
+ root->SetUnidirElementReference(0, 1, message);
+ result->SetDominatorsToSelf();
+ return result;
}
diff --git a/deps/v8/src/profile-generator.h b/deps/v8/src/profile-generator.h
index 9ab44a1e21..6bada36d57 100644
--- a/deps/v8/src/profile-generator.h
+++ b/deps/v8/src/profile-generator.h
@@ -654,6 +654,7 @@ class HeapSnapshot {
HeapEntry* gc_roots() { return gc_roots_entry_; }
HeapEntry* natives_root() { return natives_root_entry_; }
List<HeapEntry*>* entries() { return &entries_; }
+ int raw_entries_size() { return raw_entries_size_; }
void AllocateEntries(
int entries_count, int children_count, int retainers_count);
@@ -689,9 +690,7 @@ class HeapSnapshot {
char* raw_entries_;
List<HeapEntry*> entries_;
bool entries_sorted_;
-#ifdef DEBUG
int raw_entries_size_;
-#endif
friend class HeapSnapshotTester;
@@ -1097,6 +1096,7 @@ class HeapSnapshotJSONSerializer {
}
void EnumerateNodes();
+ HeapSnapshot* CreateFakeSnapshot();
int GetNodeId(HeapEntry* entry);
int GetStringId(const char* s);
void SerializeEdge(HeapGraphEdge* edge);
@@ -1108,6 +1108,8 @@ class HeapSnapshotJSONSerializer {
void SerializeStrings();
void SortHashMap(HashMap* map, List<HashMap::Entry*>* sorted_entries);
+ static const int kMaxSerializableSnapshotRawSize;
+
HeapSnapshot* snapshot_;
HashMap nodes_;
HashMap strings_;
diff --git a/deps/v8/src/regexp.js b/deps/v8/src/regexp.js
index a7f42d59c2..38d4496153 100644
--- a/deps/v8/src/regexp.js
+++ b/deps/v8/src/regexp.js
@@ -405,7 +405,8 @@ var lastMatchInfoOverride = null;
// -------------------------------------------------------------------
-function SetupRegExp() {
+function SetUpRegExp() {
+ %CheckIsBootstrapping();
%FunctionSetInstanceClassName($RegExp, 'RegExp');
%FunctionSetPrototype($RegExp, new $Object());
%SetProperty($RegExp.prototype, 'constructor', $RegExp, DONT_ENUM);
@@ -484,5 +485,4 @@ function SetupRegExp() {
}
}
-
-SetupRegExp();
+SetUpRegExp();
diff --git a/deps/v8/src/runtime-profiler.cc b/deps/v8/src/runtime-profiler.cc
index 917f6d0d66..26d8846107 100644
--- a/deps/v8/src/runtime-profiler.cc
+++ b/deps/v8/src/runtime-profiler.cc
@@ -115,10 +115,8 @@ void RuntimeProfiler::AttemptOnStackReplacement(JSFunction* function) {
}
SharedFunctionInfo* shared = function->shared();
- // If the code is not optimizable or references context slots, don't try OSR.
- if (!shared->code()->optimizable() || !shared->allows_lazy_compilation()) {
- return;
- }
+ // If the code is not optimizable, don't try OSR.
+ if (!shared->code()->optimizable()) return;
// We are not prepared to do OSR for a function that already has an
// allocated arguments object. The optimized code would bypass it for
diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc
index 802fd6845d..3e07b99823 100644
--- a/deps/v8/src/runtime.cc
+++ b/deps/v8/src/runtime.cc
@@ -32,6 +32,7 @@
#include "accessors.h"
#include "api.h"
#include "arguments.h"
+#include "bootstrapper.h"
#include "codegen.h"
#include "compilation-cache.h"
#include "compiler.h"
@@ -1149,22 +1150,14 @@ static Failure* ThrowRedeclarationError(Isolate* isolate,
RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
- ASSERT(args.length() == 4);
+ ASSERT(args.length() == 3);
HandleScope scope(isolate);
Handle<GlobalObject> global = Handle<GlobalObject>(
isolate->context()->global());
Handle<Context> context = args.at<Context>(0);
CONVERT_ARG_CHECKED(FixedArray, pairs, 1);
- bool is_eval = args.smi_at(2) == 1;
- StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
- ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
-
- // Compute the property attributes. According to ECMA-262, section
- // 13, page 71, the property must be read-only and
- // non-deletable. However, neither SpiderMonkey nor KJS creates the
- // property as read-only, so we don't either.
- PropertyAttributes base = is_eval ? NONE : DONT_DELETE;
+ CONVERT_SMI_ARG_CHECKED(flags, 2);
// Traverse the name/value pairs and set the properties.
int length = pairs->length();
@@ -1177,7 +1170,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
// assign to it when evaluating the assignment for "const x =
// <expr>" the initial value is the hole.
bool is_const_property = value->IsTheHole();
-
+ bool is_function_declaration = false;
if (value->IsUndefined() || is_const_property) {
// Lookup the property in the global object, and don't set the
// value of the variable if the property is already there.
@@ -1226,6 +1219,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
}
}
} else {
+ is_function_declaration = true;
// Copy the function and update its context. Use it as value.
Handle<SharedFunctionInfo> shared =
Handle<SharedFunctionInfo>::cast(value);
@@ -1239,10 +1233,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
LookupResult lookup;
global->LocalLookup(*name, &lookup);
- PropertyAttributes attributes = is_const_property
- ? static_cast<PropertyAttributes>(base | READ_ONLY)
- : base;
-
// There's a local property that we need to overwrite because
// we're either declaring a function or there's an interceptor
// that claims the property is absent.
@@ -1257,6 +1247,19 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
return ThrowRedeclarationError(isolate, type, name);
}
+ // Compute the property attributes. According to ECMA-262, section
+ // 13, page 71, the property must be read-only and
+ // non-deletable. However, neither SpiderMonkey nor KJS creates the
+ // property as read-only, so we don't either.
+ int attr = NONE;
+ if ((flags & kDeclareGlobalsEvalFlag) == 0) {
+ attr |= DONT_DELETE;
+ }
+ bool is_native = (flags & kDeclareGlobalsNativeFlag) != 0;
+ if (is_const_property || (is_native && is_function_declaration)) {
+ attr |= READ_ONLY;
+ }
+
// Safari does not allow the invocation of callback setters for
// function declarations. To mimic this behavior, we do not allow
// the invocation of setters for function values. This makes a
@@ -1267,20 +1270,24 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
if (value->IsJSFunction()) {
// Do not change DONT_DELETE to false from true.
if (lookup.IsProperty() && (lookup.type() != INTERCEPTOR)) {
- attributes = static_cast<PropertyAttributes>(
- attributes | (lookup.GetAttributes() & DONT_DELETE));
+ attr |= lookup.GetAttributes() & DONT_DELETE;
}
+ PropertyAttributes attributes = static_cast<PropertyAttributes>(attr);
+
RETURN_IF_EMPTY_HANDLE(isolate,
SetLocalPropertyIgnoreAttributes(global,
name,
value,
attributes));
} else {
+ StrictModeFlag strict_mode =
+ ((flags & kDeclareGlobalsStrictModeFlag) != 0) ? kStrictMode
+ : kNonStrictMode;
RETURN_IF_EMPTY_HANDLE(isolate,
SetProperty(global,
name,
value,
- attributes,
+ static_cast<PropertyAttributes>(attr),
strict_mode));
}
}
@@ -1306,8 +1313,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
int index;
PropertyAttributes attributes;
ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
+ BindingFlags binding_flags;
Handle<Object> holder =
- context->Lookup(name, flags, &index, &attributes);
+ context->Lookup(name, flags, &index, &attributes, &binding_flags);
if (attributes != ABSENT) {
// The name was declared before; check for conflicting
@@ -1594,8 +1602,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
int index;
PropertyAttributes attributes;
ContextLookupFlags flags = FOLLOW_CHAINS;
+ BindingFlags binding_flags;
Handle<Object> holder =
- context->Lookup(name, flags, &index, &attributes);
+ context->Lookup(name, flags, &index, &attributes, &binding_flags);
// In most situations, the property introduced by the const
// declaration should be present in the context extension object.
@@ -2145,6 +2154,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
+ RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
HandleScope scope(isolate);
ASSERT(args.length() == 2);
@@ -5974,6 +5984,19 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
int pattern_length = pattern->length();
RUNTIME_ASSERT(pattern_length > 0);
+ if (limit == 0xffffffffu) {
+ Handle<Object> cached_answer(StringSplitCache::Lookup(
+ isolate->heap()->string_split_cache(),
+ *subject,
+ *pattern));
+ if (*cached_answer != Smi::FromInt(0)) {
+ Handle<JSArray> result =
+ isolate->factory()->NewJSArrayWithElements(
+ Handle<FixedArray>::cast(cached_answer));
+ return *result;
+ }
+ }
+
// The limit can be very large (0xffffffffu), but since the pattern
// isn't empty, we can never create more parts than ~half the length
// of the subject.
@@ -6067,6 +6090,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
part_start = part_end + pattern_length;
}
+ if (limit == 0xffffffffu) {
+ StringSplitCache::Enter(isolate->heap(),
+ isolate->heap()->string_split_cache(),
+ *subject,
+ *pattern,
+ *elements);
+ }
+
return *result;
}
@@ -8248,6 +8279,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
}
+RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckIsBootstrapping) {
+ RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
+ return isolate->heap()->undefined_value();
+}
+
+
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -8386,7 +8423,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) {
int index;
PropertyAttributes attributes;
ContextLookupFlags flags = FOLLOW_CHAINS;
- Handle<Object> holder = context->Lookup(name, flags, &index, &attributes);
+ BindingFlags binding_flags;
+ Handle<Object> holder = context->Lookup(name,
+ flags,
+ &index,
+ &attributes,
+ &binding_flags);
// If the slot was not found the result is true.
if (holder.is_null()) {
@@ -8488,7 +8530,12 @@ static ObjectPair LoadContextSlotHelper(Arguments args,
int index;
PropertyAttributes attributes;
ContextLookupFlags flags = FOLLOW_CHAINS;
- Handle<Object> holder = context->Lookup(name, flags, &index, &attributes);
+ BindingFlags binding_flags;
+ Handle<Object> holder = context->Lookup(name,
+ flags,
+ &index,
+ &attributes,
+ &binding_flags);
// If the index is non-negative, the slot has been found in a local
// variable or a parameter. Read it from the context object or the
@@ -8504,7 +8551,17 @@ static ObjectPair LoadContextSlotHelper(Arguments args,
MaybeObject* value = (holder->IsContext())
? Context::cast(*holder)->get(index)
: JSObject::cast(*holder)->GetElement(index);
- return MakePair(Unhole(isolate->heap(), value, attributes), *receiver);
+ // Check for uninitialized bindings.
+ if (holder->IsContext() &&
+ binding_flags == MUTABLE_CHECK_INITIALIZED &&
+ value->IsTheHole()) {
+ Handle<Object> reference_error =
+ isolate->factory()->NewReferenceError("not_defined",
+ HandleVector(&name, 1));
+ return MakePair(isolate->Throw(*reference_error), NULL);
+ } else {
+ return MakePair(Unhole(isolate->heap(), value, attributes), *receiver);
+ }
}
// If the holder is found, we read the property from it.
@@ -8570,14 +8627,27 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) {
int index;
PropertyAttributes attributes;
ContextLookupFlags flags = FOLLOW_CHAINS;
- Handle<Object> holder = context->Lookup(name, flags, &index, &attributes);
+ BindingFlags binding_flags;
+ Handle<Object> holder = context->Lookup(name,
+ flags,
+ &index,
+ &attributes,
+ &binding_flags);
if (index >= 0) {
if (holder->IsContext()) {
+ Handle<Context> context = Handle<Context>::cast(holder);
+ if (binding_flags == MUTABLE_CHECK_INITIALIZED &&
+ context->get(index)->IsTheHole()) {
+ Handle<Object> error =
+ isolate->factory()->NewReferenceError("not_defined",
+ HandleVector(&name, 1));
+ return isolate->Throw(*error);
+ }
// Ignore if read_only variable.
if ((attributes & READ_ONLY) == 0) {
// Context is a fixed array and set cannot fail.
- Context::cast(*holder)->set(index, *value);
+ context->set(index, *value);
} else if (strict_mode == kStrictMode) {
// Setting read only property in strict mode.
Handle<Object> error =
@@ -9029,10 +9099,13 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
// it is bound in the global context.
int index = -1;
PropertyAttributes attributes = ABSENT;
+ BindingFlags binding_flags;
while (true) {
receiver = context->Lookup(isolate->factory()->eval_symbol(),
FOLLOW_PROTOTYPE_CHAIN,
- &index, &attributes);
+ &index,
+ &attributes,
+ &binding_flags);
// Stop search when eval is found or when the global context is
// reached.
if (attributes != ABSENT || context->IsGlobalContext()) break;
diff --git a/deps/v8/src/runtime.h b/deps/v8/src/runtime.h
index 91a19dfd45..ddd529588b 100644
--- a/deps/v8/src/runtime.h
+++ b/deps/v8/src/runtime.h
@@ -79,6 +79,7 @@ namespace internal {
F(PreventExtensions, 1, 1)\
\
/* Utilities */ \
+ F(CheckIsBootstrapping, 0, 1) \
F(GetFunctionDelegate, 1, 1) \
F(GetConstructorDelegate, 1, 1) \
F(NewArgumentsFast, 3, 1) \
@@ -317,7 +318,7 @@ namespace internal {
F(StoreContextSlot, 4, 1) \
\
/* Declarations and initialization */ \
- F(DeclareGlobals, 4, 1) \
+ F(DeclareGlobals, 3, 1) \
F(DeclareContextSlot, 4, 1) \
F(InitializeVarGlobal, -1 /* 2 or 3 */, 1) \
F(InitializeConstGlobal, 2, 1) \
@@ -663,6 +664,16 @@ class Runtime : public AllStatic {
static void PerformGC(Object* result);
};
+
+//---------------------------------------------------------------------------
+// Constants used by interface to runtime functions.
+
+enum kDeclareGlobalsFlags {
+ kDeclareGlobalsEvalFlag = 1 << 0,
+ kDeclareGlobalsStrictModeFlag = 1 << 1,
+ kDeclareGlobalsNativeFlag = 1 << 2
+};
+
} } // namespace v8::internal
#endif // V8_RUNTIME_H_
diff --git a/deps/v8/src/runtime.js b/deps/v8/src/runtime.js
index 4b600df736..61deb9baa0 100644
--- a/deps/v8/src/runtime.js
+++ b/deps/v8/src/runtime.js
@@ -48,6 +48,7 @@ const $Number = global.Number;
const $Function = global.Function;
const $Boolean = global.Boolean;
const $NaN = 0/0;
+const builtins = this;
// ECMA-262 Section 11.9.3.
function EQUALS(y) {
diff --git a/deps/v8/src/scanner-base.h b/deps/v8/src/scanner-base.h
index a7062a34af..d68d240e90 100644
--- a/deps/v8/src/scanner-base.h
+++ b/deps/v8/src/scanner-base.h
@@ -362,7 +362,7 @@ class Scanner {
// Call this after setting source_ to the input.
void Init() {
// Set c0_ (one character ahead)
- ASSERT(kCharacterLookaheadBufferSize == 1);
+ STATIC_ASSERT(kCharacterLookaheadBufferSize == 1);
Advance();
// Initialize current_ to not refer to a literal.
current_.literal_chars = NULL;
diff --git a/deps/v8/src/scanner.h b/deps/v8/src/scanner.h
index e66dd60d84..6422ee8cab 100644
--- a/deps/v8/src/scanner.h
+++ b/deps/v8/src/scanner.h
@@ -28,8 +28,6 @@
#ifndef V8_SCANNER_H_
#define V8_SCANNER_H_
-#include "token.h"
-#include "char-predicates-inl.h"
#include "scanner-base.h"
namespace v8 {
diff --git a/deps/v8/src/scopeinfo.cc b/deps/v8/src/scopeinfo.cc
index 0eacc83c79..ad31ca47c6 100644
--- a/deps/v8/src/scopeinfo.cc
+++ b/deps/v8/src/scopeinfo.cc
@@ -39,12 +39,8 @@ namespace internal {
static int CompareLocal(Variable* const* v, Variable* const* w) {
- Slot* s = (*v)->AsSlot();
- Slot* t = (*w)->AsSlot();
- // We may have rewritten parameters (that are in the arguments object)
- // and which may have a NULL slot... - find a better solution...
- int x = (s != NULL ? s->index() : 0);
- int y = (t != NULL ? t->index() : 0);
+ int x = (*v)->index();
+ int y = (*w)->index();
// Consider sorting them according to type as well?
return x - y;
}
@@ -86,27 +82,24 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope)
for (int i = 0; i < locals.length(); i++) {
Variable* var = locals[i];
if (var->is_used()) {
- Slot* slot = var->AsSlot();
- if (slot != NULL) {
- switch (slot->type()) {
- case Slot::PARAMETER:
- // explicitly added to parameters_ above - ignore
- break;
-
- case Slot::LOCAL:
- ASSERT(stack_slots_.length() == slot->index());
- stack_slots_.Add(var->name());
- break;
-
- case Slot::CONTEXT:
- heap_locals.Add(var);
- break;
-
- case Slot::LOOKUP:
- // This is currently not used.
- UNREACHABLE();
- break;
- }
+ switch (var->location()) {
+ case Variable::UNALLOCATED:
+ case Variable::PARAMETER:
+ break;
+
+ case Variable::LOCAL:
+ ASSERT(stack_slots_.length() == var->index());
+ stack_slots_.Add(var->name());
+ break;
+
+ case Variable::CONTEXT:
+ heap_locals.Add(var);
+ break;
+
+ case Variable::LOOKUP:
+ // We don't expect lookup variables in the locals list.
+ UNREACHABLE();
+ break;
}
}
}
@@ -115,9 +108,9 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope)
if (scope->num_heap_slots() > 0) {
// Add user-defined slots.
for (int i = 0; i < heap_locals.length(); i++) {
- ASSERT(heap_locals[i]->AsSlot()->index() - Context::MIN_CONTEXT_SLOTS ==
+ ASSERT(heap_locals[i]->index() - Context::MIN_CONTEXT_SLOTS ==
context_slots_.length());
- ASSERT(heap_locals[i]->AsSlot()->index() - Context::MIN_CONTEXT_SLOTS ==
+ ASSERT(heap_locals[i]->index() - Context::MIN_CONTEXT_SLOTS ==
context_modes_.length());
context_slots_.Add(heap_locals[i]->name());
context_modes_.Add(heap_locals[i]->mode());
@@ -131,18 +124,18 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope)
// For now, this must happen at the very end because of the
// ordering of the scope info slots and the respective slot indices.
if (scope->is_function_scope()) {
- Variable* var = scope->function();
- if (var != NULL &&
- var->is_used() &&
- var->AsSlot()->type() == Slot::CONTEXT) {
- function_name_ = var->name();
+ VariableProxy* proxy = scope->function();
+ if (proxy != NULL &&
+ proxy->var()->is_used() &&
+ proxy->var()->IsContextSlot()) {
+ function_name_ = proxy->name();
// Note that we must not find the function name in the context slot
// list - instead it must be handled separately in the
// Contexts::Lookup() function. Thus record an empty symbol here so we
// get the correct number of context slots.
- ASSERT(var->AsSlot()->index() - Context::MIN_CONTEXT_SLOTS ==
+ ASSERT(proxy->var()->index() - Context::MIN_CONTEXT_SLOTS ==
context_slots_.length());
- ASSERT(var->AsSlot()->index() - Context::MIN_CONTEXT_SLOTS ==
+ ASSERT(proxy->var()->index() - Context::MIN_CONTEXT_SLOTS ==
context_modes_.length());
context_slots_.Add(FACTORY->empty_symbol());
context_modes_.Add(Variable::INTERNAL);
diff --git a/deps/v8/src/scopes.cc b/deps/v8/src/scopes.cc
index ddde48a77c..4e87b25e11 100644
--- a/deps/v8/src/scopes.cc
+++ b/deps/v8/src/scopes.cc
@@ -31,7 +31,6 @@
#include "bootstrapper.h"
#include "compiler.h"
-#include "prettyprinter.h"
#include "scopeinfo.h"
#include "allocation-inl.h"
@@ -314,7 +313,7 @@ void Scope::Initialize(bool inside_with) {
Variable::VAR,
false,
Variable::THIS);
- var->set_rewrite(NewSlot(var, Slot::PARAMETER, -1));
+ var->AllocateTo(Variable::PARAMETER, -1);
receiver_ = var;
}
@@ -331,6 +330,35 @@ void Scope::Initialize(bool inside_with) {
}
+Scope* Scope::FinalizeBlockScope() {
+ ASSERT(is_block_scope());
+ ASSERT(temps_.is_empty());
+ ASSERT(params_.is_empty());
+
+ if (num_var_or_const() > 0) return this;
+
+ // Remove this scope from outer scope.
+ for (int i = 0; i < outer_scope_->inner_scopes_.length(); i++) {
+ if (outer_scope_->inner_scopes_[i] == this) {
+ outer_scope_->inner_scopes_.Remove(i);
+ break;
+ }
+ }
+
+ // Reparent inner scopes.
+ for (int i = 0; i < inner_scopes_.length(); i++) {
+ outer_scope()->AddInnerScope(inner_scopes_[i]);
+ }
+
+ // Move unresolved variables
+ for (int i = 0; i < unresolved_.length(); i++) {
+ outer_scope()->unresolved_.Add(unresolved_[i]);
+ }
+
+ return NULL;
+}
+
+
Variable* Scope::LocalLookup(Handle<String> name) {
Variable* result = variables_.Lookup(name);
if (result != NULL || scope_info_.is_null()) {
@@ -360,7 +388,7 @@ Variable* Scope::LocalLookup(Handle<String> name) {
Variable* var =
variables_.Declare(this, name, mode, true, Variable::NORMAL);
- var->set_rewrite(NewSlot(var, Slot::CONTEXT, index));
+ var->AllocateTo(Variable::CONTEXT, index);
return var;
}
@@ -378,16 +406,18 @@ Variable* Scope::Lookup(Handle<String> name) {
Variable* Scope::DeclareFunctionVar(Handle<String> name) {
ASSERT(is_function_scope() && function_ == NULL);
- function_ = new Variable(this, name, Variable::CONST, true, Variable::NORMAL);
- return function_;
+ Variable* function_var =
+ new Variable(this, name, Variable::CONST, true, Variable::NORMAL);
+ function_ = new(isolate_->zone()) VariableProxy(isolate_, function_var);
+ return function_var;
}
-void Scope::DeclareParameter(Handle<String> name) {
+void Scope::DeclareParameter(Handle<String> name, Variable::Mode mode) {
ASSERT(!already_resolved());
ASSERT(is_function_scope());
Variable* var =
- variables_.Declare(this, name, Variable::VAR, true, Variable::NORMAL);
+ variables_.Declare(this, name, mode, true, Variable::NORMAL);
params_.Add(var);
}
@@ -407,7 +437,8 @@ Variable* Scope::DeclareLocal(Handle<String> name, Variable::Mode mode) {
Variable* Scope::DeclareGlobal(Handle<String> name) {
ASSERT(is_global_scope());
- return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL, true,
+ return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL,
+ true,
Variable::NORMAL);
}
@@ -440,8 +471,11 @@ void Scope::RemoveUnresolved(VariableProxy* var) {
Variable* Scope::NewTemporary(Handle<String> name) {
ASSERT(!already_resolved());
- Variable* var =
- new Variable(this, name, Variable::TEMPORARY, true, Variable::NORMAL);
+ Variable* var = new Variable(this,
+ name,
+ Variable::TEMPORARY,
+ true,
+ Variable::NORMAL);
temps_.Add(var);
return var;
}
@@ -467,6 +501,28 @@ void Scope::VisitIllegalRedeclaration(AstVisitor* visitor) {
}
+Declaration* Scope::CheckConflictingVarDeclarations() {
+ int length = decls_.length();
+ for (int i = 0; i < length; i++) {
+ Declaration* decl = decls_[i];
+ if (decl->mode() != Variable::VAR) continue;
+ Handle<String> name = decl->proxy()->name();
+ bool cond = true;
+ for (Scope* scope = decl->scope(); cond ; scope = scope->outer_scope_) {
+ // There is a conflict if there exists a non-VAR binding.
+ Variable* other_var = scope->variables_.Lookup(name);
+ if (other_var != NULL && other_var->mode() != Variable::VAR) {
+ return decl;
+ }
+
+ // Include declaration scope in the iteration but stop after.
+ if (!scope->is_block_scope() && !scope->is_catch_scope()) cond = false;
+ }
+ }
+ return NULL;
+}
+
+
template<class Allocator>
void Scope::CollectUsedVariables(List<Variable*, Allocator>* locals) {
// Collect variables in this scope.
@@ -612,17 +668,35 @@ static void PrintName(Handle<String> name) {
}
-static void PrintVar(PrettyPrinter* printer, int indent, Variable* var) {
- if (var->is_used() || var->rewrite() != NULL) {
+static void PrintLocation(Variable* var) {
+ switch (var->location()) {
+ case Variable::UNALLOCATED:
+ break;
+ case Variable::PARAMETER:
+ PrintF("parameter[%d]", var->index());
+ break;
+ case Variable::LOCAL:
+ PrintF("local[%d]", var->index());
+ break;
+ case Variable::CONTEXT:
+ PrintF("context[%d]", var->index());
+ break;
+ case Variable::LOOKUP:
+ PrintF("lookup");
+ break;
+ }
+}
+
+
+static void PrintVar(int indent, Variable* var) {
+ if (var->is_used() || !var->IsUnallocated()) {
Indent(indent, Variable::Mode2String(var->mode()));
PrintF(" ");
PrintName(var->name());
PrintF("; // ");
- if (var->rewrite() != NULL) {
- PrintF("%s, ", printer->Print(var->rewrite()));
- if (var->is_accessed_from_inner_function_scope()) PrintF(", ");
- }
+ PrintLocation(var);
if (var->is_accessed_from_inner_function_scope()) {
+ if (!var->IsUnallocated()) PrintF(", ");
PrintF("inner scope access");
}
PrintF("\n");
@@ -630,10 +704,10 @@ static void PrintVar(PrettyPrinter* printer, int indent, Variable* var) {
}
-static void PrintMap(PrettyPrinter* printer, int indent, VariableMap* map) {
+static void PrintMap(int indent, VariableMap* map) {
for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) {
Variable* var = reinterpret_cast<Variable*>(p->value);
- PrintVar(printer, indent, var);
+ PrintVar(indent, var);
}
}
@@ -690,25 +764,24 @@ void Scope::Print(int n) {
PrintF("%d heap slots\n", num_heap_slots_); }
// Print locals.
- PrettyPrinter printer;
Indent(n1, "// function var\n");
if (function_ != NULL) {
- PrintVar(&printer, n1, function_);
+ PrintVar(n1, function_->var());
}
Indent(n1, "// temporary vars\n");
for (int i = 0; i < temps_.length(); i++) {
- PrintVar(&printer, n1, temps_[i]);
+ PrintVar(n1, temps_[i]);
}
Indent(n1, "// local vars\n");
- PrintMap(&printer, n1, &variables_);
+ PrintMap(n1, &variables_);
Indent(n1, "// dynamic vars\n");
if (dynamics_ != NULL) {
- PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC));
- PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC_LOCAL));
- PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC_GLOBAL));
+ PrintMap(n1, dynamics_->GetMap(Variable::DYNAMIC));
+ PrintMap(n1, dynamics_->GetMap(Variable::DYNAMIC_LOCAL));
+ PrintMap(n1, dynamics_->GetMap(Variable::DYNAMIC_GLOBAL));
}
// Print inner scopes (disable by providing negative n).
@@ -732,7 +805,7 @@ Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) {
// Declare a new non-local.
var = map->Declare(NULL, name, mode, true, Variable::NORMAL);
// Allocate it by giving it a dynamic lookup.
- var->set_rewrite(NewSlot(var, Slot::LOOKUP, -1));
+ var->AllocateTo(Variable::LOOKUP, -1);
}
return var;
}
@@ -774,7 +847,7 @@ Variable* Scope::LookupRecursive(Handle<String> name,
// the name of named function literal is kept in an intermediate scope
// in between this scope and the next outer scope.)
if (function_ != NULL && function_->name().is_identical_to(name)) {
- var = function_;
+ var = function_->var();
} else if (outer_scope_ != NULL) {
var = outer_scope_->LookupRecursive(
@@ -992,12 +1065,12 @@ bool Scope::HasArgumentsParameter() {
void Scope::AllocateStackSlot(Variable* var) {
- var->set_rewrite(NewSlot(var, Slot::LOCAL, num_stack_slots_++));
+ var->AllocateTo(Variable::LOCAL, num_stack_slots_++);
}
void Scope::AllocateHeapSlot(Variable* var) {
- var->set_rewrite(NewSlot(var, Slot::CONTEXT, num_heap_slots_++));
+ var->AllocateTo(Variable::CONTEXT, num_heap_slots_++);
}
@@ -1043,14 +1116,14 @@ void Scope::AllocateParameterLocals() {
if (MustAllocate(var)) {
if (MustAllocateInContext(var)) {
- ASSERT(var->rewrite() == NULL || var->IsContextSlot());
- if (var->rewrite() == NULL) {
+ ASSERT(var->IsUnallocated() || var->IsContextSlot());
+ if (var->IsUnallocated()) {
AllocateHeapSlot(var);
}
} else {
- ASSERT(var->rewrite() == NULL || var->IsParameter());
- if (var->rewrite() == NULL) {
- var->set_rewrite(NewSlot(var, Slot::PARAMETER, i));
+ ASSERT(var->IsUnallocated() || var->IsParameter());
+ if (var->IsUnallocated()) {
+ var->AllocateTo(Variable::PARAMETER, i);
}
}
}
@@ -1060,11 +1133,9 @@ void Scope::AllocateParameterLocals() {
void Scope::AllocateNonParameterLocal(Variable* var) {
ASSERT(var->scope() == this);
- ASSERT(var->rewrite() == NULL ||
- !var->IsVariable(isolate_->factory()->result_symbol()) ||
- var->AsSlot() == NULL ||
- var->AsSlot()->type() != Slot::LOCAL);
- if (var->rewrite() == NULL && MustAllocate(var)) {
+ ASSERT(!var->IsVariable(isolate_->factory()->result_symbol()) ||
+ !var->IsStackLocal());
+ if (var->IsUnallocated() && MustAllocate(var)) {
if (MustAllocateInContext(var)) {
AllocateHeapSlot(var);
} else {
@@ -1092,7 +1163,7 @@ void Scope::AllocateNonParameterLocals() {
// because of the current ScopeInfo implementation (see
// ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
if (function_ != NULL) {
- AllocateNonParameterLocal(function_);
+ AllocateNonParameterLocal(function_->var());
}
}
diff --git a/deps/v8/src/scopes.h b/deps/v8/src/scopes.h
index c2c41799b9..2917a63bba 100644
--- a/deps/v8/src/scopes.h
+++ b/deps/v8/src/scopes.h
@@ -112,6 +112,11 @@ class Scope: public ZoneObject {
void Initialize(bool inside_with);
+ // Checks if the block scope is redundant, i.e. it does not contain any
+ // block scoped declarations. In that case it is removed from the scope
+ // tree and its children are reparented.
+ Scope* FinalizeBlockScope();
+
// ---------------------------------------------------------------------------
// Declarations
@@ -130,7 +135,7 @@ class Scope: public ZoneObject {
// Declare a parameter in this scope. When there are duplicated
// parameters the rightmost one 'wins'. However, the implementation
// expects all parameters to be declared and from left to right.
- void DeclareParameter(Handle<String> name);
+ void DeclareParameter(Handle<String> name, Variable::Mode mode);
// Declare a local variable in this scope. If the variable has been
// declared before, the previously declared variable is returned.
@@ -182,6 +187,10 @@ class Scope: public ZoneObject {
// Check if the scope has (at least) one illegal redeclaration.
bool HasIllegalRedeclaration() const { return illegal_redecl_ != NULL; }
+ // For harmony block scoping mode: Check if the scope has conflicting var
+ // declarations, i.e. a var declaration that has been hoisted from a nested
+ // scope over a let binding of the same name.
+ Declaration* CheckConflictingVarDeclarations();
// ---------------------------------------------------------------------------
// Scope-specific info.
@@ -235,7 +244,7 @@ class Scope: public ZoneObject {
// The variable holding the function literal for named function
// literals, or NULL.
// Only valid for function scopes.
- Variable* function() const {
+ VariableProxy* function() const {
ASSERT(is_function_scope());
return function_;
}
@@ -354,7 +363,7 @@ class Scope: public ZoneObject {
// Convenience variable.
Variable* receiver_;
// Function variable, if any; function scopes only.
- Variable* function_;
+ VariableProxy* function_;
// Convenience variable; function scopes only.
Variable* arguments_;
@@ -435,10 +444,6 @@ class Scope: public ZoneObject {
// Construct a catch scope with a binding for the name.
Scope(Scope* inner_scope, Handle<String> catch_variable_name);
- inline Slot* NewSlot(Variable* var, Slot::Type type, int index) {
- return new(isolate_->zone()) Slot(isolate_, var, type, index);
- }
-
void AddInnerScope(Scope* inner_scope) {
if (inner_scope != NULL) {
inner_scopes_.Add(inner_scope);
diff --git a/deps/v8/src/spaces-inl.h b/deps/v8/src/spaces-inl.h
index 069d01db24..35d7224099 100644
--- a/deps/v8/src/spaces-inl.h
+++ b/deps/v8/src/spaces-inl.h
@@ -155,7 +155,8 @@ uint32_t Page::GetRegionMaskForAddress(Address addr) {
uint32_t Page::GetRegionMaskForSpan(Address start, int length_in_bytes) {
uint32_t result = 0;
- if (length_in_bytes >= kPageSize) {
+ static const intptr_t kRegionMask = (1 << kRegionSizeLog2) - 1;
+ if (length_in_bytes + (OffsetFrom(start) & kRegionMask) >= kPageSize) {
result = kAllRegionsDirtyMarks;
} else if (length_in_bytes > 0) {
int start_region = GetRegionNumberForAddress(start);
diff --git a/deps/v8/src/string.js b/deps/v8/src/string.js
index a70eeade83..6f68ce0890 100644
--- a/deps/v8/src/string.js
+++ b/deps/v8/src/string.js
@@ -911,50 +911,47 @@ function ReplaceResultBuilder(str) {
this.special_string = str;
}
-ReplaceResultBuilder.prototype.__proto__ = null;
-
-
-ReplaceResultBuilder.prototype.add = function(str) {
- str = TO_STRING_INLINE(str);
- if (str.length > 0) this.elements.push(str);
-}
-
-
-ReplaceResultBuilder.prototype.addSpecialSlice = function(start, end) {
- var len = end - start;
- if (start < 0 || len <= 0) return;
- if (start < 0x80000 && len < 0x800) {
- this.elements.push((start << 11) | len);
- } else {
- // 0 < len <= String::kMaxLength and Smi::kMaxValue >= String::kMaxLength,
- // so -len is a smi.
+SetUpLockedPrototype(ReplaceResultBuilder,
+ $Array("elements", "special_string"), $Array(
+ "add", function(str) {
+ str = TO_STRING_INLINE(str);
+ if (str.length > 0) this.elements.push(str);
+ },
+ "addSpecialSlice", function(start, end) {
+ var len = end - start;
+ if (start < 0 || len <= 0) return;
+ if (start < 0x80000 && len < 0x800) {
+ this.elements.push((start << 11) | len);
+ } else {
+ // 0 < len <= String::kMaxLength and Smi::kMaxValue >= String::kMaxLength,
+ // so -len is a smi.
+ var elements = this.elements;
+ elements.push(-len);
+ elements.push(start);
+ }
+ },
+ "generate", function() {
var elements = this.elements;
- elements.push(-len);
- elements.push(start);
+ return %StringBuilderConcat(elements, elements.length, this.special_string);
}
-}
-
-
-ReplaceResultBuilder.prototype.generate = function() {
- var elements = this.elements;
- return %StringBuilderConcat(elements, elements.length, this.special_string);
-}
+));
// -------------------------------------------------------------------
-function SetupString() {
- // Setup the constructor property on the String prototype object.
+function SetUpString() {
+ %CheckIsBootstrapping();
+ // Set up the constructor property on the String prototype object.
%SetProperty($String.prototype, "constructor", $String, DONT_ENUM);
- // Setup the non-enumerable functions on the String object.
+ // Set up the non-enumerable functions on the String object.
InstallFunctions($String, DONT_ENUM, $Array(
"fromCharCode", StringFromCharCode
));
- // Setup the non-enumerable functions on the String prototype object.
+ // Set up the non-enumerable functions on the String prototype object.
InstallFunctionsOnHiddenPrototype($String.prototype, DONT_ENUM, $Array(
"valueOf", StringValueOf,
"toString", StringToString,
@@ -994,5 +991,4 @@ function SetupString() {
));
}
-
-SetupString();
+SetUpString();
diff --git a/deps/v8/src/stub-cache.h b/deps/v8/src/stub-cache.h
index a97a4cdab2..dd06a1c078 100644
--- a/deps/v8/src/stub-cache.h
+++ b/deps/v8/src/stub-cache.h
@@ -357,7 +357,7 @@ class StubCache {
// shift are equal. Shifting down the length field to get the
// hash code would effectively throw away two bits of the hash
// code.
- ASSERT(kHeapObjectTagSize == String::kHashShift);
+ STATIC_ASSERT(kHeapObjectTagSize == String::kHashShift);
// Compute the hash of the name (use entire hash field).
ASSERT(name->HasHashCode());
uint32_t field = name->hash_field();
diff --git a/deps/v8/src/token.h b/deps/v8/src/token.h
index 33af7fe6bf..eb825c1a74 100644
--- a/deps/v8/src/token.h
+++ b/deps/v8/src/token.h
@@ -71,6 +71,7 @@ namespace internal {
/* this block of enum values being contiguous and sorted in the */ \
/* same order! */ \
T(INIT_VAR, "=init_var", 2) /* AST-use only. */ \
+ T(INIT_LET, "=init_let", 2) /* AST-use only. */ \
T(INIT_CONST, "=init_const", 2) /* AST-use only. */ \
T(ASSIGN, "=", 2) \
T(ASSIGN_BIT_OR, "|=", 2) \
diff --git a/deps/v8/src/uri.js b/deps/v8/src/uri.js
index 72ca6f1565..c910d756b4 100644
--- a/deps/v8/src/uri.js
+++ b/deps/v8/src/uri.js
@@ -392,8 +392,9 @@ function URIUnescape(str) {
// -------------------------------------------------------------------
-function SetupURI() {
- // Setup non-enumerable URI functions on the global object and set
+function SetUpUri() {
+ %CheckIsBootstrapping();
+ // Set up non-enumerable URI functions on the global object and set
// their names.
InstallFunctions(global, DONT_ENUM, $Array(
"escape", URIEscape,
@@ -405,4 +406,4 @@ function SetupURI() {
));
}
-SetupURI();
+SetUpUri();
diff --git a/deps/v8/src/v8natives.js b/deps/v8/src/v8natives.js
index 035fd2e2be..1616ac366b 100644
--- a/deps/v8/src/v8natives.js
+++ b/deps/v8/src/v8natives.js
@@ -41,7 +41,6 @@
const $isNaN = GlobalIsNaN;
const $isFinite = GlobalIsFinite;
-
// ----------------------------------------------------------------------------
@@ -66,28 +65,56 @@ function InstallFunctions(object, attributes, functions) {
// functions on String.prototype etc. and then restore the old function
// with delete. See http://code.google.com/p/chromium/issues/detail?id=1717
function InstallFunctionsOnHiddenPrototype(object, attributes, functions) {
+ %CheckIsBootstrapping();
var hidden_prototype = new $Object();
%SetHiddenPrototype(object, hidden_prototype);
InstallFunctions(hidden_prototype, attributes, functions);
}
+// Prevents changes to the prototype of a built-infunction.
+// The "prototype" property of the function object is made non-configurable,
+// and the prototype object is made non-extensible. The latter prevents
+// changing the __proto__ property.
+function SetUpLockedPrototype(constructor, fields, methods) {
+ %CheckIsBootstrapping();
+ var prototype = constructor.prototype;
+ // Install functions first, because this function is used to initialize
+ // PropertyDescriptor itself.
+ var property_count = (methods.length >> 1) + (fields ? fields.length : 0);
+ if (property_count >= 4) {
+ %OptimizeObjectForAddingMultipleProperties(prototype, property_count);
+ }
+ if (fields) {
+ for (var i = 0; i < fields.length; i++) {
+ %SetProperty(prototype, fields[i], void 0, DONT_ENUM | DONT_DELETE);
+ }
+ }
+ for (var i = 0; i < methods.length; i += 2) {
+ var key = methods[i];
+ var f = methods[i + 1];
+ %SetProperty(prototype, key, f, DONT_ENUM | DONT_DELETE | READ_ONLY);
+ %SetNativeFlag(f);
+ }
+ prototype.__proto__ = null;
+ %ToFastProperties(prototype);
+}
+
+
// ----------------------------------------------------------------------------
// ECMA 262 - 15.1.4
function GlobalIsNaN(number) {
- var n = ToNumber(number);
- return NUMBER_IS_NAN(n);
+ if (!IS_NUMBER(number)) number = NonNumberToNumber(number);
+ return NUMBER_IS_NAN(number);
}
// ECMA 262 - 15.1.5
function GlobalIsFinite(number) {
if (!IS_NUMBER(number)) number = NonNumberToNumber(number);
-
- // NaN - NaN == NaN, Infinity - Infinity == NaN, -Infinity - -Infinity == NaN.
- return %_IsSmi(number) || number - number == 0;
+ return NUMBER_IS_FINITE(number);
}
@@ -106,13 +133,16 @@ function GlobalParseInt(string, radix) {
// Truncate number.
return string | 0;
}
+ string = TO_STRING_INLINE(string);
radix = radix | 0;
} else {
+ // The spec says ToString should be evaluated before ToInt32.
+ string = TO_STRING_INLINE(string);
radix = TO_INT32(radix);
if (!(radix == 0 || (2 <= radix && radix <= 36)))
return $NaN;
}
- string = TO_STRING_INLINE(string);
+
if (%_HasCachedArrayIndex(string) &&
(radix == 0 || radix == 10)) {
return %_GetCachedArrayIndex(string);
@@ -159,8 +189,9 @@ function GlobalEval(x) {
// ----------------------------------------------------------------------------
-
-function SetupGlobal() {
+// Set up global object.
+function SetUpGlobal() {
+ %CheckIsBootstrapping();
// ECMA 262 - 15.1.1.1.
%SetProperty(global, "NaN", $NaN, DONT_ENUM | DONT_DELETE);
@@ -170,7 +201,7 @@ function SetupGlobal() {
// ECMA-262 - 15.1.1.3.
%SetProperty(global, "undefined", void 0, DONT_ENUM | DONT_DELETE);
- // Setup non-enumerable function on the global object.
+ // Set up non-enumerable function on the global object.
InstallFunctions(global, DONT_ENUM, $Array(
"isNaN", GlobalIsNaN,
"isFinite", GlobalIsFinite,
@@ -180,8 +211,7 @@ function SetupGlobal() {
));
}
-SetupGlobal();
-
+SetUpGlobal();
// ----------------------------------------------------------------------------
// Boolean (first part of definition)
@@ -478,106 +508,83 @@ function PropertyDescriptor() {
this.hasSetter_ = false;
}
-PropertyDescriptor.prototype.__proto__ = null;
-
-PropertyDescriptor.prototype.toString = function() {
- return "[object PropertyDescriptor]";
-};
-
-PropertyDescriptor.prototype.setValue = function(value) {
- this.value_ = value;
- this.hasValue_ = true;
-}
-
-
-PropertyDescriptor.prototype.getValue = function() {
- return this.value_;
-}
-
-
-PropertyDescriptor.prototype.hasValue = function() {
- return this.hasValue_;
-}
-
-
-PropertyDescriptor.prototype.setEnumerable = function(enumerable) {
- this.enumerable_ = enumerable;
- this.hasEnumerable_ = true;
-}
-
-
-PropertyDescriptor.prototype.isEnumerable = function () {
- return this.enumerable_;
-}
-
-
-PropertyDescriptor.prototype.hasEnumerable = function() {
- return this.hasEnumerable_;
-}
-
-
-PropertyDescriptor.prototype.setWritable = function(writable) {
- this.writable_ = writable;
- this.hasWritable_ = true;
-}
-
-
-PropertyDescriptor.prototype.isWritable = function() {
- return this.writable_;
-}
-
-
-PropertyDescriptor.prototype.hasWritable = function() {
- return this.hasWritable_;
-}
-
-
-PropertyDescriptor.prototype.setConfigurable = function(configurable) {
- this.configurable_ = configurable;
- this.hasConfigurable_ = true;
-}
-
-
-PropertyDescriptor.prototype.hasConfigurable = function() {
- return this.hasConfigurable_;
-}
-
-
-PropertyDescriptor.prototype.isConfigurable = function() {
- return this.configurable_;
-}
-
-
-PropertyDescriptor.prototype.setGet = function(get) {
- this.get_ = get;
- this.hasGetter_ = true;
-}
-
-
-PropertyDescriptor.prototype.getGet = function() {
- return this.get_;
-}
-
-
-PropertyDescriptor.prototype.hasGetter = function() {
- return this.hasGetter_;
-}
-
-
-PropertyDescriptor.prototype.setSet = function(set) {
- this.set_ = set;
- this.hasSetter_ = true;
-}
-
-
-PropertyDescriptor.prototype.getSet = function() {
- return this.set_;
-}
-
-
-PropertyDescriptor.prototype.hasSetter = function() {
- return this.hasSetter_;
-}
+SetUpLockedPrototype(PropertyDescriptor, $Array(
+ "value_",
+ "hasValue_",
+ "writable_",
+ "hasWritable_",
+ "enumerable_",
+ "hasEnumerable_",
+ "configurable_",
+ "hasConfigurable_",
+ "get_",
+ "hasGetter_",
+ "set_",
+ "hasSetter_"
+ ), $Array(
+ "toString", function() {
+ return "[object PropertyDescriptor]";
+ },
+ "setValue", function(value) {
+ this.value_ = value;
+ this.hasValue_ = true;
+ },
+ "getValue", function() {
+ return this.value_;
+ },
+ "hasValue", function() {
+ return this.hasValue_;
+ },
+ "setEnumerable", function(enumerable) {
+ this.enumerable_ = enumerable;
+ this.hasEnumerable_ = true;
+ },
+ "isEnumerable", function () {
+ return this.enumerable_;
+ },
+ "hasEnumerable", function() {
+ return this.hasEnumerable_;
+ },
+ "setWritable", function(writable) {
+ this.writable_ = writable;
+ this.hasWritable_ = true;
+ },
+ "isWritable", function() {
+ return this.writable_;
+ },
+ "hasWritable", function() {
+ return this.hasWritable_;
+ },
+ "setConfigurable", function(configurable) {
+ this.configurable_ = configurable;
+ this.hasConfigurable_ = true;
+ },
+ "hasConfigurable", function() {
+ return this.hasConfigurable_;
+ },
+ "isConfigurable", function() {
+ return this.configurable_;
+ },
+ "setGet", function(get) {
+ this.get_ = get;
+ this.hasGetter_ = true;
+ },
+ "getGet", function() {
+ return this.get_;
+ },
+ "hasGetter", function() {
+ return this.hasGetter_;
+ },
+ "setSet", function(set) {
+ this.set_ = set;
+ this.hasSetter_ = true;
+ },
+ "getSet", function() {
+ return this.set_;
+ },
+ "hasSetter", function() {
+ return this.hasSetter_;
+ }));
// Converts an array returned from Runtime_GetOwnProperty to an actual
@@ -1165,10 +1172,11 @@ function ObjectIsExtensible(obj) {
%SetExpectedNumberOfProperties($Object, 4);
// ----------------------------------------------------------------------------
+// Object
-
-function SetupObject() {
- // Setup non-enumerable functions on the Object.prototype object.
+function SetUpObject() {
+ %CheckIsBootstrapping();
+ // Set Up non-enumerable functions on the Object.prototype object.
InstallFunctions($Object.prototype, DONT_ENUM, $Array(
"toString", ObjectToString,
"toLocaleString", ObjectToLocaleString,
@@ -1198,8 +1206,7 @@ function SetupObject() {
));
}
-SetupObject();
-
+SetUpObject();
// ----------------------------------------------------------------------------
// Boolean
@@ -1230,14 +1237,16 @@ function BooleanValueOf() {
// ----------------------------------------------------------------------------
-function SetupBoolean() {
+function SetUpBoolean () {
+ %CheckIsBootstrapping();
InstallFunctions($Boolean.prototype, DONT_ENUM, $Array(
"toString", BooleanToString,
"valueOf", BooleanValueOf
));
}
-SetupBoolean();
+SetUpBoolean();
+
// ----------------------------------------------------------------------------
// Number
@@ -1351,9 +1360,10 @@ function NumberToPrecision(precision) {
// ----------------------------------------------------------------------------
-function SetupNumber() {
+function SetUpNumber() {
+ %CheckIsBootstrapping();
%OptimizeObjectForAddingMultipleProperties($Number.prototype, 8);
- // Setup the constructor property on the Number prototype object.
+ // Set up the constructor property on the Number prototype object.
%SetProperty($Number.prototype, "constructor", $Number, DONT_ENUM);
%OptimizeObjectForAddingMultipleProperties($Number, 5);
@@ -1382,7 +1392,7 @@ function SetupNumber() {
DONT_ENUM | DONT_DELETE | READ_ONLY);
%ToFastProperties($Number);
- // Setup non-enumerable functions on the Number prototype object.
+ // Set up non-enumerable functions on the Number prototype object.
InstallFunctions($Number.prototype, DONT_ENUM, $Array(
"toString", NumberToString,
"toLocaleString", NumberToLocaleString,
@@ -1393,7 +1403,7 @@ function SetupNumber() {
));
}
-SetupNumber();
+SetUpNumber();
// ----------------------------------------------------------------------------
@@ -1522,11 +1532,12 @@ function NewFunction(arg1) { // length == 1
// ----------------------------------------------------------------------------
-function SetupFunction() {
+function SetUpFunction() {
+ %CheckIsBootstrapping();
InstallFunctions($Function.prototype, DONT_ENUM, $Array(
"bind", FunctionBind,
"toString", FunctionToString
));
}
-SetupFunction();
+SetUpFunction();
diff --git a/deps/v8/src/variables.cc b/deps/v8/src/variables.cc
index 69495bb40f..6cf6e0b04a 100644
--- a/deps/v8/src/variables.cc
+++ b/deps/v8/src/variables.cc
@@ -53,34 +53,6 @@ const char* Variable::Mode2String(Mode mode) {
}
-Property* Variable::AsProperty() const {
- return rewrite_ == NULL ? NULL : rewrite_->AsProperty();
-}
-
-
-Slot* Variable::AsSlot() const { return rewrite_; }
-
-
-bool Variable::IsStackAllocated() const {
- return rewrite_ != NULL && rewrite_->IsStackAllocated();
-}
-
-
-bool Variable::IsParameter() const {
- return rewrite_ != NULL && rewrite_->type() == Slot::PARAMETER;
-}
-
-
-bool Variable::IsStackLocal() const {
- return rewrite_ != NULL && rewrite_->type() == Slot::LOCAL;
-}
-
-
-bool Variable::IsContextSlot() const {
- return rewrite_ != NULL && rewrite_->type() == Slot::CONTEXT;
-}
-
-
Variable::Variable(Scope* scope,
Handle<String> name,
Mode mode,
@@ -90,8 +62,9 @@ Variable::Variable(Scope* scope,
name_(name),
mode_(mode),
kind_(kind),
+ location_(UNALLOCATED),
+ index_(-1),
local_if_not_shadowed_(NULL),
- rewrite_(NULL),
is_valid_LHS_(is_valid_LHS),
is_accessed_from_inner_function_scope_(false),
is_used_(false) {
diff --git a/deps/v8/src/variables.h b/deps/v8/src/variables.h
index e92ba6d39a..a4ead51b89 100644
--- a/deps/v8/src/variables.h
+++ b/deps/v8/src/variables.h
@@ -74,6 +74,33 @@ class Variable: public ZoneObject {
ARGUMENTS
};
+ enum Location {
+ // Before and during variable allocation, a variable whose location is
+ // not yet determined. After allocation, a variable looked up as a
+ // property on the global object (and possibly absent). name() is the
+ // variable name, index() is invalid.
+ UNALLOCATED,
+
+ // A slot in the parameter section on the stack. index() is the
+ // parameter index, counting left-to-right. The reciever is index -1;
+ // the first parameter is index 0.
+ PARAMETER,
+
+ // A slot in the local section on the stack. index() is the variable
+ // index in the stack frame, starting at 0.
+ LOCAL,
+
+ // An indexed slot in a heap context. index() is the variable index in
+ // the context object on the heap, starting at 0. scope() is the
+ // corresponding scope.
+ CONTEXT,
+
+ // A named slot in a heap context. name() is the variable name in the
+ // context object on the heap, with lookup starting at the current
+ // context. index() is invalid.
+ LOOKUP
+ };
+
Variable(Scope* scope,
Handle<String> name,
Mode mode,
@@ -83,10 +110,6 @@ class Variable: public ZoneObject {
// Printing support
static const char* Mode2String(Mode mode);
- // Type testing & conversion. Global variables are not slots.
- Property* AsProperty() const;
- Slot* AsSlot() const;
-
bool IsValidLeftHandSide() { return is_valid_LHS_; }
// The source code for an eval() call may refer to a variable that is
@@ -111,10 +134,12 @@ class Variable: public ZoneObject {
return !is_this() && name().is_identical_to(n);
}
- bool IsStackAllocated() const;
- bool IsParameter() const; // Includes 'this'.
- bool IsStackLocal() const;
- bool IsContextSlot() const;
+ bool IsUnallocated() const { return location_ == UNALLOCATED; }
+ bool IsParameter() const { return location_ == PARAMETER; }
+ bool IsStackLocal() const { return location_ == LOCAL; }
+ bool IsStackAllocated() const { return IsParameter() || IsStackLocal(); }
+ bool IsContextSlot() const { return location_ == CONTEXT; }
+ bool IsLookupSlot() const { return location_ == LOOKUP; }
bool is_dynamic() const {
return (mode_ == DYNAMIC ||
@@ -141,20 +166,24 @@ class Variable: public ZoneObject {
local_if_not_shadowed_ = local;
}
- Slot* rewrite() const { return rewrite_; }
- void set_rewrite(Slot* slot) { rewrite_ = slot; }
+ Location location() const { return location_; }
+ int index() const { return index_; }
+
+ void AllocateTo(Location location, int index) {
+ location_ = location;
+ index_ = index;
+ }
private:
Scope* scope_;
Handle<String> name_;
Mode mode_;
Kind kind_;
+ Location location_;
+ int index_;
Variable* local_if_not_shadowed_;
- // Code generation.
- Slot* rewrite_;
-
// Valid as a LHS? (const and this are not valid LHS, for example)
bool is_valid_LHS_;
diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc
index 3fd0fd564e..aeab053f0f 100644
--- a/deps/v8/src/version.cc
+++ b/deps/v8/src/version.cc
@@ -33,9 +33,9 @@
// NOTE these macros are used by the SCons build script so their names
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3
-#define MINOR_VERSION 5
-#define BUILD_NUMBER 9
-#define PATCH_LEVEL 1
+#define MINOR_VERSION 6
+#define BUILD_NUMBER 1
+#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0
diff --git a/deps/v8/src/weakmap.js b/deps/v8/src/weakmap.js
index 70210b98de..6c15e30fb6 100644
--- a/deps/v8/src/weakmap.js
+++ b/deps/v8/src/weakmap.js
@@ -80,21 +80,22 @@ function WeakMapDelete(key) {
// -------------------------------------------------------------------
-function SetupWeakMap() {
- // Setup the WeakMap constructor function.
+(function () {
+ %CheckIsBootstrapping();
+ // Set up the WeakMap constructor function.
%SetCode($WeakMap, WeakMapConstructor);
- // Setup the WeakMap prototype object.
+ // Set up the WeakMap prototype object.
%FunctionSetPrototype($WeakMap, new $WeakMap());
- // Setup the non-enumerable functions on the WeakMap prototype object.
+ // Set up the constructor property on the WeakMap prototype object.
+ %SetProperty($WeakMap.prototype, "constructor", $WeakMap, DONT_ENUM);
+
+ // Set up the non-enumerable functions on the WeakMap prototype object.
InstallFunctionsOnHiddenPrototype($WeakMap.prototype, DONT_ENUM, $Array(
"get", WeakMapGet,
"set", WeakMapSet,
"has", WeakMapHas,
"delete", WeakMapDelete
));
-}
-
-
-SetupWeakMap();
+})();
diff --git a/deps/v8/src/x64/builtins-x64.cc b/deps/v8/src/x64/builtins-x64.cc
index 076398906c..7c6f7e327c 100644
--- a/deps/v8/src/x64/builtins-x64.cc
+++ b/deps/v8/src/x64/builtins-x64.cc
@@ -139,7 +139,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// rdi: constructor
__ movq(rax, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a NULL and a Smi
- ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTag == 0);
__ JumpIfSmi(rax, &rt_call);
// rdi: constructor
// rax: initial map (if proven valid below)
@@ -1283,7 +1283,7 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
// Initial map for the builtin Array functions should be maps.
__ movq(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a NULL and a Smi.
- ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTag == 0);
Condition not_smi = NegateCondition(masm->CheckSmi(rbx));
__ Check(not_smi, "Unexpected initial map for Array function");
__ CmpObjectType(rbx, MAP_TYPE, rcx);
@@ -1317,7 +1317,7 @@ void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) {
// Initial map for the builtin Array function should be a map.
__ movq(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a NULL and a Smi.
- ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTag == 0);
Condition not_smi = NegateCondition(masm->CheckSmi(rbx));
__ Check(not_smi, "Unexpected initial map for Array function");
__ CmpObjectType(rbx, MAP_TYPE, rcx);
diff --git a/deps/v8/src/x64/code-stubs-x64.cc b/deps/v8/src/x64/code-stubs-x64.cc
index 0b785c5dd6..2ae4d9f7ab 100644
--- a/deps/v8/src/x64/code-stubs-x64.cc
+++ b/deps/v8/src/x64/code-stubs-x64.cc
@@ -2470,8 +2470,8 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// a sequential string or an external string.
// In the case of a sliced string its offset has to be taken into account.
Label cons_string, check_encoding;
- STATIC_ASSERT((kConsStringTag < kExternalStringTag));
- STATIC_ASSERT((kSlicedStringTag > kExternalStringTag));
+ STATIC_ASSERT(kConsStringTag < kExternalStringTag);
+ STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
__ cmpq(rbx, Immediate(kExternalStringTag));
__ j(less, &cons_string, Label::kNear);
__ j(equal, &runtime);
@@ -3903,8 +3903,8 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
// Handle non-flat strings.
__ and_(result_, Immediate(kStringRepresentationMask));
- STATIC_ASSERT((kConsStringTag < kExternalStringTag));
- STATIC_ASSERT((kSlicedStringTag > kExternalStringTag));
+ STATIC_ASSERT(kConsStringTag < kExternalStringTag);
+ STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
__ cmpb(result_, Immediate(kExternalStringTag));
__ j(greater, &sliced_string);
__ j(equal, &call_runtime_);
@@ -3938,7 +3938,8 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
// Check for 1-byte or 2-byte string.
__ bind(&flat_string);
- STATIC_ASSERT(kAsciiStringTag != 0);
+ STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
+ STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
__ testb(result_, Immediate(kStringEncodingMask));
__ j(not_zero, &ascii_string);
@@ -4195,8 +4196,9 @@ void StringAddStub::Generate(MacroAssembler* masm) {
Label non_ascii, allocated, ascii_data;
__ movl(rcx, r8);
__ and_(rcx, r9);
- STATIC_ASSERT(kStringEncodingMask == kAsciiStringTag);
- __ testl(rcx, Immediate(kAsciiStringTag));
+ STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
+ STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
+ __ testl(rcx, Immediate(kStringEncodingMask));
__ j(zero, &non_ascii);
__ bind(&ascii_data);
// Allocate an acsii cons string.
@@ -4225,7 +4227,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
__ cmpb(r8, Immediate(kAsciiStringTag | kAsciiDataHintTag));
__ j(equal, &ascii_data);
// Allocate a two byte cons string.
- __ AllocateConsString(rcx, rdi, no_reg, &string_add_runtime);
+ __ AllocateTwoByteConsString(rcx, rdi, no_reg, &string_add_runtime);
__ jmp(&allocated);
// Handle creating a flat result. First check that both strings are not
@@ -4254,10 +4256,11 @@ void StringAddStub::Generate(MacroAssembler* masm) {
// r8: instance type of first string
// r9: instance type of second string
Label non_ascii_string_add_flat_result;
- STATIC_ASSERT(kStringEncodingMask == kAsciiStringTag);
- __ testl(r8, Immediate(kAsciiStringTag));
+ STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
+ STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
+ __ testl(r8, Immediate(kStringEncodingMask));
__ j(zero, &non_ascii_string_add_flat_result);
- __ testl(r9, Immediate(kAsciiStringTag));
+ __ testl(r9, Immediate(kStringEncodingMask));
__ j(zero, &string_add_runtime);
__ bind(&make_flat_ascii_string);
@@ -4295,7 +4298,9 @@ void StringAddStub::Generate(MacroAssembler* masm) {
// r8: instance type of first string
// r9: instance type of first string
__ bind(&non_ascii_string_add_flat_result);
- __ and_(r9, Immediate(kAsciiStringTag));
+ STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
+ STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
+ __ and_(r9, Immediate(kStringEncodingMask));
__ j(not_zero, &string_add_runtime);
// Both strings are two byte strings. As they are short they are both
// flat.
@@ -4639,9 +4644,6 @@ void StringHelper::GenerateHashGetHash(MacroAssembler* masm,
void SubStringStub::Generate(MacroAssembler* masm) {
Label runtime;
- if (FLAG_string_slices) {
- __ jmp(&runtime);
- }
// Stack frame on entry.
// rsp[0]: return address
// rsp[8]: to
@@ -4707,7 +4709,82 @@ void SubStringStub::Generate(MacroAssembler* masm) {
__ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
__ Set(rcx, 2);
- __ bind(&result_longer_than_two);
+ if (FLAG_string_slices) {
+ Label copy_routine;
+ // If coming from the make_two_character_string path, the string
+ // is too short to be sliced anyways.
+ STATIC_ASSERT(2 < SlicedString::kMinLength);
+ __ jmp(&copy_routine);
+ __ bind(&result_longer_than_two);
+
+ // rax: string
+ // rbx: instance type
+ // rcx: sub string length
+ // rdx: from index (smi)
+ Label allocate_slice, sliced_string, seq_string;
+ __ cmpq(rcx, Immediate(SlicedString::kMinLength));
+ // Short slice. Copy instead of slicing.
+ __ j(less, &copy_routine);
+ STATIC_ASSERT(kSeqStringTag == 0);
+ __ testb(rbx, Immediate(kStringRepresentationMask));
+ __ j(zero, &seq_string, Label::kNear);
+ STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
+ STATIC_ASSERT(kIsIndirectStringMask != 0);
+ __ testb(rbx, Immediate(kIsIndirectStringMask));
+ // External string. Jump to runtime.
+ __ j(zero, &runtime);
+
+ __ testb(rbx, Immediate(kSlicedNotConsMask));
+ __ j(not_zero, &sliced_string, Label::kNear);
+ // Cons string. Check whether it is flat, then fetch first part.
+ __ CompareRoot(FieldOperand(rax, ConsString::kSecondOffset),
+ Heap::kEmptyStringRootIndex);
+ __ j(not_equal, &runtime);
+ __ movq(rdi, FieldOperand(rax, ConsString::kFirstOffset));
+ __ jmp(&allocate_slice, Label::kNear);
+
+ __ bind(&sliced_string);
+ // Sliced string. Fetch parent and correct start index by offset.
+ __ addq(rdx, FieldOperand(rax, SlicedString::kOffsetOffset));
+ __ movq(rdi, FieldOperand(rax, SlicedString::kParentOffset));
+ __ jmp(&allocate_slice, Label::kNear);
+
+ __ bind(&seq_string);
+ // Sequential string. Just move string to the right register.
+ __ movq(rdi, rax);
+
+ __ bind(&allocate_slice);
+ // edi: underlying subject string
+ // ebx: instance type of original subject string
+ // edx: offset
+ // ecx: length
+ // Allocate new sliced string. At this point we do not reload the instance
+ // type including the string encoding because we simply rely on the info
+ // provided by the original string. It does not matter if the original
+ // string's encoding is wrong because we always have to recheck encoding of
+ // the newly created string's parent anyways due to externalized strings.
+ Label two_byte_slice, set_slice_header;
+ STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
+ STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
+ __ testb(rbx, Immediate(kStringEncodingMask));
+ __ j(zero, &two_byte_slice, Label::kNear);
+ __ AllocateAsciiSlicedString(rax, rbx, no_reg, &runtime);
+ __ jmp(&set_slice_header, Label::kNear);
+ __ bind(&two_byte_slice);
+ __ AllocateTwoByteSlicedString(rax, rbx, no_reg, &runtime);
+ __ bind(&set_slice_header);
+ __ movq(FieldOperand(rax, SlicedString::kOffsetOffset), rdx);
+ __ Integer32ToSmi(rcx, rcx);
+ __ movq(FieldOperand(rax, SlicedString::kLengthOffset), rcx);
+ __ movq(FieldOperand(rax, SlicedString::kParentOffset), rdi);
+ __ movq(FieldOperand(rax, SlicedString::kHashFieldOffset),
+ Immediate(String::kEmptyHashField));
+ __ jmp(&return_rax);
+
+ __ bind(&copy_routine);
+ } else {
+ __ bind(&result_longer_than_two);
+ }
// rax: string
// rbx: instance type
diff --git a/deps/v8/src/x64/full-codegen-x64.cc b/deps/v8/src/x64/full-codegen-x64.cc
index dd35053a65..ba8e0f627e 100644
--- a/deps/v8/src/x64/full-codegen-x64.cc
+++ b/deps/v8/src/x64/full-codegen-x64.cc
@@ -51,8 +51,7 @@ static unsigned GetPropertyId(Property* property) {
class JumpPatchSite BASE_EMBEDDED {
public:
- explicit JumpPatchSite(MacroAssembler* masm)
- : masm_(masm) {
+ explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
#ifdef DEBUG
info_emitted_ = false;
#endif
@@ -187,14 +186,14 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
// Copy any necessary parameters into the context.
int num_parameters = info->scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) {
- Slot* slot = scope()->parameter(i)->AsSlot();
- if (slot != NULL && slot->type() == Slot::CONTEXT) {
+ Variable* var = scope()->parameter(i);
+ if (var->IsContextSlot()) {
int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(num_parameters - 1 - i) * kPointerSize;
// Load parameter from stack.
__ movq(rax, Operand(rbp, parameter_offset));
// Store it in the context.
- int context_offset = Context::SlotOffset(slot->index());
+ int context_offset = Context::SlotOffset(var->index());
__ movq(Operand(rsi, context_offset), rax);
// Update the write barrier. This clobbers all involved
// registers, so we have use a third register to avoid
@@ -232,7 +231,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
: ArgumentsAccessStub::NEW_NON_STRICT_SLOW);
__ CallStub(&stub);
- Move(arguments->AsSlot(), rax, rbx, rdx);
+ SetVar(arguments, rax, rbx, rdx);
}
if (FLAG_trace) {
@@ -244,18 +243,21 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
if (scope()->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ Declarations");
scope()->VisitIllegalRedeclaration(this);
+
} else {
+ PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
{ Comment cmnt(masm_, "[ Declarations");
// For named function expressions, declare the function name as a
// constant.
if (scope()->is_function_scope() && scope()->function() != NULL) {
- EmitDeclaration(scope()->function(), Variable::CONST, NULL);
+ int ignored = 0;
+ EmitDeclaration(scope()->function(), Variable::CONST, NULL, &ignored);
}
VisitDeclarations(scope()->declarations());
}
{ Comment cmnt(masm_, "[ Stack check");
- PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
+ PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS);
Label ok;
__ CompareRoot(rsp, Heap::kStackLimitRootIndex);
__ j(above_equal, &ok, Label::kNear);
@@ -355,24 +357,26 @@ void FullCodeGenerator::EmitReturnSequence() {
}
-void FullCodeGenerator::EffectContext::Plug(Slot* slot) const {
+void FullCodeGenerator::EffectContext::Plug(Variable* var) const {
+ ASSERT(var->IsStackAllocated() || var->IsContextSlot());
}
-void FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const {
- MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register());
- __ movq(result_register(), slot_operand);
+void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
+ ASSERT(var->IsStackAllocated() || var->IsContextSlot());
+ codegen()->GetVar(result_register(), var);
}
-void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const {
- MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register());
- __ push(slot_operand);
+void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
+ ASSERT(var->IsStackAllocated() || var->IsContextSlot());
+ MemOperand operand = codegen()->VarOperand(var, result_register());
+ __ push(operand);
}
-void FullCodeGenerator::TestContext::Plug(Slot* slot) const {
- codegen()->Move(result_register(), slot);
+void FullCodeGenerator::TestContext::Plug(Variable* var) const {
+ codegen()->GetVar(result_register(), var);
codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
codegen()->DoTest(this);
}
@@ -591,43 +595,53 @@ void FullCodeGenerator::Split(Condition cc,
}
-MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
- switch (slot->type()) {
- case Slot::PARAMETER:
- case Slot::LOCAL:
- return Operand(rbp, SlotOffset(slot));
- case Slot::CONTEXT: {
- int context_chain_length =
- scope()->ContextChainLength(slot->var()->scope());
- __ LoadContext(scratch, context_chain_length);
- return ContextOperand(scratch, slot->index());
- }
- case Slot::LOOKUP:
- UNREACHABLE();
+MemOperand FullCodeGenerator::StackOperand(Variable* var) {
+ ASSERT(var->IsStackAllocated());
+ // Offset is negative because higher indexes are at lower addresses.
+ int offset = -var->index() * kPointerSize;
+ // Adjust by a (parameter or local) base offset.
+ if (var->IsParameter()) {
+ offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
+ } else {
+ offset += JavaScriptFrameConstants::kLocal0Offset;
}
- UNREACHABLE();
- return Operand(rax, 0);
+ return Operand(rbp, offset);
}
-void FullCodeGenerator::Move(Register destination, Slot* source) {
- MemOperand location = EmitSlotSearch(source, destination);
- __ movq(destination, location);
+MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
+ ASSERT(var->IsContextSlot() || var->IsStackAllocated());
+ if (var->IsContextSlot()) {
+ int context_chain_length = scope()->ContextChainLength(var->scope());
+ __ LoadContext(scratch, context_chain_length);
+ return ContextOperand(scratch, var->index());
+ } else {
+ return StackOperand(var);
+ }
}
-void FullCodeGenerator::Move(Slot* dst,
- Register src,
- Register scratch1,
- Register scratch2) {
- ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented.
- ASSERT(!scratch1.is(src) && !scratch2.is(src));
- MemOperand location = EmitSlotSearch(dst, scratch1);
+void FullCodeGenerator::GetVar(Register dest, Variable* var) {
+ ASSERT(var->IsContextSlot() || var->IsStackAllocated());
+ MemOperand location = VarOperand(var, dest);
+ __ movq(dest, location);
+}
+
+
+void FullCodeGenerator::SetVar(Variable* var,
+ Register src,
+ Register scratch0,
+ Register scratch1) {
+ ASSERT(var->IsContextSlot() || var->IsStackAllocated());
+ ASSERT(!scratch0.is(src));
+ ASSERT(!scratch0.is(scratch1));
+ ASSERT(!scratch1.is(src));
+ MemOperand location = VarOperand(var, scratch0);
__ movq(location, src);
// Emit the write barrier code if the location is in the heap.
- if (dst->type() == Slot::CONTEXT) {
- int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize;
- __ RecordWrite(scratch1, offset, src, scratch2);
+ if (var->IsContextSlot()) {
+ int offset = Context::SlotOffset(var->index());
+ __ RecordWrite(scratch0, offset, src, scratch1);
}
}
@@ -658,29 +672,33 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
}
-void FullCodeGenerator::EmitDeclaration(Variable* variable,
+void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
Variable::Mode mode,
- FunctionLiteral* function) {
- Comment cmnt(masm_, "[ Declaration");
- ASSERT(variable != NULL); // Must have been resolved.
- Slot* slot = variable->AsSlot();
- ASSERT(slot != NULL);
- switch (slot->type()) {
- case Slot::PARAMETER:
- case Slot::LOCAL:
- if (mode == Variable::CONST) {
- __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
- __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister);
- } else if (function != NULL) {
+ FunctionLiteral* function,
+ int* global_count) {
+ // If it was not possible to allocate the variable at compile time, we
+ // need to "declare" it at runtime to make sure it actually exists in the
+ // local context.
+ Variable* variable = proxy->var();
+ switch (variable->location()) {
+ case Variable::UNALLOCATED:
+ ++(*global_count);
+ break;
+
+ case Variable::PARAMETER:
+ case Variable::LOCAL:
+ if (function != NULL) {
+ Comment cmnt(masm_, "[ Declaration");
VisitForAccumulatorValue(function);
- __ movq(Operand(rbp, SlotOffset(slot)), result_register());
+ __ movq(StackOperand(variable), result_register());
+ } else if (mode == Variable::CONST || mode == Variable::LET) {
+ Comment cmnt(masm_, "[ Declaration");
+ __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
+ __ movq(StackOperand(variable), kScratchRegister);
}
break;
- case Slot::CONTEXT:
- // We bypass the general EmitSlotSearch because we know more about
- // this specific context.
-
+ case Variable::CONTEXT:
// The variable in the decl always resides in the current function
// context.
ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
@@ -692,23 +710,28 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
__ CompareRoot(rbx, Heap::kCatchContextMapRootIndex);
__ Check(not_equal, "Declaration in catch context.");
}
- if (mode == Variable::CONST) {
- __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
- __ movq(ContextOperand(rsi, slot->index()), kScratchRegister);
- // No write barrier since the hole value is in old space.
- } else if (function != NULL) {
+ if (function != NULL) {
+ Comment cmnt(masm_, "[ Declaration");
VisitForAccumulatorValue(function);
- __ movq(ContextOperand(rsi, slot->index()), result_register());
- int offset = Context::SlotOffset(slot->index());
+ __ movq(ContextOperand(rsi, variable->index()), result_register());
+ int offset = Context::SlotOffset(variable->index());
__ movq(rbx, rsi);
__ RecordWrite(rbx, offset, result_register(), rcx);
+ PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+ } else if (mode == Variable::CONST || mode == Variable::LET) {
+ Comment cmnt(masm_, "[ Declaration");
+ __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
+ __ movq(ContextOperand(rsi, variable->index()), kScratchRegister);
+ // No write barrier since the hole value is in old space.
+ PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
}
break;
- case Slot::LOOKUP: {
+ case Variable::LOOKUP: {
+ Comment cmnt(masm_, "[ Declaration");
__ push(rsi);
__ Push(variable->name());
- // Declaration nodes are always introduced in one of two modes.
+ // Declaration nodes are always introduced in one of three modes.
ASSERT(mode == Variable::VAR ||
mode == Variable::CONST ||
mode == Variable::LET);
@@ -718,12 +741,12 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
// Note: For variables we must not push an initial value (such as
// 'undefined') because we may have a (legal) redeclaration and we
// must not destroy the current value.
- if (mode == Variable::CONST) {
- __ PushRoot(Heap::kTheHoleValueRootIndex);
- } else if (function != NULL) {
+ if (function != NULL) {
VisitForStackValue(function);
+ } else if (mode == Variable::CONST || mode == Variable::LET) {
+ __ PushRoot(Heap::kTheHoleValueRootIndex);
} else {
- __ Push(Smi::FromInt(0)); // no initial value!
+ __ Push(Smi::FromInt(0)); // Indicates no initial value.
}
__ CallRuntime(Runtime::kDeclareContextSlot, 4);
break;
@@ -732,18 +755,15 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
}
-void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
- EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
-}
+void FullCodeGenerator::VisitDeclaration(Declaration* decl) { }
void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals.
__ push(rsi); // The context is the first argument.
__ Push(pairs);
- __ Push(Smi::FromInt(is_eval() ? 1 : 0));
- __ Push(Smi::FromInt(strict_mode_flag()));
- __ CallRuntime(Runtime::kDeclareGlobals, 4);
+ __ Push(Smi::FromInt(DeclareGlobalsFlags()));
+ __ CallRuntime(Runtime::kDeclareGlobals, 3);
// Return value is ignored.
}
@@ -1048,10 +1068,9 @@ void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
}
-void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
- Slot* slot,
- TypeofState typeof_state,
- Label* slow) {
+void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
+ TypeofState typeof_state,
+ Label* slow) {
Register context = rsi;
Register temp = rdx;
@@ -1101,7 +1120,7 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
// All extension objects were empty and it is safe to use a global
// load IC call.
__ movq(rax, GlobalObjectOperand());
- __ Move(rcx, slot->var()->name());
+ __ Move(rcx, var->name());
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
? RelocInfo::CODE_TARGET
@@ -1110,14 +1129,13 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
}
-MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(
- Slot* slot,
- Label* slow) {
- ASSERT(slot->type() == Slot::CONTEXT);
+MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
+ Label* slow) {
+ ASSERT(var->IsContextSlot());
Register context = rsi;
Register temp = rbx;
- for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) {
+ for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
if (s->num_heap_slots() > 0) {
if (s->calls_eval()) {
// Check that extension is NULL.
@@ -1137,60 +1155,31 @@ MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(
// This function is used only for loads, not stores, so it's safe to
// return an rsi-based operand (the write barrier cannot be allowed to
// destroy the rsi register).
- return ContextOperand(context, slot->index());
+ return ContextOperand(context, var->index());
}
-void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
- Slot* slot,
- TypeofState typeof_state,
- Label* slow,
- Label* done) {
+void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var,
+ TypeofState typeof_state,
+ Label* slow,
+ Label* done) {
// Generate fast-case code for variables that might be shadowed by
// eval-introduced variables. Eval is used a lot without
// introducing variables. In those cases, we do not want to
// perform a runtime call for all variables in the scope
// containing the eval.
- if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
- EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow);
+ if (var->mode() == Variable::DYNAMIC_GLOBAL) {
+ EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
__ jmp(done);
- } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
- Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot();
- Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
- if (potential_slot != NULL) {
- // Generate fast case for locals that rewrite to slots.
- __ movq(rax,
- ContextSlotOperandCheckExtensions(potential_slot, slow));
- if (potential_slot->var()->mode() == Variable::CONST) {
- __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
- __ j(not_equal, done);
- __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
- }
- __ jmp(done);
- } else if (rewrite != NULL) {
- // Generate fast case for calls of an argument function.
- Property* property = rewrite->AsProperty();
- if (property != NULL) {
- VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
- Literal* key_literal = property->key()->AsLiteral();
- if (obj_proxy != NULL &&
- key_literal != NULL &&
- obj_proxy->IsArguments() &&
- key_literal->handle()->IsSmi()) {
- // Load arguments object if there are no eval-introduced
- // variables. Then load the argument from the arguments
- // object using keyed load.
- __ movq(rdx,
- ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(),
- slow));
- __ Move(rax, key_literal->handle());
- Handle<Code> ic =
- isolate()->builtins()->KeyedLoadIC_Initialize();
- __ call(ic, RelocInfo::CODE_TARGET, GetPropertyId(property));
- __ jmp(done);
- }
- }
+ } else if (var->mode() == Variable::DYNAMIC_LOCAL) {
+ Variable* local = var->local_if_not_shadowed();
+ __ movq(rax, ContextSlotOperandCheckExtensions(local, slow));
+ if (local->mode() == Variable::CONST) {
+ __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
+ __ j(not_equal, done);
+ __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
}
+ __ jmp(done);
}
}
@@ -1200,54 +1189,58 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
SetSourcePosition(proxy->position());
Variable* var = proxy->var();
- // Three cases: non-this global variables, lookup slots, and all other
- // types of slots.
- Slot* slot = var->AsSlot();
- ASSERT((var->is_global() && !var->is_this()) == (slot == NULL));
-
- if (slot == NULL) {
- Comment cmnt(masm_, "Global variable");
- // Use inline caching. Variable name is passed in rcx and the global
- // object on the stack.
- __ Move(rcx, var->name());
- __ movq(rax, GlobalObjectOperand());
- Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
- __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
- context()->Plug(rax);
-
- } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
- Label done, slow;
-
- // Generate code for loading from variables potentially shadowed
- // by eval-introduced variables.
- EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done);
-
- __ bind(&slow);
- Comment cmnt(masm_, "Lookup slot");
- __ push(rsi); // Context.
- __ Push(var->name());
- __ CallRuntime(Runtime::kLoadContextSlot, 2);
- __ bind(&done);
+ // Three cases: global variables, lookup variables, and all other types of
+ // variables.
+ switch (var->location()) {
+ case Variable::UNALLOCATED: {
+ Comment cmnt(masm_, "Global variable");
+ // Use inline caching. Variable name is passed in rcx and the global
+ // object on the stack.
+ __ Move(rcx, var->name());
+ __ movq(rax, GlobalObjectOperand());
+ Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+ __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
+ context()->Plug(rax);
+ break;
+ }
- context()->Plug(rax);
+ case Variable::PARAMETER:
+ case Variable::LOCAL:
+ case Variable::CONTEXT: {
+ Comment cmnt(masm_, var->IsContextSlot() ? "Context slot" : "Stack slot");
+ if (var->mode() != Variable::LET && var->mode() != Variable::CONST) {
+ context()->Plug(var);
+ } else {
+ // Let and const need a read barrier.
+ Label done;
+ GetVar(rax, var);
+ __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
+ __ j(not_equal, &done, Label::kNear);
+ if (var->mode() == Variable::LET) {
+ __ Push(var->name());
+ __ CallRuntime(Runtime::kThrowReferenceError, 1);
+ } else { // Variable::CONST
+ __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
+ }
+ __ bind(&done);
+ context()->Plug(rax);
+ }
+ break;
+ }
- } else {
- Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
- ? "Context slot"
- : "Stack slot");
- if (var->mode() == Variable::CONST) {
- // Constants may be the hole value if they have not been initialized.
- // Unhole them.
- Label done;
- MemOperand slot_operand = EmitSlotSearch(slot, rax);
- __ movq(rax, slot_operand);
- __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
- __ j(not_equal, &done, Label::kNear);
- __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
+ case Variable::LOOKUP: {
+ Label done, slow;
+ // Generate code for loading from variables potentially shadowed
+ // by eval-introduced variables.
+ EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done);
+ __ bind(&slow);
+ Comment cmnt(masm_, "Lookup slot");
+ __ push(rsi); // Context.
+ __ Push(var->name());
+ __ CallRuntime(Runtime::kLoadContextSlot, 2);
__ bind(&done);
context()->Plug(rax);
- } else {
- context()->Plug(slot);
+ break;
}
}
}
@@ -1267,7 +1260,7 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
__ movq(rbx, FieldOperand(rcx, literal_offset));
__ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
- __ j(not_equal, &materialized);
+ __ j(not_equal, &materialized, Label::kNear);
// Create regexp literal using runtime function
// Result will be in rax.
@@ -1732,82 +1725,88 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
void FullCodeGenerator::EmitVariableAssignment(Variable* var,
Token::Value op) {
- ASSERT(var != NULL);
- ASSERT(var->is_global() || var->AsSlot() != NULL);
-
- if (var->is_global()) {
- ASSERT(!var->is_this());
- // Assignment to a global variable. Use inline caching for the
- // assignment. Right-hand-side value is passed in rax, variable name in
- // rcx, and the global object on the stack.
+ if (var->IsUnallocated()) {
+ // Global var, const, or let.
__ Move(rcx, var->name());
__ movq(rdx, GlobalObjectOperand());
Handle<Code> ic = is_strict_mode()
? isolate()->builtins()->StoreIC_Initialize_Strict()
: isolate()->builtins()->StoreIC_Initialize();
__ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
-
} else if (op == Token::INIT_CONST) {
- // Like var declarations, const declarations are hoisted to function
- // scope. However, unlike var initializers, const initializers are able
- // to drill a hole to that function context, even from inside a 'with'
- // context. We thus bypass the normal static scope lookup.
- Slot* slot = var->AsSlot();
- Label skip;
- switch (slot->type()) {
- case Slot::PARAMETER:
- // No const parameters.
- UNREACHABLE();
- break;
- case Slot::LOCAL:
- __ movq(rdx, Operand(rbp, SlotOffset(slot)));
- __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
- __ j(not_equal, &skip);
- __ movq(Operand(rbp, SlotOffset(slot)), rax);
- break;
- case Slot::CONTEXT:
- case Slot::LOOKUP:
- __ push(rax);
- __ push(rsi);
- __ Push(var->name());
- __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
- break;
+ // Const initializers need a write barrier.
+ ASSERT(!var->IsParameter()); // No const parameters.
+ if (var->IsStackLocal()) {
+ Label skip;
+ __ movq(rdx, StackOperand(var));
+ __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
+ __ j(not_equal, &skip);
+ __ movq(StackOperand(var), rax);
+ __ bind(&skip);
+ } else {
+ ASSERT(var->IsContextSlot() || var->IsLookupSlot());
+ // Like var declarations, const declarations are hoisted to function
+ // scope. However, unlike var initializers, const initializers are
+ // able to drill a hole to that function context, even from inside a
+ // 'with' context. We thus bypass the normal static scope lookup for
+ // var->IsContextSlot().
+ __ push(rax);
+ __ push(rsi);
+ __ Push(var->name());
+ __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
}
- __ bind(&skip);
-
- } else if (var->mode() != Variable::CONST) {
- // Perform the assignment for non-const variables. Const assignments
- // are simply skipped.
- Slot* slot = var->AsSlot();
- switch (slot->type()) {
- case Slot::PARAMETER:
- case Slot::LOCAL:
- // Perform the assignment.
- __ movq(Operand(rbp, SlotOffset(slot)), rax);
- break;
- case Slot::CONTEXT: {
- MemOperand target = EmitSlotSearch(slot, rcx);
- // Perform the assignment and issue the write barrier.
- __ movq(target, rax);
- // The value of the assignment is in rax. RecordWrite clobbers its
- // register arguments.
+ } else if (var->mode() == Variable::LET && op != Token::INIT_LET) {
+ // Non-initializing assignment to let variable needs a write barrier.
+ if (var->IsLookupSlot()) {
+ __ push(rax); // Value.
+ __ push(rsi); // Context.
+ __ Push(var->name());
+ __ Push(Smi::FromInt(strict_mode_flag()));
+ __ CallRuntime(Runtime::kStoreContextSlot, 4);
+ } else {
+ ASSERT(var->IsStackAllocated() || var->IsContextSlot());
+ Label assign;
+ MemOperand location = VarOperand(var, rcx);
+ __ movq(rdx, location);
+ __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
+ __ j(not_equal, &assign, Label::kNear);
+ __ Push(var->name());
+ __ CallRuntime(Runtime::kThrowReferenceError, 1);
+ __ bind(&assign);
+ __ movq(location, rax);
+ if (var->IsContextSlot()) {
__ movq(rdx, rax);
- int offset = Context::SlotOffset(slot->index());
- __ RecordWrite(rcx, offset, rdx, rbx);
- break;
+ __ RecordWrite(rcx, Context::SlotOffset(var->index()), rdx, rbx);
}
+ }
- case Slot::LOOKUP:
- // Call the runtime for the assignment.
- __ push(rax); // Value.
- __ push(rsi); // Context.
- __ Push(var->name());
- __ Push(Smi::FromInt(strict_mode_flag()));
- __ CallRuntime(Runtime::kStoreContextSlot, 4);
- break;
+ } else if (var->mode() != Variable::CONST) {
+ // Assignment to var or initializing assignment to let.
+ if (var->IsStackAllocated() || var->IsContextSlot()) {
+ MemOperand location = VarOperand(var, rcx);
+ if (FLAG_debug_code && op == Token::INIT_LET) {
+ // Check for an uninitialized let binding.
+ __ movq(rdx, location);
+ __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
+ __ Check(equal, "Let binding re-initialization.");
+ }
+ // Perform the assignment.
+ __ movq(location, rax);
+ if (var->IsContextSlot()) {
+ __ movq(rdx, rax);
+ __ RecordWrite(rcx, Context::SlotOffset(var->index()), rdx, rbx);
+ }
+ } else {
+ ASSERT(var->IsLookupSlot());
+ __ push(rax); // Value.
+ __ push(rsi); // Context.
+ __ Push(var->name());
+ __ Push(Smi::FromInt(strict_mode_flag()));
+ __ CallRuntime(Runtime::kStoreContextSlot, 4);
}
}
+ // Non-initializing assignments to consts are ignored.
}
@@ -2006,8 +2005,13 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
// Push the receiver of the enclosing function and do runtime call.
__ push(Operand(rbp, (2 + info_->scope()->num_parameters()) * kPointerSize));
- // Push the strict mode flag.
- __ Push(Smi::FromInt(strict_mode_flag()));
+ // Push the strict mode flag. In harmony mode every eval call
+ // is a strict mode eval call.
+ StrictModeFlag strict_mode = strict_mode_flag();
+ if (FLAG_harmony_block_scoping) {
+ strict_mode = kStrictMode;
+ }
+ __ Push(Smi::FromInt(strict_mode));
__ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
? Runtime::kResolvePossiblyDirectEvalNoLookup
@@ -2023,18 +2027,18 @@ void FullCodeGenerator::VisitCall(Call* expr) {
#endif
Comment cmnt(masm_, "[ Call");
- Expression* fun = expr->expression();
- Variable* var = fun->AsVariableProxy()->AsVariable();
+ Expression* callee = expr->expression();
+ VariableProxy* proxy = callee->AsVariableProxy();
+ Property* property = callee->AsProperty();
- if (var != NULL && var->is_possibly_eval()) {
+ if (proxy != NULL && proxy->var()->is_possibly_eval()) {
// In a call to eval, we first call %ResolvePossiblyDirectEval to
- // resolve the function we need to call and the receiver of the
- // call. Then we call the resolved function using the given
- // arguments.
+ // resolve the function we need to call and the receiver of the call.
+ // Then we call the resolved function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
{ PreservePositionScope pos_scope(masm()->positions_recorder());
- VisitForStackValue(fun);
+ VisitForStackValue(callee);
__ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot.
// Push the arguments.
@@ -2043,15 +2047,14 @@ void FullCodeGenerator::VisitCall(Call* expr) {
}
// If we know that eval can only be shadowed by eval-introduced
- // variables we attempt to load the global eval function directly
- // in generated code. If we succeed, there is no need to perform a
+ // variables we attempt to load the global eval function directly in
+ // generated code. If we succeed, there is no need to perform a
// context lookup in the runtime system.
Label done;
- if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) {
+ Variable* var = proxy->var();
+ if (!var->IsUnallocated() && var->mode() == Variable::DYNAMIC_GLOBAL) {
Label slow;
- EmitLoadGlobalSlotCheckExtensions(var->AsSlot(),
- NOT_INSIDE_TYPEOF,
- &slow);
+ EmitLoadGlobalCheckExtensions(var, NOT_INSIDE_TYPEOF, &slow);
// Push the function and resolve eval.
__ push(rax);
EmitResolvePossiblyDirectEval(SKIP_CONTEXT_LOOKUP, arg_count);
@@ -2059,13 +2062,11 @@ void FullCodeGenerator::VisitCall(Call* expr) {
__ bind(&slow);
}
- // Push copy of the function (found below the arguments) and
- // resolve eval.
+ // Push a copy of the function (found below the arguments) and resolve
+ // eval.
__ push(Operand(rsp, (arg_count + 1) * kPointerSize));
EmitResolvePossiblyDirectEval(PERFORM_CONTEXT_LOOKUP, arg_count);
- if (done.is_linked()) {
- __ bind(&done);
- }
+ __ bind(&done);
// The runtime call returns a pair of values in rax (function) and
// rdx (receiver). Touch up the stack with the right values.
@@ -2081,73 +2082,62 @@ void FullCodeGenerator::VisitCall(Call* expr) {
// Restore context register.
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, rax);
- } else if (var != NULL && !var->is_this() && var->is_global()) {
- // Call to a global variable.
- // Push global object as receiver for the call IC lookup.
+ } else if (proxy != NULL && proxy->var()->IsUnallocated()) {
+ // Call to a global variable. Push global object as receiver for the
+ // call IC lookup.
__ push(GlobalObjectOperand());
- EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
- } else if (var != NULL && var->AsSlot() != NULL &&
- var->AsSlot()->type() == Slot::LOOKUP) {
+ EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
+ } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
// Call to a lookup slot (dynamically introduced variable).
Label slow, done;
{ PreservePositionScope scope(masm()->positions_recorder());
- // Generate code for loading from variables potentially shadowed
- // by eval-introduced variables.
- EmitDynamicLoadFromSlotFastCase(var->AsSlot(),
- NOT_INSIDE_TYPEOF,
- &slow,
- &done);
-
- __ bind(&slow);
+ // Generate code for loading from variables potentially shadowed by
+ // eval-introduced variables.
+ EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
}
- // Call the runtime to find the function to call (returned in rax)
- // and the object holding it (returned in rdx).
+ __ bind(&slow);
+ // Call the runtime to find the function to call (returned in rax) and
+ // the object holding it (returned in rdx).
__ push(context_register());
- __ Push(var->name());
+ __ Push(proxy->name());
__ CallRuntime(Runtime::kLoadContextSlot, 2);
__ push(rax); // Function.
__ push(rdx); // Receiver.
- // If fast case code has been generated, emit code to push the
- // function and receiver and have the slow path jump around this
- // code.
+ // If fast case code has been generated, emit code to push the function
+ // and receiver and have the slow path jump around this code.
if (done.is_linked()) {
Label call;
__ jmp(&call, Label::kNear);
__ bind(&done);
// Push function.
__ push(rax);
- // The receiver is implicitly the global receiver. Indicate this
- // by passing the hole to the call function stub.
+ // The receiver is implicitly the global receiver. Indicate this by
+ // passing the hole to the call function stub.
__ PushRoot(Heap::kTheHoleValueRootIndex);
__ bind(&call);
}
- // The receiver is either the global receiver or an object found
- // by LoadContextSlot. That object could be the hole if the
- // receiver is implicitly the global object.
+ // The receiver is either the global receiver or an object found by
+ // LoadContextSlot. That object could be the hole if the receiver is
+ // implicitly the global object.
EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT);
- } else if (fun->AsProperty() != NULL) {
- // Call to an object property.
- Property* prop = fun->AsProperty();
- Literal* key = prop->key()->AsLiteral();
- if (key != NULL && key->handle()->IsSymbol()) {
- // Call to a named property, use call IC.
- { PreservePositionScope scope(masm()->positions_recorder());
- VisitForStackValue(prop->obj());
- }
- EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
+ } else if (property != NULL) {
+ { PreservePositionScope scope(masm()->positions_recorder());
+ VisitForStackValue(property->obj());
+ }
+ if (property->key()->IsPropertyName()) {
+ EmitCallWithIC(expr,
+ property->key()->AsLiteral()->handle(),
+ RelocInfo::CODE_TARGET);
} else {
- // Call to a keyed property.
- { PreservePositionScope scope(masm()->positions_recorder());
- VisitForStackValue(prop->obj());
- }
- EmitKeyedCallWithIC(expr, prop->key());
+ EmitKeyedCallWithIC(expr, property->key());
}
} else {
+ // Call to an arbitrary expression not handled specially above.
{ PreservePositionScope scope(masm()->positions_recorder());
- VisitForStackValue(fun);
+ VisitForStackValue(callee);
}
// Load global receiver object.
__ movq(rbx, GlobalObjectOperand());
@@ -3075,7 +3065,7 @@ void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) {
Label done, not_found;
// tmp now holds finger offset as a smi.
- ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
+ STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
__ movq(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
SmiIndex index =
__ SmiToIndex(kScratchRegister, tmp, kPointerSizeLog2);
@@ -3505,30 +3495,31 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
switch (expr->op()) {
case Token::DELETE: {
Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
- Property* prop = expr->expression()->AsProperty();
- Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
+ Property* property = expr->expression()->AsProperty();
+ VariableProxy* proxy = expr->expression()->AsVariableProxy();
- if (prop != NULL) {
- VisitForStackValue(prop->obj());
- VisitForStackValue(prop->key());
+ if (property != NULL) {
+ VisitForStackValue(property->obj());
+ VisitForStackValue(property->key());
__ Push(Smi::FromInt(strict_mode_flag()));
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(rax);
- } else if (var != NULL) {
+ } else if (proxy != NULL) {
+ Variable* var = proxy->var();
// Delete of an unqualified identifier is disallowed in strict mode
- // but "delete this" is.
+ // but "delete this" is allowed.
ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this());
- if (var->is_global()) {
+ if (var->IsUnallocated()) {
__ push(GlobalObjectOperand());
__ Push(var->name());
__ Push(Smi::FromInt(kNonStrictMode));
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(rax);
- } else if (var->AsSlot() != NULL &&
- var->AsSlot()->type() != Slot::LOOKUP) {
- // Result of deleting non-global, non-dynamic variables is false.
- // The subexpression does not have side effects.
- context()->Plug(false);
+ } else if (var->IsStackAllocated() || var->IsContextSlot()) {
+ // Result of deleting non-global variables is false. 'this' is
+ // not really a variable, though we implement it as one. The
+ // subexpression does not have side effects.
+ context()->Plug(var->is_this());
} else {
// Non-global variable. Call the runtime to try to delete from the
// context where the variable was introduced.
@@ -3814,7 +3805,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
ASSERT(!context()->IsEffect());
ASSERT(!context()->IsTest());
- if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
+ if (proxy != NULL && proxy->var()->IsUnallocated()) {
Comment cmnt(masm_, "Global variable");
__ Move(rcx, proxy->name());
__ movq(rax, GlobalObjectOperand());
@@ -3824,15 +3815,12 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
__ call(ic);
PrepareForBailout(expr, TOS_REG);
context()->Plug(rax);
- } else if (proxy != NULL &&
- proxy->var()->AsSlot() != NULL &&
- proxy->var()->AsSlot()->type() == Slot::LOOKUP) {
+ } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
Label done, slow;
// Generate code for loading from variables potentially shadowed
// by eval-introduced variables.
- Slot* slot = proxy->var()->AsSlot();
- EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done);
+ EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done);
__ bind(&slow);
__ push(rsi);
@@ -4144,6 +4132,33 @@ void FullCodeGenerator::ExitFinallyBlock() {
#undef __
+#define __ ACCESS_MASM(masm())
+
+FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
+ int* stack_depth,
+ int* context_length) {
+ // The macros used here must preserve the result register.
+
+ // Because the handler block contains the context of the finally
+ // code, we can restore it directly from there for the finally code
+ // rather than iteratively unwinding contexts via their previous
+ // links.
+ __ Drop(*stack_depth); // Down to the handler block.
+ if (*context_length > 0) {
+ // Restore the context to its dedicated register and the stack.
+ __ movq(rsi, Operand(rsp, StackHandlerConstants::kContextOffset));
+ __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
+ }
+ __ PopTryHandler();
+ __ call(finally_entry_);
+
+ *stack_depth = 0;
+ *context_length = 0;
+ return previous_;
+}
+
+
+#undef __
} } // namespace v8::internal
diff --git a/deps/v8/src/x64/ic-x64.cc b/deps/v8/src/x64/ic-x64.cc
index 339d2c19ce..990c171bed 100644
--- a/deps/v8/src/x64/ic-x64.cc
+++ b/deps/v8/src/x64/ic-x64.cc
@@ -378,7 +378,7 @@ static void GenerateKeyStringCheck(MacroAssembler* masm,
__ j(zero, index_string); // The value in hash is used at jump target.
// Is the string a symbol?
- ASSERT(kSymbolTag != 0);
+ STATIC_ASSERT(kSymbolTag != 0);
__ testb(FieldOperand(map, Map::kInstanceTypeOffset),
Immediate(kIsSymbolMask));
__ j(zero, not_symbol);
diff --git a/deps/v8/src/x64/lithium-codegen-x64.cc b/deps/v8/src/x64/lithium-codegen-x64.cc
index 76a9453b79..bedf1be437 100644
--- a/deps/v8/src/x64/lithium-codegen-x64.cc
+++ b/deps/v8/src/x64/lithium-codegen-x64.cc
@@ -207,14 +207,14 @@ bool LCodeGen::GeneratePrologue() {
// Copy any necessary parameters into the context.
int num_parameters = scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) {
- Slot* slot = scope()->parameter(i)->AsSlot();
- if (slot != NULL && slot->type() == Slot::CONTEXT) {
+ Variable* var = scope()->parameter(i);
+ if (var->IsContextSlot()) {
int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(num_parameters - 1 - i) * kPointerSize;
// Load parameter from stack.
__ movq(rax, Operand(rbp, parameter_offset));
// Store it in the context.
- int context_offset = Context::SlotOffset(slot->index());
+ int context_offset = Context::SlotOffset(var->index());
__ movq(Operand(rsi, context_offset), rax);
// Update the write barrier. This clobbers all involved
// registers, so we have use a third register to avoid
@@ -3217,8 +3217,6 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
// Dispatch on the indirect string shape: slice or cons.
Label cons_string;
- const uint32_t kSlicedNotConsMask = kSlicedStringTag & ~kConsStringTag;
- ASSERT(IsPowerOf2(kSlicedNotConsMask) && kSlicedNotConsMask != 0);
__ testb(result, Immediate(kSlicedNotConsMask));
__ j(zero, &cons_string, Label::kNear);
@@ -3253,7 +3251,8 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
// Dispatch on the encoding: ASCII or two-byte.
Label ascii_string;
- STATIC_ASSERT(kAsciiStringTag != 0);
+ STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
+ STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
__ testb(result, Immediate(kStringEncodingMask));
__ j(not_zero, &ascii_string, Label::kNear);
diff --git a/deps/v8/src/x64/macro-assembler-x64.cc b/deps/v8/src/x64/macro-assembler-x64.cc
index e4a76270a2..2ee506d7c3 100644
--- a/deps/v8/src/x64/macro-assembler-x64.cc
+++ b/deps/v8/src/x64/macro-assembler-x64.cc
@@ -923,7 +923,7 @@ void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) {
void MacroAssembler::Integer32ToSmi(Register dst, Register src) {
- ASSERT_EQ(0, kSmiTag);
+ STATIC_ASSERT(kSmiTag == 0);
if (!dst.is(src)) {
movl(dst, src);
}
@@ -961,7 +961,7 @@ void MacroAssembler::Integer64PlusConstantToSmi(Register dst,
void MacroAssembler::SmiToInteger32(Register dst, Register src) {
- ASSERT_EQ(0, kSmiTag);
+ STATIC_ASSERT(kSmiTag == 0);
if (!dst.is(src)) {
movq(dst, src);
}
@@ -975,7 +975,7 @@ void MacroAssembler::SmiToInteger32(Register dst, const Operand& src) {
void MacroAssembler::SmiToInteger64(Register dst, Register src) {
- ASSERT_EQ(0, kSmiTag);
+ STATIC_ASSERT(kSmiTag == 0);
if (!dst.is(src)) {
movq(dst, src);
}
@@ -1111,21 +1111,21 @@ void MacroAssembler::SmiOrIfSmis(Register dst, Register src1, Register src2,
Condition MacroAssembler::CheckSmi(Register src) {
- ASSERT_EQ(0, kSmiTag);
+ STATIC_ASSERT(kSmiTag == 0);
testb(src, Immediate(kSmiTagMask));
return zero;
}
Condition MacroAssembler::CheckSmi(const Operand& src) {
- ASSERT_EQ(0, kSmiTag);
+ STATIC_ASSERT(kSmiTag == 0);
testb(src, Immediate(kSmiTagMask));
return zero;
}
Condition MacroAssembler::CheckNonNegativeSmi(Register src) {
- ASSERT_EQ(0, kSmiTag);
+ STATIC_ASSERT(kSmiTag == 0);
// Test that both bits of the mask 0x8000000000000001 are zero.
movq(kScratchRegister, src);
rol(kScratchRegister, Immediate(1));
@@ -1138,7 +1138,7 @@ Condition MacroAssembler::CheckBothSmi(Register first, Register second) {
if (first.is(second)) {
return CheckSmi(first);
}
- ASSERT(kSmiTag == 0 && kHeapObjectTag == 1 && kHeapObjectTagMask == 3);
+ STATIC_ASSERT(kSmiTag == 0 && kHeapObjectTag == 1 && kHeapObjectTagMask == 3);
leal(kScratchRegister, Operand(first, second, times_1, 0));
testb(kScratchRegister, Immediate(0x03));
return zero;
@@ -1294,7 +1294,7 @@ void MacroAssembler::SmiTryAddConstant(Register dst,
Label::Distance near_jump) {
// Does not assume that src is a smi.
ASSERT_EQ(static_cast<int>(1), static_cast<int>(kSmiTagMask));
- ASSERT_EQ(0, kSmiTag);
+ STATIC_ASSERT(kSmiTag == 0);
ASSERT(!dst.is(kScratchRegister));
ASSERT(!src.is(kScratchRegister));
@@ -1998,7 +1998,7 @@ void MacroAssembler::SelectNonSmi(Register dst,
Check(not_both_smis, "Both registers were smis in SelectNonSmi.");
}
#endif
- ASSERT_EQ(0, kSmiTag);
+ STATIC_ASSERT(kSmiTag == 0);
ASSERT_EQ(0, Smi::FromInt(0));
movl(kScratchRegister, Immediate(kSmiTagMask));
and_(kScratchRegister, src1);
@@ -2699,7 +2699,7 @@ Condition MacroAssembler::IsObjectStringType(Register heap_object,
Register instance_type) {
movq(map, FieldOperand(heap_object, HeapObject::kMapOffset));
movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
- ASSERT(kNotStringTag != 0);
+ STATIC_ASSERT(kNotStringTag != 0);
testb(instance_type, Immediate(kIsNotStringMask));
return zero;
}
@@ -3623,7 +3623,7 @@ void MacroAssembler::AllocateAsciiString(Register result,
}
-void MacroAssembler::AllocateConsString(Register result,
+void MacroAssembler::AllocateTwoByteConsString(Register result,
Register scratch1,
Register scratch2,
Label* gc_required) {
@@ -3659,6 +3659,42 @@ void MacroAssembler::AllocateAsciiConsString(Register result,
}
+void MacroAssembler::AllocateTwoByteSlicedString(Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required) {
+ // Allocate heap number in new space.
+ AllocateInNewSpace(SlicedString::kSize,
+ result,
+ scratch1,
+ scratch2,
+ gc_required,
+ TAG_OBJECT);
+
+ // Set the map. The other fields are left uninitialized.
+ LoadRoot(kScratchRegister, Heap::kSlicedStringMapRootIndex);
+ movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
+}
+
+
+void MacroAssembler::AllocateAsciiSlicedString(Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required) {
+ // Allocate heap number in new space.
+ AllocateInNewSpace(SlicedString::kSize,
+ result,
+ scratch1,
+ scratch2,
+ gc_required,
+ TAG_OBJECT);
+
+ // Set the map. The other fields are left uninitialized.
+ LoadRoot(kScratchRegister, Heap::kSlicedAsciiStringMapRootIndex);
+ movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
+}
+
+
// Copy memory, byte-by-byte, from source to destination. Not optimized for
// long or aligned copies. The contents of scratch and length are destroyed.
// Destination is incremented by length, source, length and scratch are
diff --git a/deps/v8/src/x64/macro-assembler-x64.h b/deps/v8/src/x64/macro-assembler-x64.h
index 47ce01bd0c..e7eb104c0b 100644
--- a/deps/v8/src/x64/macro-assembler-x64.h
+++ b/deps/v8/src/x64/macro-assembler-x64.h
@@ -921,7 +921,7 @@ class MacroAssembler: public Assembler {
// Allocate a raw cons string object. Only the map field of the result is
// initialized.
- void AllocateConsString(Register result,
+ void AllocateTwoByteConsString(Register result,
Register scratch1,
Register scratch2,
Label* gc_required);
@@ -930,6 +930,17 @@ class MacroAssembler: public Assembler {
Register scratch2,
Label* gc_required);
+ // Allocate a raw sliced string object. Only the map field of the result is
+ // initialized.
+ void AllocateTwoByteSlicedString(Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required);
+ void AllocateAsciiSlicedString(Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required);
+
// ---------------------------------------------------------------------------
// Support functions.
diff --git a/deps/v8/src/x64/regexp-macro-assembler-x64.cc b/deps/v8/src/x64/regexp-macro-assembler-x64.cc
index 7f804477f3..a782bd7052 100644
--- a/deps/v8/src/x64/regexp-macro-assembler-x64.cc
+++ b/deps/v8/src/x64/regexp-macro-assembler-x64.cc
@@ -1185,7 +1185,7 @@ int RegExpMacroAssemblerX64::CheckStackGuardState(Address* return_address,
MaybeObject* result = Execution::HandleStackGuardInterrupt();
if (*code_handle != re_code) { // Return address no longer valid
- intptr_t delta = *code_handle - re_code;
+ intptr_t delta = code_handle->address() - re_code->address();
// Overwrite the return address on the stack.
*return_address += delta;
}
diff --git a/deps/v8/src/x64/stub-cache-x64.cc b/deps/v8/src/x64/stub-cache-x64.cc
index cfd19bf146..5ea72579b4 100644
--- a/deps/v8/src/x64/stub-cache-x64.cc
+++ b/deps/v8/src/x64/stub-cache-x64.cc
@@ -258,7 +258,7 @@ static void GenerateStringCheck(MacroAssembler* masm,
// Check that the object is a string.
__ movq(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
__ movzxbq(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
- ASSERT(kNotStringTag != 0);
+ STATIC_ASSERT(kNotStringTag != 0);
__ testl(scratch, Immediate(kNotStringTag));
__ j(not_zero, non_string_object);
}
@@ -3070,7 +3070,7 @@ MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
// Load the initial map and verify that it is in fact a map.
__ movq(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
// Will both indicate a NULL and a Smi.
- ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTag == 0);
__ JumpIfSmi(rbx, &generic_stub_call);
__ CmpObjectType(rbx, MAP_TYPE, rcx);
__ j(not_equal, &generic_stub_call);
diff --git a/deps/v8/test/cctest/cctest.gyp b/deps/v8/test/cctest/cctest.gyp
index c0b531636c..5d0cab3e98 100644
--- a/deps/v8/test/cctest/cctest.gyp
+++ b/deps/v8/test/cctest/cctest.gyp
@@ -35,7 +35,6 @@
'target_name': 'cctest',
'type': 'executable',
'dependencies': [
- '../../tools/gyp/v8.gyp:v8',
'resources',
],
'include_dirs': [
@@ -136,6 +135,20 @@
'test-platform-win32.cc',
],
}],
+ ['component=="shared_library"', {
+ # cctest can't be built against a shared library, so we need to
+ # depend on the underlying static target in that case.
+ 'conditions': [
+ ['v8_use_snapshot=="true"', {
+ 'dependencies': ['../../tools/gyp/v8.gyp:v8_snapshot'],
+ },
+ {
+ 'dependencies': ['../../tools/gyp/v8.gyp:v8_nosnapshot'],
+ }],
+ ],
+ }, {
+ 'dependencies': ['../../tools/gyp/v8.gyp:v8'],
+ }],
],
},
{
diff --git a/deps/v8/test/cctest/cctest.status b/deps/v8/test/cctest/cctest.status
index 78f3756195..5122da5ae3 100644
--- a/deps/v8/test/cctest/cctest.status
+++ b/deps/v8/test/cctest/cctest.status
@@ -76,3 +76,7 @@ test-debug/DebugBreakLoop: SKIP
[ $arch == mips ]
test-deoptimization: SKIP
test-serialize: SKIP
+
+# Tests that may time out.
+test-api/ExternalArrays: PASS || TIMEOUT
+test-api/Threading: PASS || TIMEOUT
diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc
index f2af81eb71..f9f08a6641 100644
--- a/deps/v8/test/cctest/test-api.cc
+++ b/deps/v8/test/cctest/test-api.cc
@@ -823,7 +823,7 @@ static void* expected_ptr;
static v8::Handle<v8::Value> callback(const v8::Arguments& args) {
void* ptr = v8::External::Unwrap(args.Data());
CHECK_EQ(expected_ptr, ptr);
- return v8::Boolean::New(true);
+ return v8::True();
}
@@ -2609,7 +2609,7 @@ v8::Handle<Value> ThrowFromC(const v8::Arguments& args) {
v8::Handle<Value> CCatcher(const v8::Arguments& args) {
- if (args.Length() < 1) return v8::Boolean::New(false);
+ if (args.Length() < 1) return v8::False();
v8::HandleScope scope;
v8::TryCatch try_catch;
Local<Value> result = v8::Script::Compile(args[0]->ToString())->Run();
@@ -4226,7 +4226,7 @@ template <typename T> static void USE(T) { }
// This test is not intended to be run, just type checked.
-static void PersistentHandles() {
+static inline void PersistentHandles() {
USE(PersistentHandles);
Local<String> str = v8_str("foo");
v8::Persistent<String> p_str = v8::Persistent<String>::New(str);
@@ -7296,7 +7296,7 @@ THREADED_TEST(ConstructorForObject) {
CHECK(value->IsBoolean());
CHECK_EQ(true, value->BooleanValue());
- Handle<Value> args3[] = { v8::Boolean::New(true) };
+ Handle<Value> args3[] = { v8::True() };
Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
CHECK(value_obj3->IsObject());
Local<Object> object3 = Local<Object>::Cast(value_obj3);
@@ -9567,10 +9567,7 @@ THREADED_TEST(Overriding) {
static v8::Handle<Value> IsConstructHandler(const v8::Arguments& args) {
ApiTestFuzzer::Fuzz();
- if (args.IsConstructCall()) {
- return v8::Boolean::New(true);
- }
- return v8::Boolean::New(false);
+ return v8::Boolean::New(args.IsConstructCall());
}
@@ -11796,14 +11793,21 @@ THREADED_TEST(PixelArray) {
CHECK_EQ(28, result->Int32Value());
i::Handle<i::Smi> value(i::Smi::FromInt(2));
- i::SetElement(jsobj, 1, value, i::kNonStrictMode);
+ i::Handle<i::Object> no_failure;
+ no_failure = i::SetElement(jsobj, 1, value, i::kNonStrictMode);
+ ASSERT(!no_failure.is_null());
+ i::USE(no_failure);
CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
*value.location() = i::Smi::FromInt(256);
- i::SetElement(jsobj, 1, value, i::kNonStrictMode);
+ no_failure = i::SetElement(jsobj, 1, value, i::kNonStrictMode);
+ ASSERT(!no_failure.is_null());
+ i::USE(no_failure);
CHECK_EQ(255,
i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
*value.location() = i::Smi::FromInt(-1);
- i::SetElement(jsobj, 1, value, i::kNonStrictMode);
+ no_failure = i::SetElement(jsobj, 1, value, i::kNonStrictMode);
+ ASSERT(!no_failure.is_null());
+ i::USE(no_failure);
CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
result = CompileRun("for (var i = 0; i < 8; i++) {"
diff --git a/deps/v8/test/cctest/test-assembler-arm.cc b/deps/v8/test/cctest/test-assembler-arm.cc
index 17032035c4..ecbf956916 100644
--- a/deps/v8/test/cctest/test-assembler-arm.cc
+++ b/deps/v8/test/cctest/test-assembler-arm.cc
@@ -1010,4 +1010,18 @@ TEST(11) {
CHECK_EQ(0xffffffff, i.d);
}
+
+TEST(12) {
+ // Test chaining of label usages within instructions (issue 1644).
+ InitializeVM();
+ v8::HandleScope scope;
+ Assembler assm(Isolate::Current(), NULL, 0);
+
+ Label target;
+ __ b(eq, &target);
+ __ b(ne, &target);
+ __ bind(&target);
+ __ nop();
+}
+
#undef __
diff --git a/deps/v8/test/cctest/test-assembler-ia32.cc b/deps/v8/test/cctest/test-assembler-ia32.cc
index e9d799b548..839b7f562e 100644
--- a/deps/v8/test/cctest/test-assembler-ia32.cc
+++ b/deps/v8/test/cctest/test-assembler-ia32.cc
@@ -394,4 +394,18 @@ TEST(AssemblerIa329) {
CHECK_EQ(kNaN, f(OS::nan_value(), 1.1));
}
+
+TEST(AssemblerIa3210) {
+ // Test chaining of label usages within instructions (issue 1644).
+ InitializeVM();
+ v8::HandleScope scope;
+ Assembler assm(Isolate::Current(), NULL, 0);
+
+ Label target;
+ __ j(equal, &target);
+ __ j(not_equal, &target);
+ __ bind(&target);
+ __ nop();
+}
+
#undef __
diff --git a/deps/v8/test/cctest/test-assembler-mips.cc b/deps/v8/test/cctest/test-assembler-mips.cc
index 065569dd10..a6c76f03ed 100644
--- a/deps/v8/test/cctest/test-assembler-mips.cc
+++ b/deps/v8/test/cctest/test-assembler-mips.cc
@@ -774,7 +774,7 @@ TEST(MIPS10) {
Assembler assm(Isolate::Current(), NULL, 0);
Label L, C;
- if (CpuFeatures::IsSupported(FPU)) {
+ if (CpuFeatures::IsSupported(FPU) && mips32r2) {
CpuFeatures::Scope scope(FPU);
// Load all structure elements to registers.
@@ -1259,4 +1259,20 @@ TEST(MIPS14) {
}
}
+
+TEST(MIPS15) {
+ // Test chaining of label usages within instructions (issue 1644).
+ InitializeVM();
+ v8::HandleScope scope;
+ Assembler assm(Isolate::Current(), NULL, 0);
+
+ Label target;
+ __ beq(v0, v1, &target);
+ __ nop();
+ __ bne(v0, v1, &target);
+ __ nop();
+ __ bind(&target);
+ __ nop();
+}
+
#undef __
diff --git a/deps/v8/test/cctest/test-assembler-x64.cc b/deps/v8/test/cctest/test-assembler-x64.cc
index ea70f54205..28f7c9b703 100644
--- a/deps/v8/test/cctest/test-assembler-x64.cc
+++ b/deps/v8/test/cctest/test-assembler-x64.cc
@@ -46,6 +46,7 @@ using v8::internal::Operand;
using v8::internal::byte;
using v8::internal::greater;
using v8::internal::less_equal;
+using v8::internal::equal;
using v8::internal::not_equal;
using v8::internal::r13;
using v8::internal::r15;
@@ -345,4 +346,17 @@ TEST(OperandRegisterDependency) {
}
}
+
+TEST(AssemblerX64LabelChaining) {
+ // Test chaining of label usages within instructions (issue 1644).
+ v8::HandleScope scope;
+ Assembler assm(Isolate::Current(), NULL, 0);
+
+ Label target;
+ __ j(equal, &target);
+ __ j(not_equal, &target);
+ __ bind(&target);
+ __ nop();
+}
+
#undef __
diff --git a/deps/v8/test/cctest/test-compiler.cc b/deps/v8/test/cctest/test-compiler.cc
index 8f226f6cde..2d9b01204a 100644
--- a/deps/v8/test/cctest/test-compiler.cc
+++ b/deps/v8/test/cctest/test-compiler.cc
@@ -26,7 +26,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdlib.h>
-#include <wchar.h> // wint_t
+#include <wchar.h>
#include "v8.h"
@@ -75,7 +75,7 @@ v8::Handle<v8::Value> PrintExtension::Print(const v8::Arguments& args) {
uint16_t* string = NewArray<uint16_t>(length + 1);
string_obj->Write(string);
for (int j = 0; j < length; j++)
- printf("%lc", static_cast<wint_t>(string[j]));
+ printf("%lc", static_cast<wchar_t>(string[j]));
DeleteArray(string);
}
printf("\n");
diff --git a/deps/v8/test/cctest/test-disasm-mips.cc b/deps/v8/test/cctest/test-disasm-mips.cc
index 901dbc1bf5..5ad99d7a39 100644
--- a/deps/v8/test/cctest/test-disasm-mips.cc
+++ b/deps/v8/test/cctest/test-disasm-mips.cc
@@ -274,23 +274,25 @@ TEST(Type0) {
COMPARE(srav(v0, v1, fp),
"03c31007 srav v0, v1, fp");
- COMPARE(rotr(a0, a1, 0),
- "00252002 rotr a0, a1, 0");
- COMPARE(rotr(s0, s1, 8),
- "00318202 rotr s0, s1, 8");
- COMPARE(rotr(t2, t3, 24),
- "002b5602 rotr t2, t3, 24");
- COMPARE(rotr(v0, v1, 31),
- "002317c2 rotr v0, v1, 31");
-
- COMPARE(rotrv(a0, a1, a2),
- "00c52046 rotrv a0, a1, a2");
- COMPARE(rotrv(s0, s1, s2),
- "02518046 rotrv s0, s1, s2");
- COMPARE(rotrv(t2, t3, t4),
- "018b5046 rotrv t2, t3, t4");
- COMPARE(rotrv(v0, v1, fp),
- "03c31046 rotrv v0, v1, fp");
+ if (mips32r2) {
+ COMPARE(rotr(a0, a1, 0),
+ "00252002 rotr a0, a1, 0");
+ COMPARE(rotr(s0, s1, 8),
+ "00318202 rotr s0, s1, 8");
+ COMPARE(rotr(t2, t3, 24),
+ "002b5602 rotr t2, t3, 24");
+ COMPARE(rotr(v0, v1, 31),
+ "002317c2 rotr v0, v1, 31");
+
+ COMPARE(rotrv(a0, a1, a2),
+ "00c52046 rotrv a0, a1, a2");
+ COMPARE(rotrv(s0, s1, s2),
+ "02518046 rotrv s0, s1, s2");
+ COMPARE(rotrv(t2, t3, t4),
+ "018b5046 rotrv t2, t3, t4");
+ COMPARE(rotrv(v0, v1, fp),
+ "03c31046 rotrv v0, v1, fp");
+ }
COMPARE(break_(0),
"0000000d break, code: 0x00000 (0)");
@@ -415,18 +417,21 @@ TEST(Type0) {
"72f6b020 clz s6, s7");
COMPARE(clz(v0, v1),
"70621020 clz v0, v1");
- COMPARE(ins_(a0, a1, 31, 1),
- "7ca4ffc4 ins a0, a1, 31, 1");
- COMPARE(ins_(s6, s7, 30, 2),
- "7ef6ff84 ins s6, s7, 30, 2");
- COMPARE(ins_(v0, v1, 0, 32),
- "7c62f804 ins v0, v1, 0, 32");
- COMPARE(ext_(a0, a1, 31, 1),
- "7ca407c0 ext a0, a1, 31, 1");
- COMPARE(ext_(s6, s7, 30, 2),
- "7ef60f80 ext s6, s7, 30, 2");
- COMPARE(ext_(v0, v1, 0, 32),
- "7c62f800 ext v0, v1, 0, 32");
+
+ if (mips32r2) {
+ COMPARE(ins_(a0, a1, 31, 1),
+ "7ca4ffc4 ins a0, a1, 31, 1");
+ COMPARE(ins_(s6, s7, 30, 2),
+ "7ef6ff84 ins s6, s7, 30, 2");
+ COMPARE(ins_(v0, v1, 0, 32),
+ "7c62f804 ins v0, v1, 0, 32");
+ COMPARE(ext_(a0, a1, 31, 1),
+ "7ca407c0 ext a0, a1, 31, 1");
+ COMPARE(ext_(s6, s7, 30, 2),
+ "7ef60f80 ext s6, s7, 30, 2");
+ COMPARE(ext_(v0, v1, 0, 32),
+ "7c62f800 ext v0, v1, 0, 32");
+ }
VERIFY_RUN();
}
diff --git a/deps/v8/test/cctest/test-regexp.cc b/deps/v8/test/cctest/test-regexp.cc
index 9f18b600b2..46ac88cd92 100644
--- a/deps/v8/test/cctest/test-regexp.cc
+++ b/deps/v8/test/cctest/test-regexp.cc
@@ -30,14 +30,15 @@
#include "v8.h"
-#include "string-stream.h"
-#include "cctest.h"
-#include "zone-inl.h"
-#include "parser.h"
#include "ast.h"
+#include "char-predicates-inl.h"
+#include "cctest.h"
#include "jsregexp.h"
+#include "parser.h"
#include "regexp-macro-assembler.h"
#include "regexp-macro-assembler-irregexp.h"
+#include "string-stream.h"
+#include "zone-inl.h"
#ifdef V8_INTERPRETED_REGEXP
#include "interpreter-irregexp.h"
#else // V8_INTERPRETED_REGEXP
diff --git a/deps/v8/test/cctest/test-strings.cc b/deps/v8/test/cctest/test-strings.cc
index 17020a3254..55c21417d0 100644
--- a/deps/v8/test/cctest/test-strings.cc
+++ b/deps/v8/test/cctest/test-strings.cc
@@ -529,3 +529,32 @@ TEST(TrivialSlice) {
CHECK(string->IsSlicedString());
CHECK_EQ("bcdefghijklmnopqrstuvwxy", *(string->ToCString()));
}
+
+
+TEST(SliceFromSlice) {
+ // This tests whether a slice that contains the entire parent string
+ // actually creates a new string (it should not).
+ FLAG_string_slices = true;
+ InitializeVM();
+ HandleScope scope;
+ v8::Local<v8::Value> result;
+ Handle<String> string;
+ const char* init = "var str = 'abcdefghijklmnopqrstuvwxyz';";
+ const char* slice = "var slice = str.slice(1,-1); slice";
+ const char* slice_from_slice = "slice.slice(1,-1);";
+
+ CompileRun(init);
+ result = CompileRun(slice);
+ CHECK(result->IsString());
+ string = v8::Utils::OpenHandle(v8::String::Cast(*result));
+ CHECK(string->IsSlicedString());
+ CHECK(SlicedString::cast(*string)->parent()->IsSeqString());
+ CHECK_EQ("bcdefghijklmnopqrstuvwxy", *(string->ToCString()));
+
+ result = CompileRun(slice_from_slice);
+ CHECK(result->IsString());
+ string = v8::Utils::OpenHandle(v8::String::Cast(*result));
+ CHECK(string->IsSlicedString());
+ CHECK(SlicedString::cast(*string)->parent()->IsSeqString());
+ CHECK_EQ("cdefghijklmnopqrstuvwx", *(string->ToCString()));
+}
diff --git a/deps/v8/test/es5conform/es5conform.status b/deps/v8/test/es5conform/es5conform.status
index 55712baf69..d095a2471d 100644
--- a/deps/v8/test/es5conform/es5conform.status
+++ b/deps/v8/test/es5conform/es5conform.status
@@ -75,11 +75,11 @@ chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-214: UNIMPLEMENTED
# NOT IMPLEMENTED: RegExp.prototype.multiline
chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-215: UNIMPLEMENTED
-# All of the tests below marked SUBSETFAIL (in 15.2.3.4) fail because
+# All of the tests below marked SUBSETFAIL (in 15.2.3.4) fail because
# the tests assumes that objects can not have more properties
-# than those described in the spec - but according to spec they can
+# than those described in the spec - but according to spec they can
# have additional properties.
-# All compareArray calls in these tests could be exchanged with a
+# All compareArray calls in these tests could be exchanged with a
# isSubsetOfArray call (I will upload a patch to the es5conform site).
# SUBSETFAIL
diff --git a/deps/v8/test/mjsunit/array-constructor.js b/deps/v8/test/mjsunit/array-constructor.js
index 063ccde583..bf5d3d611a 100644
--- a/deps/v8/test/mjsunit/array-constructor.js
+++ b/deps/v8/test/mjsunit/array-constructor.js
@@ -73,7 +73,7 @@ for (var i = 0; i < loop_count; i++) {
a = new Array(0, 1, 2, 3, 4, 5, 6, 7, 8);
assertArrayEquals([0, 1, 2, 3, 4, 5, 6, 7, 8], a);
a = new Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
- assertArrayEquals([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], a);
+ assertArrayEquals([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], a);
}
@@ -91,9 +91,9 @@ function testConstructOfSizeSize(n) {
var a = eval('[' + str + ']');
var b = eval('new Array(' + str + ')')
var c = eval('Array(' + str + ')')
- assertEquals(n, a.length);
- assertArrayEquals(a, b);
- assertArrayEquals(a, c);
+ assertEquals(n, a.length);
+ assertArrayEquals(a, b);
+ assertArrayEquals(a, c);
}
diff --git a/deps/v8/test/mjsunit/array-iteration.js b/deps/v8/test/mjsunit/array-iteration.js
index f11b51cb8f..0ee2e6e9ac 100644
--- a/deps/v8/test/mjsunit/array-iteration.js
+++ b/deps/v8/test/mjsunit/array-iteration.js
@@ -134,7 +134,7 @@
a = [0,1];
assertFalse(a.every(function(n, index, array) { array[index] = n + 1; return n == 1;}));
assertArrayEquals([1,1], a);
-
+
// Only loop through initial part of array eventhough elements are
// added.
a = [1,1];
@@ -156,23 +156,23 @@
//
(function() {
var a = [0,1,2,3,4];
-
+
// Simple use.
var result = [1,2,3,4,5];
assertArrayEquals(result, a.map(function(n) { return n + 1; }));
assertEquals(a, a);
-
+
// Use specified object as this object when calling the function.
var o = { delta: 42 }
result = [42,43,44,45,46];
assertArrayEquals(result, a.map(function(n) { return this.delta + n; }, o));
-
+
// Modify original array.
a = [0,1,2,3,4];
result = [1,2,3,4,5];
assertArrayEquals(result, a.map(function(n, index, array) { array[index] = n + 1; return n + 1;}));
assertArrayEquals(result, a);
-
+
// Only loop through initial part of array eventhough elements are
// added.
a = [0,1,2,3,4];
@@ -197,7 +197,7 @@
// Simple use.
assertTrue(a.some(function(n) { return n == 3}));
assertFalse(a.some(function(n) { return n == 5}));
-
+
// Use specified object as this object when calling the function.
var o = { element: 42 };
a = [1,42,3];
diff --git a/deps/v8/test/mjsunit/array-sort.js b/deps/v8/test/mjsunit/array-sort.js
index fd18a5b2d9..3fa623a656 100644
--- a/deps/v8/test/mjsunit/array-sort.js
+++ b/deps/v8/test/mjsunit/array-sort.js
@@ -392,7 +392,7 @@ TestSpecialCasesInheritedElementSort();
// Test that sort calls compare function with global object as receiver,
// and with only elements of the array as arguments.
-function o(v) {
+function o(v) {
return {__proto__: o.prototype, val: v};
}
var arr = [o(1), o(2), o(4), o(8), o(16), o(32), o(64), o(128), o(256), o(-0)];
diff --git a/deps/v8/test/mjsunit/bugs/618.js b/deps/v8/test/mjsunit/bugs/618.js
index afa9929a60..ddc0c19c88 100644
--- a/deps/v8/test/mjsunit/bugs/618.js
+++ b/deps/v8/test/mjsunit/bugs/618.js
@@ -32,14 +32,14 @@ function C1() {
var c1 = new C1();
assertEquals(23, c1.x);
assertEquals("undefined", typeof c1.y);
-
+
// Add setter somewhere on the prototype chain after having constructed the
// first instance.
C1.prototype = { set x(value) { this.y = 23; } };
var c1 = new C1();
assertEquals("undefined", typeof c1.x);
assertEquals(23, c1.y);
-
+
// Simple class using inline constructor.
function C2() {
this.x = 23;
diff --git a/deps/v8/test/mjsunit/bugs/bug-618.js b/deps/v8/test/mjsunit/bugs/bug-618.js
index 8f47440354..ae843267ff 100644
--- a/deps/v8/test/mjsunit/bugs/bug-618.js
+++ b/deps/v8/test/mjsunit/bugs/bug-618.js
@@ -33,11 +33,11 @@ function C() {
this.x = 23;
}
-// If a setter is added to the prototype chain of a simple constructor setting
-// one of the properties assigned in the constructor then this setter is
+// If a setter is added to the prototype chain of a simple constructor setting
+// one of the properties assigned in the constructor then this setter is
// ignored when constructing new objects from the constructor.
-// This only happens if the setter is added _after_ an instance has been
+// This only happens if the setter is added _after_ an instance has been
// created.
assertEquals(23, new C().x);
diff --git a/deps/v8/test/mjsunit/builtins.js b/deps/v8/test/mjsunit/builtins.js
new file mode 100644
index 0000000000..f2ad5446a0
--- /dev/null
+++ b/deps/v8/test/mjsunit/builtins.js
@@ -0,0 +1,82 @@
+// Copyright 2011 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.
+
+// Flags: --expose-natives-as=builtins
+
+// Checks that all function properties of the builtin object are neither
+// writable nor configurable. Also, theose functions that are actually
+// constructors (recognized by having properties on their .prototype object),
+// have only unconfigurable properties on the prototype, and the methods
+// are also non-writable.
+
+var names = Object.getOwnPropertyNames(builtins);
+
+function isFunction(obj) {
+ return typeof obj == "function";
+}
+
+function checkConstructor(func, name) {
+ // A constructor is a function with a prototype and properties on the
+ // prototype object besides "constructor";
+ if (name.charAt(0) == "$") return;
+ if (typeof func.prototype != "object") return;
+ var propNames = Object.getOwnPropertyNames(func.prototype);
+ if (propNames.length == 0 ||
+ (propNames.length == 1 && propNames[0] == "constructor")) {
+ // Not a constructor.
+ return;
+ }
+ var proto_desc = Object.getOwnPropertyDescriptor(func, "prototype");
+ assertTrue(proto_desc.hasOwnProperty("value"), name);
+ assertFalse(proto_desc.writable, name);
+ assertFalse(proto_desc.configurable, name);
+ var prototype = proto_desc.value;
+ assertEquals(null, prototype.__proto__, name);
+ for (var i = 0; i < propNames.length; i++) {
+ var propName = propNames[i];
+ if (propName == "constructor") continue;
+ var testName = name + "-" + propName;
+ var propDesc = Object.getOwnPropertyDescriptor(prototype, propName);
+ assertTrue(propDesc.hasOwnProperty("value"), testName);
+ assertFalse(propDesc.configurable, testName);
+ if (isFunction(propDesc.value)) {
+ assertFalse(propDesc.writable, testName);
+ }
+ }
+}
+
+for (var i = 0; i < names.length; i++) {
+ var name = names[i];
+ var desc = Object.getOwnPropertyDescriptor(builtins, name);
+ assertTrue(desc.hasOwnProperty("value"));
+ var value = desc.value;
+ if (isFunction(value)) {
+ assertFalse(desc.writable, name);
+ assertFalse(desc.configurable, name);
+ checkConstructor(value, name);
+ }
+}
diff --git a/deps/v8/test/mjsunit/compiler/delete.js b/deps/v8/test/mjsunit/compiler/delete.js
index 373a1cbcf3..2aaecb25b6 100644
--- a/deps/v8/test/mjsunit/compiler/delete.js
+++ b/deps/v8/test/mjsunit/compiler/delete.js
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 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:
@@ -66,6 +66,7 @@ assertEquals(2, ((delete 0) || 2) + 1);
assertEquals(3, (function (x) { return ((delete x) || 2) + 1; })(0));
-// 'this' at toplevel is different from all other global variables---not
-// deletable.
+// 'this' is not a Reference so delete returns true (see section 11.4.1,
+// step 2 of ES 5.1).
assertEquals(true, delete this);
+assertEquals(true, (function () { return delete this; })());
diff --git a/deps/v8/test/mjsunit/compiler/global-accessors.js b/deps/v8/test/mjsunit/compiler/global-accessors.js
index bd031a8329..337424dc41 100644
--- a/deps/v8/test/mjsunit/compiler/global-accessors.js
+++ b/deps/v8/test/mjsunit/compiler/global-accessors.js
@@ -26,7 +26,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// This test tests that no bailouts are missing by not hitting asserts in debug
-// mode.
+// mode.
test_count_operation()
test_compound_assignment()
diff --git a/deps/v8/test/mjsunit/const-redecl.js b/deps/v8/test/mjsunit/const-redecl.js
index 26d765b97a..945970891b 100644
--- a/deps/v8/test/mjsunit/const-redecl.js
+++ b/deps/v8/test/mjsunit/const-redecl.js
@@ -55,7 +55,7 @@ function TestLocal(s,e) {
function TestGlobal(s,e) {
// Collect the global properties before the call.
var properties = [];
- for (var key in this) properties.push(key);
+ for (var key in this) properties.push(key);
// Compute the result.
var result;
try {
@@ -113,7 +113,7 @@ function TestConflict(def0, def1) {
// Eval second definition.
TestAll("TypeError", def0 + '; eval("' + def1 + '")');
// Eval both definitions separately.
- TestAll("TypeError", 'eval("' + def0 +'"); eval("' + def1 + '")');
+ TestAll("TypeError", 'eval("' + def0 +'"); eval("' + def1 + '")');
}
diff --git a/deps/v8/test/mjsunit/d8-os.js b/deps/v8/test/mjsunit/d8-os.js
index fd6fb774ea..5640326856 100644
--- a/deps/v8/test/mjsunit/d8-os.js
+++ b/deps/v8/test/mjsunit/d8-os.js
@@ -30,7 +30,7 @@
// implemented on Windows, and even if it were then many of the things
// we are calling would not be available.
-var TEST_DIR = "d8-os-test-directory-" + ((Math.random() * (1<<30)) | 0);
+var TEST_DIR = "/tmp/d8-os-test-directory-" + ((Math.random() * (1<<30)) | 0);
function arg_error(str) {
@@ -64,7 +64,7 @@ if (this.os && os.system) {
os.chdir(TEST_DIR);
try {
// Check the chdir worked.
- os.system('ls', ['../' + TEST_DIR]);
+ os.system('ls', [TEST_DIR]);
// Simple create dir.
os.mkdirp("dir");
// Create dir in dir.
@@ -144,7 +144,6 @@ if (this.os && os.system) {
//}
}
} finally {
- os.chdir("..");
os.system("rm", ["-r", TEST_DIR]);
}
diff --git a/deps/v8/test/mjsunit/date-parse.js b/deps/v8/test/mjsunit/date-parse.js
index a1eef663b9..b46e39ab61 100644
--- a/deps/v8/test/mjsunit/date-parse.js
+++ b/deps/v8/test/mjsunit/date-parse.js
@@ -286,7 +286,7 @@ for (var i = 0; i < 24 * 365 * 100; i += 150) {
// Negative tests.
var testCasesNegative = [
'May 25 2008 1:30 (PM)) UTC', // Bad unmatched ')' after number.
- 'May 25 2008 1:30( )AM (PM)', //
+ 'May 25 2008 1:30( )AM (PM)', //
'May 25 2008 AAA (GMT)']; // Unknown word after number.
testCasesNegative.forEach(function (s) {
diff --git a/deps/v8/test/mjsunit/debug-compile-event.js b/deps/v8/test/mjsunit/debug-compile-event.js
index b00a907a3c..94dddfa104 100644
--- a/deps/v8/test/mjsunit/debug-compile-event.js
+++ b/deps/v8/test/mjsunit/debug-compile-event.js
@@ -81,7 +81,7 @@ function listener(event, exec_state, event_data, data) {
assertTrue('context' in msg.body.script);
// Check that we pick script name from //@ sourceURL, iff present
- assertEquals(current_source.indexOf('sourceURL') >= 0 ?
+ assertEquals(current_source.indexOf('sourceURL') >= 0 ?
'myscript.js' : undefined,
event_data.script().name());
}
diff --git a/deps/v8/test/mjsunit/debug-evaluate-recursive.js b/deps/v8/test/mjsunit/debug-evaluate-recursive.js
index 6ee391b63b..f34943e5f4 100644
--- a/deps/v8/test/mjsunit/debug-evaluate-recursive.js
+++ b/deps/v8/test/mjsunit/debug-evaluate-recursive.js
@@ -110,7 +110,7 @@ function listener_recurse(event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break)
{
break_count++;
-
+
// Call functions with break using the FrameMirror directly.
if (break_count == 1) {
// First break event evaluates with break enabled.
diff --git a/deps/v8/test/mjsunit/debug-handle.js b/deps/v8/test/mjsunit/debug-handle.js
index 98875ceb41..1582b9f121 100644
--- a/deps/v8/test/mjsunit/debug-handle.js
+++ b/deps/v8/test/mjsunit/debug-handle.js
@@ -72,7 +72,7 @@ function lookupRequest(exec_state, arguments, success) {
// The base part of all lookup requests.
var base_request = '"seq":0,"type":"request","command":"lookup"'
-
+
// Generate request with the supplied arguments.
var request;
if (arguments) {
@@ -214,7 +214,7 @@ function listener(event, exec_state, event_data, data) {
'Handle not in the request: ' + handle);
count++;
}
- assertEquals(count, obj.properties.length,
+ assertEquals(count, obj.properties.length,
'Unexpected number of resolved objects');
diff --git a/deps/v8/test/mjsunit/debug-listbreakpoints.js b/deps/v8/test/mjsunit/debug-listbreakpoints.js
index de0114fe09..1d4755fd1b 100644
--- a/deps/v8/test/mjsunit/debug-listbreakpoints.js
+++ b/deps/v8/test/mjsunit/debug-listbreakpoints.js
@@ -39,7 +39,7 @@ Debug = debug.Debug
// below. The test checks for these line numbers.
function g() { // line 40
- var x = 5;
+ var x = 5;
var y = 6;
var z = 7;
};
diff --git a/deps/v8/test/mjsunit/debug-references.js b/deps/v8/test/mjsunit/debug-references.js
index ab6c6292e3..763e354fc8 100644
--- a/deps/v8/test/mjsunit/debug-references.js
+++ b/deps/v8/test/mjsunit/debug-references.js
@@ -52,7 +52,7 @@ function testRequest(dcp, arguments, success, count) {
} else {
request = '{' + base_request + '}'
}
-
+
// Process the request and check expectation.
var response = safeEval(dcp.processDebugJSONRequest(request));
if (success) {
@@ -88,7 +88,7 @@ function listener(event, exec_state, event_data, data) {
var response = safeEval(dcp.processDebugJSONRequest(evaluate_point));
assertTrue(response.success, "Evaluation of Point failed");
var handle = response.body.handle;
-
+
// Test some legal references requests.
testRequest(dcp, '{"handle":' + handle + ',"type":"referencedBy"}', true);
testRequest(dcp, '{"handle":' + handle + ',"type":"constructedBy"}',
diff --git a/deps/v8/test/mjsunit/debug-return-value.js b/deps/v8/test/mjsunit/debug-return-value.js
index 3982ea91b3..02d6a7cbc9 100644
--- a/deps/v8/test/mjsunit/debug-return-value.js
+++ b/deps/v8/test/mjsunit/debug-return-value.js
@@ -103,12 +103,12 @@ function listener(event, exec_state, event_data, data) {
// Position at the end of the function.
assertEquals(debugger_source_position + 50,
exec_state.frame(0).sourcePosition());
-
+
// Just about to return from the function.
assertTrue(exec_state.frame(0).isAtReturn())
assertEquals(expected_return_value,
exec_state.frame(0).returnValue().value());
-
+
// Check the same using the JSON commands.
var dcp = exec_state.debugCommandProcessor(false);
var request = '{"seq":0,"type":"request","command":"backtrace"}';
@@ -118,7 +118,7 @@ function listener(event, exec_state, event_data, data) {
assertTrue(frames[0].atReturn);
assertEquals(expected_return_value,
response.lookup(frames[0].returnValue.ref).value);
-
+
listener_complete = true;
}
}
@@ -132,7 +132,7 @@ Debug.setListener(listener);
// Four steps from the debugger statement in this function will position us at
// the function return.
-// 0 1 2 3 4 5
+// 0 1 2 3 4 5
// 0123456789012345678901234567890123456789012345678901
function f(x) {debugger; if (x) { return 1; } else { return 2; } };
diff --git a/deps/v8/test/mjsunit/debug-stepin-call-function-stub.js b/deps/v8/test/mjsunit/debug-stepin-call-function-stub.js
index c5cf8fdf3a..053b8bfe8a 100644
--- a/deps/v8/test/mjsunit/debug-stepin-call-function-stub.js
+++ b/deps/v8/test/mjsunit/debug-stepin-call-function-stub.js
@@ -62,7 +62,7 @@ function listener(event, exec_state, event_data, data) {
Debug.setListener(listener);
-function g() {
+function g() {
return "s"; // expected line
}
@@ -71,7 +71,7 @@ function testFunction() {
var s = 1 +f(10);
}
-function g2() {
+function g2() {
return "s2"; // expected line
}
diff --git a/deps/v8/test/mjsunit/debug-stepin-constructor.js b/deps/v8/test/mjsunit/debug-stepin-constructor.js
index 6ee3347352..5549814a65 100644
--- a/deps/v8/test/mjsunit/debug-stepin-constructor.js
+++ b/deps/v8/test/mjsunit/debug-stepin-constructor.js
@@ -38,7 +38,7 @@ function listener(event, exec_state, event_data, data) {
if (exec_state.frameCount() > 1) {
exec_state.prepareStep(Debug.StepAction.StepIn);
}
-
+
// Test that there is a script.
assertTrue(typeof(event_data.func().script()) == 'object');
}
diff --git a/deps/v8/test/mjsunit/delete-in-with.js b/deps/v8/test/mjsunit/delete-in-with.js
index 1efc18de11..cbcfe991b8 100644
--- a/deps/v8/test/mjsunit/delete-in-with.js
+++ b/deps/v8/test/mjsunit/delete-in-with.js
@@ -29,6 +29,6 @@
// objects from within 'with' statements.
(function(){
var tmp = { x: 12 };
- with (tmp) { assertTrue(delete x); }
+ with (tmp) { assertTrue(delete x); }
assertFalse("x" in tmp);
})();
diff --git a/deps/v8/test/mjsunit/function-source.js b/deps/v8/test/mjsunit/function-source.js
index 75257756d6..8f2fc2265c 100644
--- a/deps/v8/test/mjsunit/function-source.js
+++ b/deps/v8/test/mjsunit/function-source.js
@@ -36,7 +36,7 @@ function f() {
}
h();
}
-
+
function g() {
function h() {
assertEquals(Debug.scriptSource(f), Debug.scriptSource(h));
diff --git a/deps/v8/test/mjsunit/get-own-property-descriptor.js b/deps/v8/test/mjsunit/get-own-property-descriptor.js
index 79c1fac6ae..abb2420034 100644
--- a/deps/v8/test/mjsunit/get-own-property-descriptor.js
+++ b/deps/v8/test/mjsunit/get-own-property-descriptor.js
@@ -27,7 +27,7 @@
// This file only tests very simple descriptors that always have
// configurable, enumerable, and writable set to true.
-// A range of more elaborate tests are performed in
+// A range of more elaborate tests are performed in
// object-define-property.js
function get() { return x; }
diff --git a/deps/v8/test/mjsunit/global-deleted-property-keyed.js b/deps/v8/test/mjsunit/global-deleted-property-keyed.js
index 1a1d3cb99b..dba3a4d405 100644
--- a/deps/v8/test/mjsunit/global-deleted-property-keyed.js
+++ b/deps/v8/test/mjsunit/global-deleted-property-keyed.js
@@ -33,6 +33,6 @@
var name = "fisk";
natives[name] = name;
function foo() { natives[name] + 12; }
-for(var i = 0; i < 3; i++) foo();
+for(var i = 0; i < 3; i++) foo();
delete natives[name];
for(var i = 0; i < 3; i++) foo();
diff --git a/deps/v8/test/mjsunit/harmony/block-conflicts.js b/deps/v8/test/mjsunit/harmony/block-conflicts.js
new file mode 100644
index 0000000000..8d3de6f9d6
--- /dev/null
+++ b/deps/v8/test/mjsunit/harmony/block-conflicts.js
@@ -0,0 +1,126 @@
+// Copyright 2011 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.
+
+// Flags: --harmony-block-scoping
+
+// Test for conflicting variable bindings.
+
+function CheckException(e) {
+ var string = e.toString();
+ assertTrue(string.indexOf("has already been declared") >= 0 ||
+ string.indexOf("redeclaration") >= 0); return 'Conflict';
+}
+
+
+function TestFunction(s,e) {
+ try {
+ return eval("(function(){" + s + ";return " + e + "})")();
+ } catch (x) {
+ return CheckException(x);
+ }
+}
+
+
+function TestBlock(s,e) {
+ try {
+ return eval("(function(){ if (true) { " + s + "; }; return " + e + "})")();
+ } catch (x) {
+ return CheckException(x);
+ }
+}
+
+function TestAll(expected,s,opt_e) {
+ var e = "";
+ var msg = s;
+ if (opt_e) { e = opt_e; msg += "; " + opt_e; }
+ assertEquals(expected, TestFunction(s,e), "function:'" + msg + "'");
+ assertEquals(expected, TestBlock(s,e), "block:'" + msg + "'");
+}
+
+
+function TestConflict(s) {
+ TestAll('Conflict', s);
+ TestAll('Conflict', 'eval("' + s + '")');
+}
+
+
+function TestNoConflict(s) {
+ TestAll('NoConflict', s, "'NoConflict'");
+ TestAll('NoConflict', 'eval("' + s + '")', "'NoConflict'");
+}
+
+var letbinds = [ "let x",
+ "let x = 0",
+ "let x = undefined",
+ "function x() { }",
+ "let x = function() {}",
+ "let x, y",
+ "let y, x",
+ ];
+var varbinds = [ "var x",
+ "var x = 0",
+ "var x = undefined",
+ "var x = function() {}",
+ "var x, y",
+ "var y, x",
+ ];
+
+
+for (var l = 0; l < letbinds.length; ++l) {
+ // Test conflicting let/var bindings.
+ for (var v = 0; v < varbinds.length; ++v) {
+ // Same level.
+ TestConflict(letbinds[l] +'; ' + varbinds[v]);
+ TestConflict(varbinds[v] +'; ' + letbinds[l]);
+ // Different level.
+ TestConflict(letbinds[l] +'; {' + varbinds[v] + '; }');
+ TestConflict('{ ' + varbinds[v] +'; }' + letbinds[l]);
+ }
+
+ // Test conflicting let/let bindings.
+ for (var k = 0; k < letbinds.length; ++k) {
+ // Same level.
+ TestConflict(letbinds[l] +'; ' + letbinds[k]);
+ TestConflict(letbinds[k] +'; ' + letbinds[l]);
+ // Different level.
+ TestNoConflict(letbinds[l] +'; { ' + letbinds[k] + '; }');
+ TestNoConflict('{ ' + letbinds[k] +'; } ' + letbinds[l]);
+ }
+
+ // Test conflicting parameter/let bindings.
+ TestConflict('(function (x) { ' + letbinds[l] + '; })()');
+}
+
+// Test conflicting catch/var bindings.
+for (var v = 0; v < varbinds.length; ++v) {
+ TestConflict('try {} catch (x) { ' + varbinds[v] + '; }');
+}
+
+// Test conflicting parameter/var bindings.
+for (var v = 0; v < varbinds.length; ++v) {
+ TestConflict('(function (x) { ' + varbinds[v] + '; })()');
+}
diff --git a/deps/v8/test/mjsunit/harmony/block-leave.js b/deps/v8/test/mjsunit/harmony/block-leave.js
new file mode 100644
index 0000000000..73eaf29449
--- /dev/null
+++ b/deps/v8/test/mjsunit/harmony/block-leave.js
@@ -0,0 +1,225 @@
+// Copyright 2011 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.
+
+// Flags: --harmony-block-scoping
+
+// We want to test the context chain shape. In each of the tests cases
+// below, the outer with is to force a runtime lookup of the identifier 'x'
+// to actually verify that the inner context has been discarded. A static
+// lookup of 'x' might accidentally succeed.
+
+{
+ let x = 2;
+ L: {
+ let x = 3;
+ assertEquals(3, x);
+ break L;
+ assertTrue(false);
+ }
+ assertEquals(2, x);
+}
+
+do {
+ let x = 4;
+ assertEquals(4,x);
+ {
+ let x = 5;
+ assertEquals(5, x);
+ continue;
+ assertTrue(false);
+ }
+} while (false);
+
+var caught = false;
+try {
+ {
+ let xx = 18;
+ throw 25;
+ assertTrue(false);
+ }
+} catch (e) {
+ caught = true;
+ assertEquals(25, e);
+ with ({y:19}) {
+ assertEquals(19, y);
+ try {
+ // NOTE: This checks that the block scope containing xx has been
+ // removed from the context chain.
+ xx;
+ assertTrue(false); // should not reach here
+ } catch (e2) {
+ assertTrue(e2 instanceof ReferenceError);
+ }
+ }
+}
+assertTrue(caught);
+
+
+with ({x: 'outer'}) {
+ label: {
+ let x = 'inner';
+ break label;
+ }
+ assertEquals('outer', x);
+}
+
+
+with ({x: 'outer'}) {
+ label: {
+ let x = 'middle';
+ {
+ let x = 'inner';
+ break label;
+ }
+ }
+ assertEquals('outer', x);
+}
+
+
+with ({x: 'outer'}) {
+ for (var i = 0; i < 10; ++i) {
+ let x = 'inner' + i;
+ continue;
+ }
+ assertEquals('outer', x);
+}
+
+
+with ({x: 'outer'}) {
+ label: for (var i = 0; i < 10; ++i) {
+ let x = 'middle' + i;
+ for (var j = 0; j < 10; ++j) {
+ let x = 'inner' + j;
+ continue label;
+ }
+ }
+ assertEquals('outer', x);
+}
+
+
+with ({x: 'outer'}) {
+ try {
+ let x = 'inner';
+ throw 0;
+ } catch (e) {
+ assertEquals('outer', x);
+ }
+}
+
+
+with ({x: 'outer'}) {
+ try {
+ let x = 'middle';
+ {
+ let x = 'inner';
+ throw 0;
+ }
+ } catch (e) {
+ assertEquals('outer', x);
+ }
+}
+
+
+try {
+ with ({x: 'outer'}) {
+ try {
+ let x = 'inner';
+ throw 0;
+ } finally {
+ assertEquals('outer', x);
+ }
+ }
+} catch (e) {
+ if (e instanceof MjsUnitAssertionError) throw e;
+}
+
+
+try {
+ with ({x: 'outer'}) {
+ try {
+ let x = 'middle';
+ {
+ let x = 'inner';
+ throw 0;
+ }
+ } finally {
+ assertEquals('outer', x);
+ }
+ }
+} catch (e) {
+ if (e instanceof MjsUnitAssertionError) throw e;
+}
+
+
+// Verify that the context is correctly set in the stack frame after exiting
+// from with.
+function f() {}
+
+with ({x: 'outer'}) {
+ label: {
+ let x = 'inner';
+ break label;
+ }
+ f(); // The context could be restored from the stack after the call.
+ assertEquals('outer', x);
+}
+
+
+with ({x: 'outer'}) {
+ for (var i = 0; i < 10; ++i) {
+ let x = 'inner';
+ continue;
+ }
+ f();
+ assertEquals('outer', x);
+}
+
+
+with ({x: 'outer'}) {
+ try {
+ let x = 'inner';
+ throw 0;
+ } catch (e) {
+ f();
+ assertEquals('outer', x);
+ }
+}
+
+
+try {
+ with ({x: 'outer'}) {
+ try {
+ let x = 'inner';
+ throw 0;
+ } finally {
+ f();
+ assertEquals('outer', x);
+ }
+ }
+} catch (e) {
+ if (e instanceof MjsUnitAssertionError) throw e;
+}
diff --git a/deps/v8/test/mjsunit/harmony/block-let-crankshaft.js b/deps/v8/test/mjsunit/harmony/block-let-crankshaft.js
new file mode 100644
index 0000000000..c2fb96b6a4
--- /dev/null
+++ b/deps/v8/test/mjsunit/harmony/block-let-crankshaft.js
@@ -0,0 +1,63 @@
+// Copyright 2011 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.
+
+// Flags: --harmony-block-scoping --allow-natives-syntax
+
+// Test that temporal dead zone semantics for function and block scoped
+// ket bindings are handled by the optimizing compiler.
+
+function f(x, b) {
+ let y = (b ? y : x) + 42;
+ return y;
+}
+
+function g(x, b) {
+ {
+ let y = (b ? y : x) + 42;
+ return y;
+ }
+}
+
+for (var i=0; i<10; i++) {
+ f(i, false);
+ g(i, false);
+}
+
+%OptimizeFunctionOnNextCall(f);
+%OptimizeFunctionOnNextCall(g);
+
+try {
+ f(42, true);
+} catch (e) {
+ assertInstanceof(e, ReferenceError);
+}
+
+try {
+ g(42, true);
+} catch (e) {
+ assertInstanceof(e, ReferenceError);
+}
diff --git a/deps/v8/test/mjsunit/harmony/block-let-declaration.js b/deps/v8/test/mjsunit/harmony/block-let-declaration.js
index 19c943f14c..49b63481a0 100644
--- a/deps/v8/test/mjsunit/harmony/block-let-declaration.js
+++ b/deps/v8/test/mjsunit/harmony/block-let-declaration.js
@@ -57,11 +57,9 @@ function TestLocalDoesNotThrow(str) {
// Unprotected statement
TestLocalThrows("if (true) let x;", SyntaxError);
-TestLocalThrows("with ({}) let x;", SyntaxError);
TestLocalThrows("do let x; while (false)", SyntaxError);
TestLocalThrows("while (false) let x;", SyntaxError);
TestLocalDoesNotThrow("if (true) var x;");
-TestLocalDoesNotThrow("with ({}) var x;");
TestLocalDoesNotThrow("do var x; while (false)");
TestLocalDoesNotThrow("while (false) var x;");
diff --git a/deps/v8/test/mjsunit/harmony/block-let-semantics.js b/deps/v8/test/mjsunit/harmony/block-let-semantics.js
new file mode 100644
index 0000000000..198c3b4fb9
--- /dev/null
+++ b/deps/v8/test/mjsunit/harmony/block-let-semantics.js
@@ -0,0 +1,138 @@
+// Copyright 2011 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.
+
+// Flags: --harmony-block-scoping
+
+// Test temporal dead zone semantics of let bound variables in
+// function and block scopes.
+
+function TestFunctionLocal(s) {
+ try {
+ eval("(function(){" + s + "; })")();
+ } catch (e) {
+ assertInstanceof(e, ReferenceError);
+ return;
+ }
+ assertUnreachable();
+}
+
+function TestBlockLocal(s,e) {
+ try {
+ eval("(function(){ {" + s + ";} })")();
+ } catch (e) {
+ assertInstanceof(e, ReferenceError);
+ return;
+ }
+ assertUnreachable();
+}
+
+
+function TestAll(s) {
+ TestBlockLocal(s);
+ TestFunctionLocal(s);
+}
+
+// Use before initialization in declaration statement.
+TestAll('let x = x + 1');
+TestAll('let x = x += 1');
+TestAll('let x = x++');
+TestAll('let x = ++x');
+
+// Use before initialization in prior statement.
+TestAll('x + 1; let x;');
+TestAll('x = 1; let x;');
+TestAll('x += 1; let x;');
+TestAll('++x; let x;');
+TestAll('x++; let x;');
+
+TestAll('f(); let x; function f() { return x + 1; }');
+TestAll('f(); let x; function f() { x = 1; }');
+TestAll('f(); let x; function f() { x += 1; }');
+TestAll('f(); let x; function f() { ++x; }');
+TestAll('f(); let x; function f() { x++; }');
+
+TestAll('f()(); let x; function f() { return function() { return x + 1; } }');
+TestAll('f()(); let x; function f() { return function() { x = 1; } }');
+TestAll('f()(); let x; function f() { return function() { x += 1; } }');
+TestAll('f()(); let x; function f() { return function() { ++x; } }');
+TestAll('f()(); let x; function f() { return function() { x++; } }');
+
+// Use in before initialization with a dynamic lookup.
+TestAll('eval("x + 1;"); let x;');
+TestAll('eval("x = 1;"); let x;');
+TestAll('eval("x += 1;"); let x;');
+TestAll('eval("++x;"); let x;');
+TestAll('eval("x++;"); let x;');
+
+// Test that variables introduced by function declarations are created and
+// initialized upon entering a function / block scope.
+function f() {
+ {
+ assertEquals(2, g1());
+ assertEquals(2, eval("g1()"));
+
+ // block scoped function declaration
+ function g1() {
+ return 2;
+ }
+ }
+
+ assertEquals(3, g2());
+ assertEquals(3, eval("g2()"));
+ // function scoped function declaration
+ function g2() {
+ return 3;
+ }
+}
+f();
+
+// Test that a function declaration introduces a block scoped variable.
+TestAll('{ function k() { return 0; } }; k(); ');
+
+// Test that a function declaration sees the scope it resides in.
+function f2() {
+ let m, n;
+ {
+ m = g;
+ function g() {
+ return a;
+ }
+ let a = 1;
+ }
+ assertEquals(1, m());
+
+ try {
+ throw 2;
+ } catch(b) {
+ n = h;
+ function h() {
+ return b + c;
+ }
+ let b = 3;
+ }
+ assertEquals(5, n());
+}
diff --git a/deps/v8/test/mjsunit/harmony/debug-blockscopes.js b/deps/v8/test/mjsunit/harmony/debug-blockscopes.js
index e0df71b2df..0230e84b5e 100644
--- a/deps/v8/test/mjsunit/harmony/debug-blockscopes.js
+++ b/deps/v8/test/mjsunit/harmony/debug-blockscopes.js
@@ -202,17 +202,15 @@ function local_block_1() {
}
listener_delegate = function(exec_state) {
- CheckScopeChain([debug.ScopeType.Block,
- debug.ScopeType.Local,
+ CheckScopeChain([debug.ScopeType.Local,
debug.ScopeType.Global], exec_state);
CheckScopeContent({}, 0, exec_state);
- CheckScopeContent({}, 1, exec_state);
};
local_block_1();
EndTest();
-// Local scope with a parameter.
+// Simple empty block scope in local scope with a parameter.
BeginTest("Local 2");
function local_2(a) {
@@ -222,10 +220,9 @@ function local_2(a) {
}
listener_delegate = function(exec_state) {
- CheckScopeChain([debug.ScopeType.Block,
- debug.ScopeType.Local,
+ CheckScopeChain([debug.ScopeType.Local,
debug.ScopeType.Global], exec_state);
- CheckScopeContent({a:1}, 1, exec_state);
+ CheckScopeContent({a:1}, 0, exec_state);
};
local_2(1);
EndTest();
@@ -266,6 +263,72 @@ local_4(1, 2);
EndTest();
+// Single variable in a block scope.
+BeginTest("Local 5");
+
+function local_5(a) {
+ {
+ let x = 5;
+ debugger;
+ }
+}
+
+listener_delegate = function(exec_state) {
+ CheckScopeChain([debug.ScopeType.Block,
+ debug.ScopeType.Local,
+ debug.ScopeType.Global], exec_state);
+ CheckScopeContent({x:5}, 0, exec_state);
+ CheckScopeContent({a:1}, 1, exec_state);
+};
+local_5(1);
+EndTest();
+
+
+// Two variables in a block scope.
+BeginTest("Local 6");
+
+function local_6(a) {
+ {
+ let x = 6;
+ let y = 7;
+ debugger;
+ }
+}
+
+listener_delegate = function(exec_state) {
+ CheckScopeChain([debug.ScopeType.Block,
+ debug.ScopeType.Local,
+ debug.ScopeType.Global], exec_state);
+ CheckScopeContent({x:6,y:7}, 0, exec_state);
+ CheckScopeContent({a:1}, 1, exec_state);
+};
+local_6(1);
+EndTest();
+
+
+// Two variables in a block scope.
+BeginTest("Local 7");
+
+function local_7(a) {
+ {
+ {
+ let x = 8;
+ debugger;
+ }
+ }
+}
+
+listener_delegate = function(exec_state) {
+ CheckScopeChain([debug.ScopeType.Block,
+ debug.ScopeType.Local,
+ debug.ScopeType.Global], exec_state);
+ CheckScopeContent({x:8}, 0, exec_state);
+ CheckScopeContent({a:1}, 1, exec_state);
+};
+local_7(1);
+EndTest();
+
+
// Single empty with block.
BeginTest("With block 1");
@@ -276,8 +339,7 @@ function with_block_1() {
}
listener_delegate = function(exec_state) {
- CheckScopeChain([debug.ScopeType.Block,
- debug.ScopeType.With,
+ CheckScopeChain([debug.ScopeType.With,
debug.ScopeType.Local,
debug.ScopeType.Global], exec_state);
CheckScopeContent({}, 0, exec_state);
@@ -299,16 +361,13 @@ function with_block_2() {
}
listener_delegate = function(exec_state) {
- CheckScopeChain([debug.ScopeType.Block,
- debug.ScopeType.With,
- debug.ScopeType.Block,
+ CheckScopeChain([debug.ScopeType.With,
debug.ScopeType.With,
debug.ScopeType.Local,
debug.ScopeType.Global], exec_state);
CheckScopeContent({}, 0, exec_state);
CheckScopeContent({}, 1, exec_state);
CheckScopeContent({}, 2, exec_state);
- CheckScopeContent({}, 3, exec_state);
};
with_block_2();
EndTest();
@@ -324,12 +383,10 @@ function with_block_3() {
}
listener_delegate = function(exec_state) {
- CheckScopeChain([debug.ScopeType.Block,
- debug.ScopeType.With,
+ CheckScopeChain([debug.ScopeType.With,
debug.ScopeType.Local,
debug.ScopeType.Global], exec_state);
- CheckScopeContent({}, 0, exec_state);
- CheckScopeContent({a:1,b:2}, 1, exec_state);
+ CheckScopeContent({a:1,b:2}, 0, exec_state);
};
with_block_3();
EndTest();
@@ -347,19 +404,39 @@ function with_block_4() {
}
listener_delegate = function(exec_state) {
- CheckScopeChain([debug.ScopeType.Block,
- debug.ScopeType.With,
- debug.ScopeType.Block,
+ CheckScopeChain([debug.ScopeType.With,
debug.ScopeType.With,
debug.ScopeType.Local,
debug.ScopeType.Global], exec_state);
- CheckScopeContent({a:2,b:1}, 1, exec_state);
- CheckScopeContent({a:1,b:2}, 3, exec_state);
+ CheckScopeContent({a:2,b:1}, 0, exec_state);
+ CheckScopeContent({a:1,b:2}, 1, exec_state);
};
with_block_4();
EndTest();
+// With block and a block local variable.
+BeginTest("With block 5");
+
+function with_block_5() {
+ with({a:1}) {
+ let a = 2;
+ debugger;
+ }
+}
+
+listener_delegate = function(exec_state) {
+ CheckScopeChain([debug.ScopeType.Block,
+ debug.ScopeType.With,
+ debug.ScopeType.Local,
+ debug.ScopeType.Global], exec_state);
+ CheckScopeContent({a:2}, 0, exec_state);
+ CheckScopeContent({a:1}, 1, exec_state);
+};
+with_block_5();
+EndTest();
+
+
// Simple closure formed by returning an inner function referering to an outer
// block local variable and an outer function's parameter.
BeginTest("Closure 1");
diff --git a/deps/v8/test/mjsunit/harmony/weakmaps.js b/deps/v8/test/mjsunit/harmony/weakmaps.js
index 97f553cf29..e43f9167e6 100644
--- a/deps/v8/test/mjsunit/harmony/weakmaps.js
+++ b/deps/v8/test/mjsunit/harmony/weakmaps.js
@@ -137,6 +137,7 @@ assertTrue(WeakMap.prototype.set instanceof Function)
assertTrue(WeakMap.prototype.get instanceof Function)
assertTrue(WeakMap.prototype.has instanceof Function)
assertTrue(WeakMap.prototype.delete instanceof Function)
+assertTrue(WeakMap.prototype.constructor === WeakMap)
// Regression test for issue 1617: The prototype of the WeakMap constructor
diff --git a/deps/v8/test/mjsunit/html-string-funcs.js b/deps/v8/test/mjsunit/html-string-funcs.js
index 213b7f3412..b640639d8a 100644
--- a/deps/v8/test/mjsunit/html-string-funcs.js
+++ b/deps/v8/test/mjsunit/html-string-funcs.js
@@ -29,7 +29,7 @@
// HTML.
function CheckSimple(f, tag) {
assertEquals('<' + tag + '>foo</' + tag + '>',
- "foo"[f]().toLowerCase());
+ "foo"[f]().toLowerCase());
};
var simple = { big: 'big', blink: 'blink', bold: 'b',
fixed: 'tt', italics: 'i', small: 'small',
diff --git a/deps/v8/test/mjsunit/in.js b/deps/v8/test/mjsunit/in.js
index f98db42f61..cca6187827 100644
--- a/deps/v8/test/mjsunit/in.js
+++ b/deps/v8/test/mjsunit/in.js
@@ -86,7 +86,7 @@ a[1] = 2;
assertFalse(0 in a);
assertTrue(1 in a);
assertFalse(2 in a);
-assertFalse('0' in a);
+assertFalse('0' in a);
assertTrue('1' in a);
assertFalse('2' in a);
assertTrue('toString' in a, "toString");
diff --git a/deps/v8/test/mjsunit/instanceof.js b/deps/v8/test/mjsunit/instanceof.js
index 01ea4268e6..050ef2d9d7 100644
--- a/deps/v8/test/mjsunit/instanceof.js
+++ b/deps/v8/test/mjsunit/instanceof.js
@@ -60,10 +60,10 @@ TestChains();
function TestExceptions() {
function F() { }
- var items = [ 1, new Number(42),
- true,
+ var items = [ 1, new Number(42),
+ true,
'string', new String('hest'),
- {}, [],
+ {}, [],
F, new F(),
Object, String ];
diff --git a/deps/v8/test/mjsunit/keyed-storage-extend.js b/deps/v8/test/mjsunit/keyed-storage-extend.js
index 04d2f0477a..d7e157b846 100644
--- a/deps/v8/test/mjsunit/keyed-storage-extend.js
+++ b/deps/v8/test/mjsunit/keyed-storage-extend.js
@@ -37,7 +37,7 @@ function GrowNamed(o) {
}
function GrowKeyed(o) {
- var names = ['a','b','c','d','e','f'];
+ var names = ['a','b','c','d','e','f'];
var i = 0;
o[names[i++]] = i;
o[names[i++]] = i;
diff --git a/deps/v8/test/mjsunit/mirror-array.js b/deps/v8/test/mjsunit/mirror-array.js
index eb8f72a8c9..92e3913f31 100644
--- a/deps/v8/test/mjsunit/mirror-array.js
+++ b/deps/v8/test/mjsunit/mirror-array.js
@@ -64,7 +64,7 @@ function testArrayMirror(a, names) {
assertTrue(mirror.protoObject() instanceof debug.Mirror, 'Unexpected mirror hierachy');
assertTrue(mirror.prototypeObject() instanceof debug.Mirror, 'Unexpected mirror hierachy');
assertEquals(mirror.length(), a.length, "Length mismatch");
-
+
var indexedProperties = mirror.indexedPropertiesFromRange();
assertEquals(indexedProperties.length, a.length);
for (var i = 0; i < indexedProperties.length; i++) {
@@ -110,7 +110,7 @@ function testArrayMirror(a, names) {
var found = false;
for (var j = 0; j < fromJSON.properties.length; j++) {
if (names[i] == fromJSON.properties[j].name) {
- found = true;
+ found = true;
}
}
assertTrue(found, names[i])
diff --git a/deps/v8/test/mjsunit/mirror-function.js b/deps/v8/test/mjsunit/mirror-function.js
index 58aee3dae8..cda815df68 100644
--- a/deps/v8/test/mjsunit/mirror-function.js
+++ b/deps/v8/test/mjsunit/mirror-function.js
@@ -65,7 +65,7 @@ function testFunctionMirror(f) {
assertTrue(mirror.constructorFunction() instanceof debug.ObjectMirror);
assertTrue(mirror.protoObject() instanceof debug.Mirror);
assertTrue(mirror.prototypeObject() instanceof debug.Mirror);
-
+
// Test text representation
assertEquals(f.toString(), mirror.toText());
diff --git a/deps/v8/test/mjsunit/mirror-script.js b/deps/v8/test/mjsunit/mirror-script.js
index 71561701a2..1d64ac26bf 100644
--- a/deps/v8/test/mjsunit/mirror-script.js
+++ b/deps/v8/test/mjsunit/mirror-script.js
@@ -62,7 +62,7 @@ function testScriptMirror(f, file_name, file_lines, type, compilation_type,
if (eval_from_line) {
assertEquals(eval_from_line, mirror.evalFromLocation().line);
}
-
+
// Parse JSON representation and check.
var fromJSON = JSON.parse(json);
assertEquals('script', fromJSON.type);
diff --git a/deps/v8/test/mjsunit/mirror-unresolved-function.js b/deps/v8/test/mjsunit/mirror-unresolved-function.js
index c1fe4a3ef0..46f22a08a7 100644
--- a/deps/v8/test/mjsunit/mirror-unresolved-function.js
+++ b/deps/v8/test/mjsunit/mirror-unresolved-function.js
@@ -64,7 +64,7 @@ assertEquals(void 0, mirror.source());
assertEquals('undefined', mirror.constructorFunction().type());
assertEquals('undefined', mirror.protoObject().type());
assertEquals('undefined', mirror.prototypeObject().type());
-
+
// Parse JSON representation of unresolved functions and check.
var fromJSON = eval('(' + json + ')');
assertEquals('function', fromJSON.type, 'Unexpected mirror type in JSON');
diff --git a/deps/v8/test/mjsunit/mjsunit.status b/deps/v8/test/mjsunit/mjsunit.status
index b7b0c774c4..027da584b4 100644
--- a/deps/v8/test/mjsunit/mjsunit.status
+++ b/deps/v8/test/mjsunit/mjsunit.status
@@ -115,6 +115,9 @@ regress/regress-1132: SKIP
##############################################################################
[ $arch == mips ]
+# Run those tests, but expect them to time out.
+array-sort: PASS || TIMEOUT
+mirror-object: PASS || TIMEOUT
# Skip long-running tests.
compiler/alloc-number: SKIP
@@ -141,8 +144,11 @@ regress/regress-634: SKIP
regress/regress-create-exception: SKIP
regress/regress-3218915: SKIP
regress/regress-3247124: SKIP
+regress/regress-1132: SKIP
+regress/regress-1257: SKIP
+regress/regress-91008: SKIP
-
+##############################################################################
[ $isolates ]
# d8-os writes temporary files that might interfer with each other when running
# in multible threads. Skip this if running with isolates testing.
diff --git a/deps/v8/test/mjsunit/no-semicolon.js b/deps/v8/test/mjsunit/no-semicolon.js
index fa6ccba89d..273ec4bccb 100644
--- a/deps/v8/test/mjsunit/no-semicolon.js
+++ b/deps/v8/test/mjsunit/no-semicolon.js
@@ -30,7 +30,7 @@
function f() { return }
-function g() {
+function g() {
return
4;
}
@@ -42,4 +42,4 @@ for (var i = 0; i < 10; i++) { break }
assertEquals(0, i);
for (var i = 0; i < 10; i++) { continue }
-assertEquals(10, i); \ No newline at end of file
+assertEquals(10, i);
diff --git a/deps/v8/test/mjsunit/object-define-properties.js b/deps/v8/test/mjsunit/object-define-properties.js
index 6b3725b392..128df694d3 100644
--- a/deps/v8/test/mjsunit/object-define-properties.js
+++ b/deps/v8/test/mjsunit/object-define-properties.js
@@ -26,7 +26,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Tests the Object.defineProperties method - ES 15.2.3.7
-// Note that the internal DefineOwnProperty method is tested through
+// Note that the internal DefineOwnProperty method is tested through
// object-define-property.js, this file only contains tests specific for
// Object.defineProperties. Also note that object-create.js contains
// a range of indirect tests on this method since Object.create uses
diff --git a/deps/v8/test/mjsunit/object-literal-conversions.js b/deps/v8/test/mjsunit/object-literal-conversions.js
index 8540d93082..742f814ba3 100644
--- a/deps/v8/test/mjsunit/object-literal-conversions.js
+++ b/deps/v8/test/mjsunit/object-literal-conversions.js
@@ -43,4 +43,4 @@ var test6 = { 17.31: function() {}, "17.31": 7 };
assertEquals(7, test5[13]);
assertEquals(7, test6[17.31]);
- \ No newline at end of file
+
diff --git a/deps/v8/test/mjsunit/object-literal-overwrite.js b/deps/v8/test/mjsunit/object-literal-overwrite.js
index 5c58a2ddb6..5a3584df8a 100644
--- a/deps/v8/test/mjsunit/object-literal-overwrite.js
+++ b/deps/v8/test/mjsunit/object-literal-overwrite.js
@@ -79,7 +79,7 @@ assertEquals(7, foo7[15]);
// Test for the classic code generator.
function fun(x) {
- var inner = { j: function(x) { return x; }, j: 7 };
+ var inner = { j: function(x) { return x; }, j: 7 };
return inner.j;
}
@@ -115,4 +115,4 @@ function fun3() {
var y = fun3();
assertEquals(7, y);
-assertEquals(3, glob3); \ No newline at end of file
+assertEquals(3, glob3);
diff --git a/deps/v8/test/mjsunit/object-prevent-extensions.js b/deps/v8/test/mjsunit/object-prevent-extensions.js
index dc32342c0e..322a2cb543 100644
--- a/deps/v8/test/mjsunit/object-prevent-extensions.js
+++ b/deps/v8/test/mjsunit/object-prevent-extensions.js
@@ -33,7 +33,7 @@ var obj1 = {};
assertTrue(Object.isExtensible(obj1));
Object.preventExtensions(obj1);
-// Make sure the is_extensible flag is set.
+// Make sure the is_extensible flag is set.
assertFalse(Object.isExtensible(obj1));
obj1.x = 42;
assertEquals(undefined, obj1.x);
diff --git a/deps/v8/test/mjsunit/parse-int-float.js b/deps/v8/test/mjsunit/parse-int-float.js
index a4f09df9b4..2e4f648437 100644
--- a/deps/v8/test/mjsunit/parse-int-float.js
+++ b/deps/v8/test/mjsunit/parse-int-float.js
@@ -100,4 +100,17 @@ assertTrue(isNaN(parseFloat(0/0)));
assertEquals(Infinity, parseFloat(1/0), "parseFloat Infinity");
assertEquals(-Infinity, parseFloat(-1/0), "parseFloat -Infinity");
+var state;
+var throwingRadix = { valueOf: function() { state = "throwingRadix"; throw null; } };
+var throwingString = { toString: function() { state = "throwingString"; throw null; } };
+state = null;
+try { parseInt('123', throwingRadix); } catch (e) {}
+assertEquals(state, "throwingRadix");
+state = null;
+try { parseInt(throwingString, 10); } catch (e) {}
+assertEquals(state, "throwingString");
+
+state = null;
+try { parseInt(throwingString, throwingRadix); } catch (e) {}
+assertEquals(state, "throwingString");
diff --git a/deps/v8/test/mjsunit/regress/regress-1081309.js b/deps/v8/test/mjsunit/regress/regress-1081309.js
index 009ede1516..5a6c52412e 100644
--- a/deps/v8/test/mjsunit/regress/regress-1081309.js
+++ b/deps/v8/test/mjsunit/regress/regress-1081309.js
@@ -67,7 +67,7 @@ function listener(event, exec_state, event_data, data) {
// The expected backtrace is
// 1: g
// 0: [anonymous]
-
+
// Get the debug command processor.
var dcp = exec_state.debugCommandProcessor(false);
diff --git a/deps/v8/test/mjsunit/regress/regress-1092.js b/deps/v8/test/mjsunit/regress/regress-1092.js
index 0b29231a4b..00422cb452 100644
--- a/deps/v8/test/mjsunit/regress/regress-1092.js
+++ b/deps/v8/test/mjsunit/regress/regress-1092.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Test that CodeGenerator::EmitKeyedPropertyAssignment for the start
+// Test that CodeGenerator::EmitKeyedPropertyAssignment for the start
// of an initialization block doesn't normalize the properties of the
// JSGlobalProxy.
this.w = 0;
diff --git a/deps/v8/test/mjsunit/regress/regress-1110.js b/deps/v8/test/mjsunit/regress/regress-1110.js
index 204a87ba3d..43b8d77aeb 100644
--- a/deps/v8/test/mjsunit/regress/regress-1110.js
+++ b/deps/v8/test/mjsunit/regress/regress-1110.js
@@ -29,7 +29,7 @@
try {
function Crash() { continue;if (Crash) {
- } }
+ } }
Crash();
assertTrue(false);
} catch (e) {
diff --git a/deps/v8/test/mjsunit/regress/regress-1213575.js b/deps/v8/test/mjsunit/regress/regress-1213575.js
index 0c3dcc28c6..9d82064e47 100644
--- a/deps/v8/test/mjsunit/regress/regress-1213575.js
+++ b/deps/v8/test/mjsunit/regress/regress-1213575.js
@@ -33,7 +33,7 @@ this.__defineSetter__('x', function(value) { assertTrue(false); });
var caught = false;
try {
- eval('const x');
+ eval('const x');
} catch(e) {
assertTrue(e instanceof TypeError);
caught = true;
diff --git a/deps/v8/test/mjsunit/regress/regress-1215.js b/deps/v8/test/mjsunit/regress/regress-1215.js
new file mode 100644
index 0000000000..93a89f6a3f
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1215.js
@@ -0,0 +1,36 @@
+// Copyright 2011 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.
+
+// Make sure that the "message" property on Error.prototype
+// has the following descriptor:
+// {writable: true, enumerable: false, and configurable: true}
+
+var desc = Object.getOwnPropertyDescriptor(Error.prototype, 'message');
+
+assertEquals(desc.writable, true);
+assertEquals(desc.enumerable, false);
+assertEquals(desc.configurable, true);
diff --git a/deps/v8/test/mjsunit/regress/regress-1447.js b/deps/v8/test/mjsunit/regress/regress-1447.js
index 3c64929d1d..2c1ee5917d 100644
--- a/deps/v8/test/mjsunit/regress/regress-1447.js
+++ b/deps/v8/test/mjsunit/regress/regress-1447.js
@@ -27,3 +27,11 @@
[0].forEach(function(){ Object.freeze(Array.prototype.forEach); });
[0].every(function(){ Object.seal(Array.prototype.every); });
+
+function testStrict(){
+ "use strict";
+ [0].forEach(function(){ Object.freeze(Array.prototype.forEach); });
+ [0].every(function(){ Object.seal(Array.prototype.every); });
+}
+
+testStrict();
diff --git a/deps/v8/test/mjsunit/regress/regress-1548.js b/deps/v8/test/mjsunit/regress/regress-1548.js
new file mode 100644
index 0000000000..074007b916
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1548.js
@@ -0,0 +1,48 @@
+// Copyright 2011 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.
+
+// Test that the caller and arguments objects are not available on native
+// functions.
+
+function testfn(f) { return [1].map(f)[0]; }
+function foo() { return [].map.caller; }
+assertEquals(null, testfn(foo));
+
+// Try to delete the caller property (to make sure that we can't get to the
+// caller accessor on the prototype.
+delete Array.prototype.map.caller;
+assertEquals(null, testfn(foo));
+
+// Redo tests with arguments object.
+function testarguments(f) { return [1].map(f)[0]; }
+function bar() { return [].map.arguments; }
+assertEquals(null, testfn(bar));
+
+// Try to delete the arguments property (to make sure that we can't get to the
+// caller accessor on the prototype.
+delete Array.prototype.map.arguments;
+assertEquals(null, testarguments(bar));
diff --git a/deps/v8/test/mjsunit/regress/regress-1647.js b/deps/v8/test/mjsunit/regress/regress-1647.js
new file mode 100644
index 0000000000..a6afcc0be2
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1647.js
@@ -0,0 +1,43 @@
+// Copyright 2011 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.
+
+// Flags: --allow-natives-syntax
+
+// Test for correct deoptimization in named function expressions.
+
+var t = { foo: function() {} };
+
+var f = (function bar() {
+ t.foo();
+ assertEquals("function", typeof bar);
+});
+
+for (var i = 0; i < 10; i++) f();
+%OptimizeFunctionOnNextCall(f);
+t.number = 2;
+f();
+
diff --git a/deps/v8/test/mjsunit/regress/regress-1650.js b/deps/v8/test/mjsunit/regress/regress-1650.js
new file mode 100644
index 0000000000..fb6a17814d
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1650.js
@@ -0,0 +1,60 @@
+// Copyright 2011 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.
+
+// Flags: --allow-natives-syntax
+
+function g(f) { return f.call.apply(f.bind, arguments); }
+
+var x = new Object;
+
+function t() { }
+
+g(t, x);
+g(t, x);
+g(t, x);
+%OptimizeFunctionOnNextCall(g);
+
+function Fake() {}
+
+var fakeCallInvoked = false;
+
+Fake.prototype.call = function () {
+ assertSame(Fake.prototype.bind, this);
+ assertEquals(2, arguments.length);
+ assertSame(fake, arguments[0]);
+ assertSame(x, arguments[1]);
+ fakeCallInvoked = true;
+};
+
+Fake.prototype.bind = function () {
+};
+
+var fake = new Fake;
+
+g(fake, x);
+
+assertTrue(fakeCallInvoked);
diff --git a/deps/v8/test/mjsunit/regress/regress-1919169.js b/deps/v8/test/mjsunit/regress/regress-1919169.js
index 774f26558d..a73231289f 100644
--- a/deps/v8/test/mjsunit/regress/regress-1919169.js
+++ b/deps/v8/test/mjsunit/regress/regress-1919169.js
@@ -30,7 +30,7 @@ function test() {
var s2 = "s2";
for (var i = 0; i < 2; i++) {
// Crashes in round i==1 with IllegalAccess in %StringAdd(x,y)
- var res = 1 + s2;
+ var res = 1 + s2;
s2 = 2;
}
}
diff --git a/deps/v8/test/mjsunit/regress/regress-20070207.js b/deps/v8/test/mjsunit/regress/regress-20070207.js
index e90b2ec589..b7f7a5cc6f 100644
--- a/deps/v8/test/mjsunit/regress/regress-20070207.js
+++ b/deps/v8/test/mjsunit/regress/regress-20070207.js
@@ -26,7 +26,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// The following regression test illustrates a problem in using the
-// value of setting a property in the arguments object.
+// value of setting a property in the arguments object.
function f(s) {
arguments.length;
diff --git a/deps/v8/test/mjsunit/regress/regress-269.js b/deps/v8/test/mjsunit/regress/regress-269.js
index 49b24c0b43..ce165e0abf 100644
--- a/deps/v8/test/mjsunit/regress/regress-269.js
+++ b/deps/v8/test/mjsunit/regress/regress-269.js
@@ -40,10 +40,10 @@ Debug.setListener(listener);
function g() {
}
-
+
function f() {
debugger;
g.apply(null, ['']);
}
-f() \ No newline at end of file
+f()
diff --git a/deps/v8/test/mjsunit/regress/regress-619.js b/deps/v8/test/mjsunit/regress/regress-619.js
index 24bdbc1879..4d3e66b298 100644
--- a/deps/v8/test/mjsunit/regress/regress-619.js
+++ b/deps/v8/test/mjsunit/regress/regress-619.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Tests that Object.defineProperty works correctly on array indices.
+// Tests that Object.defineProperty works correctly on array indices.
// Please see http://code.google.com/p/v8/issues/detail?id=619 for details.
var obj = {};
diff --git a/deps/v8/test/mjsunit/regress/regress-678525.js b/deps/v8/test/mjsunit/regress/regress-678525.js
index 5ff9c3d9e4..11eaf74fc8 100644
--- a/deps/v8/test/mjsunit/regress/regress-678525.js
+++ b/deps/v8/test/mjsunit/regress/regress-678525.js
@@ -36,16 +36,16 @@ assertEquals(7, '\7'.charCodeAt(0));
assertEquals(56, '\8'.charCodeAt(0));
assertEquals('\010', '\10');
-assertEquals('\011', '\11');
+assertEquals('\011', '\11');
assertEquals('\012', '\12');
assertEquals('\013', '\13');
assertEquals('\014', '\14');
assertEquals('\015', '\15');
assertEquals('\016', '\16');
assertEquals('\017', '\17');
-
+
assertEquals('\020', '\20');
-assertEquals('\021', '\21');
+assertEquals('\021', '\21');
assertEquals('\022', '\22');
assertEquals('\023', '\23');
assertEquals('\024', '\24');
@@ -56,4 +56,4 @@ assertEquals('\027', '\27');
assertEquals(73, '\111'.charCodeAt(0));
assertEquals(105, '\151'.charCodeAt(0));
-
+
diff --git a/deps/v8/test/mjsunit/regress/regress-696.js b/deps/v8/test/mjsunit/regress/regress-696.js
index 21977e1c82..e443c4243d 100644
--- a/deps/v8/test/mjsunit/regress/regress-696.js
+++ b/deps/v8/test/mjsunit/regress/regress-696.js
@@ -28,7 +28,7 @@
// See: http://code.google.com/p/v8/issues/detail?id=696
// Because of the change in dateparser in revision 4557 to support time
// only strings in Date.parse we also misleadingly supported strings with non
-// leading numbers.
+// leading numbers.
assertTrue(isNaN(Date.parse('x')));
assertTrue(isNaN(Date.parse('1x')));
diff --git a/deps/v8/test/mjsunit/regress/regress-720.js b/deps/v8/test/mjsunit/regress/regress-720.js
index 97e1284e09..267b32d088 100644
--- a/deps/v8/test/mjsunit/regress/regress-720.js
+++ b/deps/v8/test/mjsunit/regress/regress-720.js
@@ -27,7 +27,7 @@
// This regression test is used to ensure that Object.defineProperty
// keeps the existing value of the writable flag if none is given
-// in the provided descriptor.
+// in the provided descriptor.
// See: http://code.google.com/p/v8/issues/detail?id=720
var o = {x: 10};
diff --git a/deps/v8/test/mjsunit/regress/regress-747.js b/deps/v8/test/mjsunit/regress/regress-747.js
index 6fcc0000a6..648c36684c 100644
--- a/deps/v8/test/mjsunit/regress/regress-747.js
+++ b/deps/v8/test/mjsunit/regress/regress-747.js
@@ -40,7 +40,7 @@ try {
callEval();
} catch (e) {
assertUnreachable();
-}
+}
gc();
gc();
@@ -53,4 +53,4 @@ try {
callEval();
} catch (e) {
assertUnreachable();
-}
+}
diff --git a/deps/v8/test/mjsunit/regress/regress-760-1.js b/deps/v8/test/mjsunit/regress/regress-760-1.js
index 2e0cee5f8f..081c99309d 100644
--- a/deps/v8/test/mjsunit/regress/regress-760-1.js
+++ b/deps/v8/test/mjsunit/regress/regress-760-1.js
@@ -26,7 +26,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Check that when valueOf for a String object is overwritten it is called and
-// the result used when that object is added with a string.
+// the result used when that object is added with a string.
// See: http://code.google.com/p/v8/issues/detail?id=760
diff --git a/deps/v8/test/mjsunit/regress/regress-760-2.js b/deps/v8/test/mjsunit/regress/regress-760-2.js
index 1b1cbfebed..549ed4ee41 100644
--- a/deps/v8/test/mjsunit/regress/regress-760-2.js
+++ b/deps/v8/test/mjsunit/regress/regress-760-2.js
@@ -26,7 +26,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Check that when valueOf for a String object is overwritten it is called and
-// the result used when that object is added with a string.
+// the result used when that object is added with a string.
// See: http://code.google.com/p/v8/issues/detail?id=760
diff --git a/deps/v8/test/mjsunit/regress/regress-798.js b/deps/v8/test/mjsunit/regress/regress-798.js
index ffee5da915..182eb4da77 100644
--- a/deps/v8/test/mjsunit/regress/regress-798.js
+++ b/deps/v8/test/mjsunit/regress/regress-798.js
@@ -32,7 +32,7 @@ x.__defineGetter__("a", function() {
try {
y.x = 40;
} catch (e) {
- assertEquals(3, e.stack.split('\n').length);
+ assertEquals(3, e.stack.split('\n').length);
}
return 40;
});
@@ -41,7 +41,7 @@ x.__defineSetter__("a", function(val) {
try {
y.x = 40;
} catch(e) {
- assertEquals(3, e.stack.split('\n').length);
+ assertEquals(3, e.stack.split('\n').length);
}
});
@@ -50,7 +50,7 @@ function getB() {
try {
y.x = 30;
} catch (e) {
- assertEquals(3, e.stack.split('\n').length);
+ assertEquals(3, e.stack.split('\n').length);
}
return 30;
}
@@ -59,7 +59,7 @@ function setB(val) {
try {
y.x = 30;
} catch(e) {
- assertEquals(3, e.stack.split('\n').length);
+ assertEquals(3, e.stack.split('\n').length);
}
}
@@ -72,7 +72,7 @@ var descriptor = {
try {
y.x = 40;
} catch (e) {
- assertEquals(3, e.stack.split('\n').length);
+ assertEquals(3, e.stack.split('\n').length);
}
return 40;
},
@@ -80,7 +80,7 @@ var descriptor = {
try {
y.x = 40;
} catch(e) {
- assertEquals(3, e.stack.split('\n').length);
+ assertEquals(3, e.stack.split('\n').length);
}
}
}
@@ -88,7 +88,7 @@ var descriptor = {
Object.defineProperty(x, 'c', descriptor)
// Check that the stack for an exception in a getter and setter produce the
-// expected stack height.
+// expected stack height.
x.a;
x.b;
x.c;
diff --git a/deps/v8/test/mjsunit/regress/regress-918.js b/deps/v8/test/mjsunit/regress/regress-918.js
index 4b6ddbacf8..871e9d9f3d 100644
--- a/deps/v8/test/mjsunit/regress/regress-918.js
+++ b/deps/v8/test/mjsunit/regress/regress-918.js
@@ -28,6 +28,6 @@
// Parser should not accept parentheses around labels.
// See http://code.google.com/p/v8/issues/detail?id=918
-// The label was parsed as an expression and then tested for being a
+// The label was parsed as an expression and then tested for being a
// single identifier. This threw away the parentheses.
assertThrows("(label):42;");
diff --git a/deps/v8/test/mjsunit/regress/regress-925537.js b/deps/v8/test/mjsunit/regress/regress-925537.js
index 11582eaf90..d50c5689a5 100644
--- a/deps/v8/test/mjsunit/regress/regress-925537.js
+++ b/deps/v8/test/mjsunit/regress/regress-925537.js
@@ -28,8 +28,8 @@
function assertClose(expected, actual) {
var delta = 0.00001;
if (Math.abs(expected - actual) > delta) {
- print('Failure: Expected <' + actual + '> to be close to <' +
- expected + '>');
+ print('Failure: Expected <' + actual + '> to be close to <' +
+ expected + '>');
}
}
diff --git a/deps/v8/test/mjsunit/regress/regress-937896.js b/deps/v8/test/mjsunit/regress/regress-937896.js
index e8e5ef21b7..e7831da3c8 100644
--- a/deps/v8/test/mjsunit/regress/regress-937896.js
+++ b/deps/v8/test/mjsunit/regress/regress-937896.js
@@ -41,7 +41,7 @@ function f() {
}
}
} catch (e) {
- // Empty.
+ // Empty.
}
return 42;
}
diff --git a/deps/v8/test/mjsunit/regress/regress-94425.js b/deps/v8/test/mjsunit/regress/regress-94425.js
new file mode 100644
index 0000000000..4a48f4ad5c
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-94425.js
@@ -0,0 +1,46 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * 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.
+
+// Flags: --expose-gc
+
+var N = 2040 - 2 + 10;
+var arr = new Array(N);
+
+gc();
+gc();
+gc();
+
+// arr is in the large object space now.
+// Write new space object into it.
+arr[arr.length - 2] = new Object;
+
+// Shift array multiple times to ensure that young
+// object crosses region boundary.
+for (var i = 0; i < 9; i++) arr.shift();
+
+// Do a GC to verify region dirty marks.
+gc();
diff --git a/deps/v8/test/mjsunit/regress/regress-95113.js b/deps/v8/test/mjsunit/regress/regress-95113.js
new file mode 100644
index 0000000000..f01b27004c
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-95113.js
@@ -0,0 +1,48 @@
+// Copyright 2011 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.
+
+// Flags: --allow-natives-syntax
+
+function get_double_array() {
+ var a = new Array(100000);
+ var i = 0;
+ while (!%HasFastDoubleElements(a)) {
+ a[i] = i;
+ i++;
+ }
+ assertTrue(%HasFastDoubleElements(a));
+ a.length = 1;
+ a[0] = 1.5;
+ a.length = 2;
+ a[1] = 2.5;
+ assertEquals(a[0], 1.5);
+ assertEquals(a[1], 2.5);
+ assertTrue(%HasFastDoubleElements(a));
+ return a;
+}
+
+var a = get_double_array();
diff --git a/deps/v8/test/mjsunit/regress/regress-95485.js b/deps/v8/test/mjsunit/regress/regress-95485.js
new file mode 100644
index 0000000000..2510072e0b
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-95485.js
@@ -0,0 +1,42 @@
+// Copyright 2011 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.
+
+function Test() {
+ var left = 'XXX';
+ var right = 'YYY';
+ for (var i = 0; i < 3; i++) {
+ var cons = left + right;
+ var substring = cons.substring(2, 4);
+ try {
+ with ({Test: i})
+ continue;
+ } finally { }
+ }
+ return substring;
+}
+
+assertEquals('XY', Test());
diff --git a/deps/v8/test/mjsunit/regress/regress-fundecl.js b/deps/v8/test/mjsunit/regress/regress-fundecl.js
new file mode 100644
index 0000000000..fddb5895eb
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-fundecl.js
@@ -0,0 +1,44 @@
+// Copyright 2011 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.
+
+// Flags: --allow-natives-syntax
+
+// Test hoisting of function declarations in the optimizing
+// compiler in case of deoptimization.
+
+function h(a, b) {
+ var r = a + b;
+ function X() { return 42; }
+ return r + X();
+}
+
+for (var i = 0; i < 5; i++) h(1,2);
+
+%OptimizeFunctionOnNextCall(h);
+
+assertEquals(45, h(1,2));
+assertEquals("foo742", h("foo", 7));
diff --git a/deps/v8/test/mjsunit/setter-on-constructor-prototype.js b/deps/v8/test/mjsunit/setter-on-constructor-prototype.js
index d5718f9c9b..a74f7da7b3 100644
--- a/deps/v8/test/mjsunit/setter-on-constructor-prototype.js
+++ b/deps/v8/test/mjsunit/setter-on-constructor-prototype.js
@@ -35,14 +35,14 @@ function RunTest(ensure_fast_case) {
if (ensure_fast_case) {
%ToFastProperties(C1.prototype);
}
-
+
for (var i = 0; i < 10; i++) {
var c1 = new C1();
assertEquals("undefined", typeof c1.x);
assertEquals(23, c1.y);
}
-
-
+
+
function C2() {
this.x = 23;
};
@@ -51,14 +51,14 @@ function RunTest(ensure_fast_case) {
if (ensure_fast_case) {
%ToFastProperties(C2.prototype.__proto__)
}
-
+
for (var i = 0; i < 10; i++) {
var c2 = new C2();
assertEquals("undefined", typeof c2.x);
assertEquals(23, c2.y);
}
-
-
+
+
function C3() {
this.x = 23;
};
@@ -67,14 +67,14 @@ function RunTest(ensure_fast_case) {
if (ensure_fast_case) {
%ToFastProperties(C3.prototype);
}
-
+
for (var i = 0; i < 10; i++) {
var c3 = new C3();
assertEquals("undefined", typeof c3.x);
assertEquals(23, c3.y);
}
-
-
+
+
function C4() {
this.x = 23;
};
@@ -84,14 +84,14 @@ function RunTest(ensure_fast_case) {
if (ensure_fast_case) {
%ToFastProperties(C4.prototype.__proto__);
}
-
+
for (var i = 0; i < 10; i++) {
var c4 = new C4();
assertEquals("undefined", typeof c4.x);
assertEquals(23, c4.y);
}
-
-
+
+
function D() {
this.x = 23;
};
@@ -99,7 +99,7 @@ function RunTest(ensure_fast_case) {
if (ensure_fast_case) {
%ToFastProperties(D.prototype);
}
-
+
for (var i = 0; i < 10; i++) {
var d = new D();
assertEquals(23, d.x);
diff --git a/deps/v8/test/mjsunit/string-compare-alignment.js b/deps/v8/test/mjsunit/string-compare-alignment.js
index a291417ba5..0ae8eb7910 100644
--- a/deps/v8/test/mjsunit/string-compare-alignment.js
+++ b/deps/v8/test/mjsunit/string-compare-alignment.js
@@ -29,8 +29,9 @@
// This situation can arise with sliced strings. This tests for an ARM bug
// that was fixed in r554.
-var base = "Now is the time for all good men to come to the aid of the party. " +
- "Now is the time for all good men to come to the aid of the party."
+var base =
+ "Now is the time for all good men to come to the aid of the party. " +
+ "Now is the time for all good men to come to the aid of the party."
var s1 = base.substring(0, 64);
var s2 = base.substring(66, 130);
diff --git a/deps/v8/test/mjsunit/string-indexof-1.js b/deps/v8/test/mjsunit/string-indexof-1.js
index c5ae4b898a..db3623f7c0 100644
--- a/deps/v8/test/mjsunit/string-indexof-1.js
+++ b/deps/v8/test/mjsunit/string-indexof-1.js
@@ -63,7 +63,7 @@ assertEquals(1, twoByteString.indexOf("\u0391"), "Alpha");
assertEquals(2, twoByteString.indexOf("\u03a3"), "First Sigma");
assertEquals(3, twoByteString.indexOf("\u03a3",3), "Second Sigma");
assertEquals(4, twoByteString.indexOf("\u0395"), "Epsilon");
-assertEquals(-1, twoByteString.indexOf("\u0392"), "Not beta");
+assertEquals(-1, twoByteString.indexOf("\u0392"), "Not beta");
// Test multi-char pattern
assertEquals(0, twoByteString.indexOf("\u039a\u0391"), "lambda Alpha");
@@ -71,7 +71,7 @@ assertEquals(1, twoByteString.indexOf("\u0391\u03a3"), "Alpha Sigma");
assertEquals(2, twoByteString.indexOf("\u03a3\u03a3"), "Sigma Sigma");
assertEquals(3, twoByteString.indexOf("\u03a3\u0395"), "Sigma Epsilon");
-assertEquals(-1, twoByteString.indexOf("\u0391\u03a3\u0395"),
+assertEquals(-1, twoByteString.indexOf("\u0391\u03a3\u0395"),
"Not Alpha Sigma Epsilon");
//single char pattern
diff --git a/deps/v8/test/mjsunit/string-indexof-2.js b/deps/v8/test/mjsunit/string-indexof-2.js
index a7c3f600a1..48db84d26e 100644
--- a/deps/v8/test/mjsunit/string-indexof-2.js
+++ b/deps/v8/test/mjsunit/string-indexof-2.js
@@ -57,10 +57,10 @@ for(var i = 0; i < lipsum.length; i += 3) {
var index = -1;
do {
index = lipsum.indexOf(substring, index + 1);
- assertTrue(index != -1,
+ assertTrue(index != -1,
"Lipsum substring " + i + ".." + (i + len-1) + " not found");
- assertEquals(lipsum.substring(index, index + len), substring,
- "Wrong lipsum substring found: " + i + ".." + (i + len - 1) + "/" +
+ assertEquals(lipsum.substring(index, index + len), substring,
+ "Wrong lipsum substring found: " + i + ".." + (i + len - 1) + "/" +
index + ".." + (index + len - 1));
} while (index >= 0 && index < i);
assertEquals(i, index, "Lipsum match at " + i + ".." + (i + len - 1));
diff --git a/deps/v8/test/mjsunit/string-slices.js b/deps/v8/test/mjsunit/string-slices.js
index b0b05eca36..8cc1f81e77 100755
--- a/deps/v8/test/mjsunit/string-slices.js
+++ b/deps/v8/test/mjsunit/string-slices.js
@@ -57,7 +57,7 @@ assertEquals(s, s.substr(-100));
assertEquals('abc', s.substr(-100, 3));
assertEquals(s1, s.substr(-s.length + 1));
-// assertEquals('', s.substr(0, void 0)); // smjs and rhino
+// assertEquals('', s.substr(0, void 0)); // smjs and rhino
assertEquals('abcdefghijklmn', s.substr(0, void 0)); // kjs and v8
assertEquals('', s.substr(0, null));
assertEquals(s, s.substr(0, String(s.length)));
@@ -72,7 +72,7 @@ for (var i = 0; i < 25; i++) {
}
/x/.exec(x); // Try to force a flatten.
for (var i = 5; i < 25; i++) {
- for (var j = 12; j < 25; j++) {
+ for (var j = 0; j < 25; j++) {
var z = x.substring(i, i+j);
var w = Math.random() * 42; // Allocate something new in new-space.
assertEquals(j, z.length);
@@ -110,7 +110,7 @@ x += x;
x += x;
var xl = x.length;
var cache = [];
-for (var i = 0; i < 10000; i++) {
+for (var i = 0; i < 1000; i++) {
var z = x.substring(i % xl);
assertEquals(xl - (i % xl), z.length);
cache.push(z);
@@ -129,7 +129,7 @@ x += x;
x += x;
var xl = x.length;
var cache = [];
-for (var i = 0; i < 10000; i++) {
+for (var i = 0; i < 1000; i++) {
var z = x.substring(i % xl);
assertEquals(xl - (i % xl), z.length);
cache.push(z);
@@ -149,6 +149,7 @@ for (var i = 63; i >= 0; i--) {
var z = cache.pop();
assertTrue(/\u2028123456789ABCDEF/.test(z));
assertEquals(xl - offset, z.length);
+ assertEquals(x.charAt(i*(i+1)/2), z.charAt(0));
offset -= i;
}
@@ -195,4 +196,4 @@ var b = a.slice(1,-1);
assertEquals(a.slice(1,-1), b);
externalizeString(a);
assertEquals(a.slice(1,-1), b);
-*/ \ No newline at end of file
+*/
diff --git a/deps/v8/test/mjsunit/string-split.js b/deps/v8/test/mjsunit/string-split.js
index bc50945135..d8412f0eed 100644
--- a/deps/v8/test/mjsunit/string-split.js
+++ b/deps/v8/test/mjsunit/string-split.js
@@ -68,13 +68,13 @@ assertArrayEquals(["a", "b", "c"], "abc".split(/(?=.)/));
/* "ab".split(/((?=.))/)
- *
+ *
* KJS: ,a,,b
* SM: a,,b,
* IE: a,b
* Opera: a,,b
* V8: a,,b
- *
+ *
* Opera seems to have this right. The others make no sense.
*/
assertArrayEquals(["a", "", "b"], "ab".split(/((?=.))/));
diff --git a/deps/v8/test/mjsunit/substr.js b/deps/v8/test/mjsunit/substr.js
index cffaf94da2..cab8b1bf6d 100755
--- a/deps/v8/test/mjsunit/substr.js
+++ b/deps/v8/test/mjsunit/substr.js
@@ -55,7 +55,7 @@ assertEquals(s, s.substr(-100));
assertEquals('abc', s.substr(-100, 3));
assertEquals(s1, s.substr(-s.length + 1));
-// assertEquals('', s.substr(0, void 0)); // smjs and rhino
+// assertEquals('', s.substr(0, void 0)); // smjs and rhino
assertEquals('abcdefghijklmn', s.substr(0, void 0)); // kjs and v8
assertEquals('', s.substr(0, null));
assertEquals(s, s.substr(0, String(s.length)));
diff --git a/deps/v8/test/mjsunit/this-property-assignment.js b/deps/v8/test/mjsunit/this-property-assignment.js
index c6819996c0..54c6537256 100644
--- a/deps/v8/test/mjsunit/this-property-assignment.js
+++ b/deps/v8/test/mjsunit/this-property-assignment.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Tests the handling of multiple assignments to the same property in a
+// Tests the handling of multiple assignments to the same property in a
// constructor that only has simple this property assignments.
function Node() {
diff --git a/deps/v8/test/mjsunit/try.js b/deps/v8/test/mjsunit/try.js
index 794860a7c6..86afdf7f08 100644
--- a/deps/v8/test/mjsunit/try.js
+++ b/deps/v8/test/mjsunit/try.js
@@ -250,7 +250,7 @@ function break_from_nested_catch(x) {
} catch (o) {
x--;
}
- }
+ }
return x;
}
@@ -274,7 +274,7 @@ function break_from_nested_finally(x) {
x--;
}
x--; // should not happen
- }
+ }
return x;
}
diff --git a/deps/v8/test/mjsunit/unicode-test.js b/deps/v8/test/mjsunit/unicode-test.js
index 59a684e053..66a029a7ef 100644
--- a/deps/v8/test/mjsunit/unicode-test.js
+++ b/deps/v8/test/mjsunit/unicode-test.js
@@ -807,7 +807,7 @@ var cyrillic =
" * Васильев Л.С. Древний Китай: в 3 т. Т. 3. Период Чжаньго (V–III вв. до н.э.). М.: Восточная литература, 2006. ISBN 502018103X\n" +
" * Непомнин О.Е. История Китая: Эпоха Цин. XVII – начало XX века. М.: Восточная литература, 2005. ISBN 5020184004\n";
-var devanagari =
+var devanagari =
"भारत\n" +
"विकिपीडिया, एक मुक्त ज्ञानकोष से\n" +
"Jump to: navigation, search\n" +
@@ -1417,7 +1417,7 @@ var english =
"There are many words of French origin in English, such as competition, art, table, publicity, police, role, routine, machine, force, and many others that have been and are being anglicised; they are now pronounced according to English rules of phonology, rather than French. A large portion of English vocabulary is of French or Oïl language origin, most derived from, or transmitted via, the Anglo-Norman spoken by the upper classes in England for several hundred years after the Norman Conquest.\n";
-var greek =
+var greek =
"Ελλάδα\n" +
"Από τη Βικιπαίδεια, την ελεύθερη εγκυκλοπαίδεια\n" +
"Ελληνική Δημοκρατία\n" +
diff --git a/deps/v8/test/mjsunit/value-wrapper.js b/deps/v8/test/mjsunit/value-wrapper.js
index 88330b4497..76e200f36e 100644
--- a/deps/v8/test/mjsunit/value-wrapper.js
+++ b/deps/v8/test/mjsunit/value-wrapper.js
@@ -39,7 +39,7 @@ function RunTests() {
assertEquals('object', (42).TypeOfThis());
assertEquals('object', (3.14).TypeOfThis());
}
-
+
for (var i = 0; i < 10; i++) {
assertEquals('object', 'xxx'['TypeOfThis']());
assertEquals('object', true['TypeOfThis']());
@@ -47,11 +47,11 @@ function RunTests() {
assertEquals('object', (42)['TypeOfThis']());
assertEquals('object', (3.14)['TypeOfThis']());
}
-
+
function CallTypeOfThis(obj) {
assertEquals('object', obj.TypeOfThis());
}
-
+
for (var i = 0; i < 10; i++) {
CallTypeOfThis('xxx');
CallTypeOfThis(true);
@@ -59,7 +59,7 @@ function RunTests() {
CallTypeOfThis(42);
CallTypeOfThis(3.14);
}
-
+
function TestWithWith(obj) {
with (obj) {
for (var i = 0; i < 10; i++) {
@@ -67,13 +67,13 @@ function RunTests() {
}
}
}
-
+
TestWithWith('xxx');
TestWithWith(true);
TestWithWith(false);
TestWithWith(42);
TestWithWith(3.14);
-
+
for (var i = 0; i < 10; i++) {
assertEquals('object', true[7]());
assertEquals('object', false[7]());
@@ -100,7 +100,7 @@ function RunTests() {
function TypeOfThis() { return typeof this; }
-// Test with normal setup of prototype.
+// Test with normal setup of prototype.
String.prototype.TypeOfThis = TypeOfThis;
Boolean.prototype.TypeOfThis = TypeOfThis;
Number.prototype.TypeOfThis = TypeOfThis;
diff --git a/deps/v8/test/mozilla/mozilla.status b/deps/v8/test/mozilla/mozilla.status
index f6d69257c6..3a27130990 100644
--- a/deps/v8/test/mozilla/mozilla.status
+++ b/deps/v8/test/mozilla/mozilla.status
@@ -201,6 +201,10 @@ js1_5/extensions/regress-363258: PASS || FAIL
ecma_3/RegExp/regress-85721: PASS || FAIL if $mode == debug
+# Test that assumes specific execution time, flaky in debug mode.
+js1_5/Array/regress-101964: PASS || FAIL if $mode == debug
+
+
##################### INCOMPATIBLE TESTS #####################
# This section is for tests that fail in both V8 and JSC. Thus they
@@ -245,7 +249,7 @@ ecma_3/Number/15.7.4.7-1: FAIL_OK
# toExponential argument restricted to range 0..20 in JSC/V8
ecma_3/Number/15.7.4.6-1: FAIL_OK
-#:=== RegExp:===
+#:=== RegExp:===
# We don't match the syntax error message of Mozilla for invalid
# RegExp flags.
ecma_3/RegExp/15.10.4.1-6: FAIL_OK
@@ -578,7 +582,7 @@ js1_5/Regress/regress-352604: FAIL_OK
js1_5/Regress/regress-417893: FAIL_OK
-# Unsupported use of "[]" as function parameter. We match JSC.
+# Unsupported use of "[]" as function parameter. We match JSC.
js1_5/Regress/regress-416737-01: FAIL_OK
js1_5/Regress/regress-416737-02: FAIL_OK
diff --git a/deps/v8/tools/gdb-v8-support.py b/deps/v8/tools/gdb-v8-support.py
index 0aa1d49467..9cc046c7a5 100644
--- a/deps/v8/tools/gdb-v8-support.py
+++ b/deps/v8/tools/gdb-v8-support.py
@@ -138,7 +138,7 @@ def v8_to_int(v):
else:
return '?'
-
+
def v8_get_value(vstring):
v = gdb.parse_and_eval(vstring)
return v8_to_int(v)
diff --git a/deps/v8/tools/presubmit.py b/deps/v8/tools/presubmit.py
index c191fc7497..50d2620162 100755
--- a/deps/v8/tools/presubmit.py
+++ b/deps/v8/tools/presubmit.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2008 the V8 project authors. All rights reserved.
+# Copyright 2011 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:
@@ -42,6 +42,7 @@ import pickle
import re
import sys
import subprocess
+from subprocess import PIPE
# Disabled LINT rules and reason.
# build/include_what_you_use: Started giving false positives for variables
@@ -88,7 +89,6 @@ whitespace/blank_line
whitespace/braces
whitespace/comma
whitespace/comments
-whitespace/end_of_line
whitespace/ending_newline
whitespace/indent
whitespace/labels
@@ -231,11 +231,29 @@ COPYRIGHT_HEADER_PATTERN = re.compile(
class SourceProcessor(SourceFileProcessor):
"""
- Check that all files include a copyright notice.
+ Check that all files include a copyright notice and no trailing whitespaces.
"""
RELEVANT_EXTENSIONS = ['.js', '.cc', '.h', '.py', '.c', 'SConscript',
- 'SConstruct', '.status']
+ 'SConstruct', '.status', '.gyp', '.gypi']
+
+ # Overwriting the one in the parent class.
+ def FindFilesIn(self, path):
+ if os.path.exists(path+'/.git'):
+ output = subprocess.Popen('git ls-files --full-name',
+ stdout=PIPE, cwd=path, shell=True)
+ result = []
+ for file in output.stdout.read().split():
+ for dir_part in os.path.dirname(file).split(os.sep):
+ if self.IgnoreDir(dir_part):
+ break
+ else:
+ if self.IsRelevant(file) and not self.IgnoreFile(file):
+ result.append(join(path, file))
+ if output.wait() == 0:
+ return result
+ return super(SourceProcessor, self).FindFilesIn(path)
+
def IsRelevant(self, name):
for ext in SourceProcessor.RELEVANT_EXTENSIONS:
if name.endswith(ext):
@@ -273,6 +291,22 @@ class SourceProcessor(SourceFileProcessor):
if not COPYRIGHT_HEADER_PATTERN.search(contents):
print "%s is missing a correct copyright header." % name
result = False
+ ext = base.split('.').pop()
+ if ' \n' in contents or contents.endswith(' '):
+ line = 0
+ lines = []
+ parts = contents.split(' \n')
+ if not contents.endswith(' '):
+ parts.pop()
+ for part in parts:
+ line += part.count('\n') + 1
+ lines.append(str(line))
+ linenumbers = ', '.join(lines)
+ if len(lines) > 1:
+ print "%s has trailing whitespaces in lines %s." % (name, linenumbers)
+ else:
+ print "%s has trailing whitespaces in line %s." % (name, linenumbers)
+ result = False
return result
def ProcessFiles(self, files, path):
diff --git a/deps/v8/tools/process-heap-prof.py b/deps/v8/tools/process-heap-prof.py
index 6a2c3978d2..a26cbf1589 100755
--- a/deps/v8/tools/process-heap-prof.py
+++ b/deps/v8/tools/process-heap-prof.py
@@ -47,7 +47,7 @@ def ProcessLogFile(filename, options):
itemname = 'heap-js-cons-item'
else:
itemname = 'heap-sample-item'
-
+
first_call_time = None
sample_time = 0.0
sampling = False
@@ -108,11 +108,11 @@ def Main():
if not ProcessOptions(options):
parser.print_help()
sys.exit();
-
+
if not args:
print "Missing logfile"
sys.exit();
-
+
ProcessLogFile(args[0], options)
diff --git a/deps/v8/tools/test-wrapper-gypbuild.py b/deps/v8/tools/test-wrapper-gypbuild.py
index 9bc6bf6ac7..ad5449a404 100755
--- a/deps/v8/tools/test-wrapper-gypbuild.py
+++ b/deps/v8/tools/test-wrapper-gypbuild.py
@@ -53,6 +53,9 @@ def BuildOptions():
result.add_option("--outdir",
help='Base output directory',
default='out')
+ result.add_option("--no-presubmit",
+ help='Skip presubmit checks',
+ default=False, action="store_true")
# Flags this wrapper script handles itself:
result.add_option("-m", "--mode",
@@ -202,22 +205,31 @@ def Main():
return 1
workspace = abspath(join(dirname(sys.argv[0]), '..'))
+
+ if not options.no_presubmit:
+ print ">>> running presubmit tests"
+ subprocess.call([workspace + '/tools/presubmit.py'])
+
args_for_children = [workspace + '/tools/test.py'] + PassOnOptions(options)
args_for_children += ['--no-build', '--build-system=gyp']
for arg in args:
args_for_children += [arg]
returncodes = 0
+ env = os.environ
for mode in options.mode:
for arch in options.arch:
print ">>> running tests for %s.%s" % (arch, mode)
- shell = workspace + '/' + options.outdir + '/' + arch + '.' + mode + "/d8"
+ shellpath = workspace + '/' + options.outdir + '/' + arch + '.' + mode
+ env['LD_LIBRARY_PATH'] = shellpath + '/lib.target'
+ shell = shellpath + "/d8"
child = subprocess.Popen(' '.join(args_for_children +
['--arch=' + arch] +
['--mode=' + mode] +
['--shell=' + shell]),
shell=True,
- cwd=workspace)
+ cwd=workspace,
+ env=env)
returncodes += child.wait()
return returncodes
diff --git a/deps/v8/tools/test.py b/deps/v8/tools/test.py
index d40159c6f2..ecc0062da5 100755
--- a/deps/v8/tools/test.py
+++ b/deps/v8/tools/test.py
@@ -1164,6 +1164,7 @@ def ReadConfigurationInto(path, sections, defs):
ARCH_GUESS = utils.GuessArchitecture()
+TIMEOUT_DEFAULT = 60;
def BuildOptions():
@@ -1188,7 +1189,7 @@ def BuildOptions():
result.add_option("-s", "--suite", help="A test suite",
default=[], action="append")
result.add_option("-t", "--timeout", help="Timeout in seconds",
- default=60, type="int")
+ default=-1, type="int")
result.add_option("--arch", help='The architecture to run tests for',
default='none')
result.add_option("--snapshot", help="Run the tests with snapshot turned on",
@@ -1262,6 +1263,12 @@ def ProcessOptions(options):
if options.arch == 'none':
options.arch = ARCH_GUESS
options.scons_flags.append("arch=" + options.arch)
+ # Simulators are slow, therefore allow a longer default timeout.
+ if options.timeout == -1:
+ if options.arch == 'arm' or options.arch == 'mips':
+ options.timeout = 2 * TIMEOUT_DEFAULT;
+ else:
+ options.timeout = TIMEOUT_DEFAULT;
if options.snapshot:
options.scons_flags.append("snapshot=on")
global VARIANT_FLAGS