Version 3.28.2 (based on bleeding_edge revision r21987)
Remove bogus assertions in HCompareObjectEqAndBranch (Chromium issue 387636).
Do not eagerly update allow_osr_at_loop_nesting_level (Chromium issue 387599).
Set host_arch to ia32 on machines with a 32bit userland but a 64bit kernel (Chromium issue 368384).
Map/Set: Implement constructor parameter handling (issue 3398).
Performance and stability improvements on all platforms.
git-svn-id: https://v8.googlecode.com/svn/trunk@21989 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/BUILD.gn b/BUILD.gn
index b2a2155..2cf0b0f 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -447,6 +447,8 @@
"src/assembler.h",
"src/assert-scope.h",
"src/assert-scope.cc",
+ "src/ast-value-factory.cc",
+ "src/ast-value-factory.h",
"src/ast.cc",
"src/ast.h",
"src/bignum-dtoa.cc",
@@ -986,7 +988,6 @@
}
} else if (is_android) {
defines += [ "CAN_USE_VFP_INSTRUCTIONS" ]
- sources += [ "src/platform-posix.cc" ]
if (build_os == "mac") {
if (current_toolchain == host_toolchain) {
diff --git a/ChangeLog b/ChangeLog
index d3ae718..9907d37 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2014-06-25: Version 3.28.2
+
+ Remove bogus assertions in HCompareObjectEqAndBranch (Chromium issue
+ 387636).
+
+ Do not eagerly update allow_osr_at_loop_nesting_level (Chromium issue
+ 387599).
+
+ Set host_arch to ia32 on machines with a 32bit userland but a 64bit
+ kernel (Chromium issue 368384).
+
+ Map/Set: Implement constructor parameter handling (issue 3398).
+
+ Performance and stability improvements on all platforms.
+
+
2014-06-24: Version 3.28.1
Support LiveEdit on Arm64 (Chromium issue 368580).
diff --git a/Makefile b/Makefile
index 9c170f6..eb73f5d 100644
--- a/Makefile
+++ b/Makefile
@@ -220,7 +220,7 @@
# Architectures and modes to be compiled. Consider these to be internal
# variables, don't override them (use the targets instead).
-ARCHES = ia32 x64 arm arm64 mips mipsel x87
+ARCHES = ia32 x64 x32 arm arm64 mips mipsel x87
DEFAULT_ARCHES = ia32 x64 arm
MODES = release debug optdebug
DEFAULT_MODES = release debug
@@ -398,8 +398,7 @@
# GYP file generation targets.
OUT_MAKEFILES = $(addprefix $(OUTDIR)/Makefile.,$(BUILDS))
$(OUT_MAKEFILES): $(GYPFILES) $(ENVFILE)
- PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(PYTHONPATH)" \
- PYTHONPATH="$(shell pwd)/build/gyp/pylib:$(PYTHONPATH)" \
+ PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(shell pwd)/build:$(PYTHONPATH):$(shell pwd)/build/gyp/pylib:$(PYTHONPATH)" \
GYP_GENERATORS=make \
build/gyp/gyp --generator-output="$(OUTDIR)" build/all.gyp \
-Ibuild/standalone.gypi --depth=. \
@@ -408,8 +407,7 @@
-S$(suffix $(basename $@))$(suffix $@) $(GYPFLAGS)
$(OUTDIR)/Makefile.native: $(GYPFILES) $(ENVFILE)
- PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(PYTHONPATH)" \
- PYTHONPATH="$(shell pwd)/build/gyp/pylib:$(PYTHONPATH)" \
+ PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(shell pwd)/build:$(PYTHONPATH):$(shell pwd)/build/gyp/pylib:$(PYTHONPATH)" \
GYP_GENERATORS=make \
build/gyp/gyp --generator-output="$(OUTDIR)" build/all.gyp \
-Ibuild/standalone.gypi --depth=. -S.native $(GYPFLAGS)
diff --git a/Makefile.android b/Makefile.android
index d3ed1f4..b06d9e5 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -119,7 +119,7 @@
GYP_DEFINES="${DEFINES}" \
CC="${ANDROID_TOOLCHAIN}/bin/${TOOLCHAIN_PREFIX}-gcc" \
CXX="${ANDROID_TOOLCHAIN}/bin/${TOOLCHAIN_PREFIX}-g++" \
- PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(PYTHONPATH)" \
+ PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(shell pwd)/build:$(PYTHONPATH)" \
build/gyp/gyp --generator-output="${OUTDIR}" build/all.gyp \
-Ibuild/standalone.gypi --depth=. -Ibuild/android.gypi \
-S$(suffix $(basename $@))$(suffix $@) ${GYPFLAGS}
diff --git a/Makefile.nacl b/Makefile.nacl
index 1d34a3b..34bd960 100644
--- a/Makefile.nacl
+++ b/Makefile.nacl
@@ -97,7 +97,7 @@
GYP_DEFINES="${GYPENV}" \
CC=${NACL_CC} \
CXX=${NACL_CXX} \
- PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(PYTHONPATH)" \
+ PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(shell pwd)/build:$(PYTHONPATH)" \
build/gyp/gyp --generator-output="${OUTDIR}" build/all.gyp \
-Ibuild/standalone.gypi --depth=. \
-S$(suffix $(basename $@))$(suffix $@) $(GYPFLAGS) \
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 70f576a..430692f 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -41,6 +41,7 @@
input_api.PresubmitLocalPath(), 'tools'))
from presubmit import CppLintProcessor
from presubmit import SourceProcessor
+ from presubmit import CheckGeneratedRuntimeTests
results = []
if not CppLintProcessor().Run(input_api.PresubmitLocalPath()):
@@ -49,6 +50,9 @@
results.append(output_api.PresubmitError(
"Copyright header, trailing whitespaces and two empty lines " \
"between declarations check failed"))
+ if not CheckGeneratedRuntimeTests(input_api.PresubmitLocalPath()):
+ results.append(output_api.PresubmitError(
+ "Generated runtime tests check failed"))
return results
diff --git a/build/detect_v8_host_arch.py b/build/detect_v8_host_arch.py
new file mode 100644
index 0000000..f66383b
--- /dev/null
+++ b/build/detect_v8_host_arch.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+# Copyright 2014 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.
+
+"""Outputs host CPU architecture in format recognized by gyp."""
+
+import platform
+import re
+import sys
+
+
+def main():
+ print DoMain([])
+ return 0
+
+def DoMain(_):
+ """Hook to be called from gyp without starting a separate python
+ interpreter."""
+ host_arch = platform.machine()
+
+ # Convert machine type to format recognized by gyp.
+ if re.match(r'i.86', host_arch) or host_arch == 'i86pc':
+ host_arch = 'ia32'
+ elif host_arch in ['x86_64', 'amd64']:
+ host_arch = 'x64'
+ elif host_arch.startswith('arm'):
+ host_arch = 'arm'
+ elif host_arch == 'aarch64':
+ host_arch = 'arm64'
+ elif host_arch.startswith('mips'):
+ host_arch = 'mipsel'
+
+ # platform.machine is based on running kernel. It's possible to use 64-bit
+ # kernel with 32-bit userland, e.g. to give linker slightly more memory.
+ # Distinguish between different userland bitness by querying
+ # the python binary.
+ if host_arch == 'x64' and platform.architecture()[0] == '32bit':
+ host_arch = 'ia32'
+
+ return host_arch
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/build/standalone.gypi b/build/standalone.gypi
index 7670e5b..7952bdc 100644
--- a/build/standalone.gypi
+++ b/build/standalone.gypi
@@ -51,13 +51,7 @@
# Anything else gets passed through, which probably won't work
# very well; such hosts should pass an explicit target_arch
# to gyp.
- 'host_arch%':
- '<!(uname -m | sed -e "s/i.86/ia32/;\
- s/x86_64/x64/;\
- s/amd64/x64/;\
- s/arm.*/arm/;\
- s/aarch64/arm64/;\
- s/mips.*/mipsel/")',
+ 'host_arch%': '<!pymod_do_main(detect_v8_host_arch)',
}, {
# OS!="linux" and OS!="freebsd" and OS!="openbsd" and
# OS!="netbsd" and OS!="mac"
diff --git a/build/toolchain.gypi b/build/toolchain.gypi
index 4e6869b..0852eac 100644
--- a/build/toolchain.gypi
+++ b/build/toolchain.gypi
@@ -348,6 +348,21 @@
},
'msvs_configuration_platform': 'x64',
}], # v8_target_arch=="x64"
+ ['v8_target_arch=="x32"', {
+ 'defines': [
+ # x32 port shares the source code with x64 port.
+ 'V8_TARGET_ARCH_X64',
+ 'V8_TARGET_ARCH_32_BIT',
+ ],
+ 'cflags': [
+ '-mx32',
+ # Inhibit warning if long long type is used.
+ '-Wno-long-long',
+ ],
+ 'ldflags': [
+ '-mx32',
+ ],
+ }], # v8_target_arch=="x32"
['OS=="win"', {
'defines': [
'WIN32',
diff --git a/include/v8.h b/include/v8.h
index 5176566..7d27029 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -5586,7 +5586,7 @@
static const int kNullValueRootIndex = 7;
static const int kTrueValueRootIndex = 8;
static const int kFalseValueRootIndex = 9;
- static const int kEmptyStringRootIndex = 163;
+ static const int kEmptyStringRootIndex = 160;
// The external allocation limit should be below 256 MB on all architectures
// to avoid that resource-constrained embedders run low on memory.
@@ -6214,7 +6214,7 @@
String::ExternalStringResource* String::GetExternalStringResource() const {
typedef internal::Object O;
typedef internal::Internals I;
- O* obj = *reinterpret_cast<O**>(const_cast<String*>(this));
+ O* obj = *reinterpret_cast<O* const*>(this);
String::ExternalStringResource* result;
if (I::IsExternalTwoByteString(I::GetInstanceType(obj))) {
void* value = I::ReadField<void*>(obj, I::kStringResourceOffset);
@@ -6233,7 +6233,7 @@
String::Encoding* encoding_out) const {
typedef internal::Object O;
typedef internal::Internals I;
- O* obj = *reinterpret_cast<O**>(const_cast<String*>(this));
+ O* obj = *reinterpret_cast<O* const*>(this);
int type = I::GetInstanceType(obj) & I::kFullStringRepresentationMask;
*encoding_out = static_cast<Encoding>(type & I::kStringEncodingMask);
ExternalStringResourceBase* resource = NULL;
@@ -6260,7 +6260,7 @@
bool Value::QuickIsUndefined() const {
typedef internal::Object O;
typedef internal::Internals I;
- O* obj = *reinterpret_cast<O**>(const_cast<Value*>(this));
+ O* obj = *reinterpret_cast<O* const*>(this);
if (!I::HasHeapObjectTag(obj)) return false;
if (I::GetInstanceType(obj) != I::kOddballType) return false;
return (I::GetOddballKind(obj) == I::kUndefinedOddballKind);
@@ -6278,7 +6278,7 @@
bool Value::QuickIsNull() const {
typedef internal::Object O;
typedef internal::Internals I;
- O* obj = *reinterpret_cast<O**>(const_cast<Value*>(this));
+ O* obj = *reinterpret_cast<O* const*>(this);
if (!I::HasHeapObjectTag(obj)) return false;
if (I::GetInstanceType(obj) != I::kOddballType) return false;
return (I::GetOddballKind(obj) == I::kNullOddballKind);
@@ -6296,7 +6296,7 @@
bool Value::QuickIsString() const {
typedef internal::Object O;
typedef internal::Internals I;
- O* obj = *reinterpret_cast<O**>(const_cast<Value*>(this));
+ O* obj = *reinterpret_cast<O* const*>(this);
if (!I::HasHeapObjectTag(obj)) return false;
return (I::GetInstanceType(obj) < I::kFirstNonstringType);
}
diff --git a/src/api.cc b/src/api.cc
index fc22929..92aa745 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -3432,7 +3432,7 @@
i::JSObject::SetAccessor(Utils::OpenHandle(obj), info),
false);
if (result->IsUndefined()) return false;
- if (fast) i::JSObject::TransformToFastProperties(Utils::OpenHandle(obj), 0);
+ if (fast) i::JSObject::MigrateSlowToFast(Utils::OpenHandle(obj), 0);
return true;
}
@@ -3600,7 +3600,7 @@
i::Handle<i::Map> new_map = i::Map::Copy(i::Handle<i::Map>(obj->map()));
new_map->set_is_access_check_needed(true);
- obj->set_map(*new_map);
+ i::JSObject::MigrateToMap(obj, new_map);
}
diff --git a/src/api.h b/src/api.h
index 7a688ca..ccede0d 100644
--- a/src/api.h
+++ b/src/api.h
@@ -370,8 +370,7 @@
const v8::From* that, bool allow_empty_handle) { \
EXTRA_CHECK(allow_empty_handle || that != NULL); \
EXTRA_CHECK(that == NULL || \
- (*reinterpret_cast<v8::internal::Object**>( \
- const_cast<v8::From*>(that)))->Is##To()); \
+ (*reinterpret_cast<v8::internal::Object* const*>(that))->Is##To()); \
return v8::internal::Handle<v8::internal::To>( \
reinterpret_cast<v8::internal::To**>(const_cast<v8::From*>(that))); \
}
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index 6a35d93..814bd8b 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -400,10 +400,6 @@
// -----------------------------------------------------------------------------
// Specific instructions, constants, and masks.
-// add(sp, sp, 4) instruction (aka Pop())
-const Instr kPopInstruction =
- al | PostIndex | 4 | LeaveCC | I | kRegister_sp_Code * B16 |
- kRegister_sp_Code * B12;
// str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r))
// register r is not encoded.
const Instr kPushRegPattern =
@@ -412,8 +408,6 @@
// register r is not encoded.
const Instr kPopRegPattern =
al | B26 | L | 4 | PostIndex | kRegister_sp_Code * B16;
-// mov lr, pc
-const Instr kMovLrPc = al | MOV | kRegister_pc_Code | kRegister_lr_Code * B12;
// ldr rd, [pc, #offset]
const Instr kLdrPCImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
const Instr kLdrPCImmedPattern = 5 * B24 | L | kRegister_pc_Code * B16;
@@ -437,8 +431,6 @@
const Instr kMovMvnFlip = B22;
const Instr kMovLeaveCCMask = 0xdff * B16;
const Instr kMovLeaveCCPattern = 0x1a0 * B16;
-const Instr kMovwMask = 0xff * B20;
-const Instr kMovwPattern = 0x30 * B20;
const Instr kMovwLeaveCCFlip = 0x5 * B21;
const Instr kCmpCmnMask = 0xdd * B20 | 0xf * B12;
const Instr kCmpCmnPattern = 0x15 * B20;
@@ -456,8 +448,6 @@
const Instr kStrRegFpNegOffsetPattern =
al | B26 | NegOffset | kRegister_fp_Code * B16;
const Instr kLdrStrInstrTypeMask = 0xffff0000;
-const Instr kLdrStrInstrArgumentMask = 0x0000ffff;
-const Instr kLdrStrOffsetMask = 0x00000fff;
Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
diff --git a/src/arm/cpu-arm.cc b/src/arm/cpu-arm.cc
index 78ab5f7..6412366 100644
--- a/src/arm/cpu-arm.cc
+++ b/src/arm/cpu-arm.cc
@@ -52,7 +52,7 @@
// r0 = beg
// r1 = end
// r2 = flags (0)
- " ldr r7, =%[scno]\n" // r7 = syscall number
+ " ldr r7, =%c[scno]\n" // r7 = syscall number
" svc 0\n"
" pop {r7}\n"
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index 2d2b31c..0392997 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -2369,9 +2369,7 @@
LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
info()->MarkAsDeferredCalling();
LOperand* context = UseAny(instr->context());
- LOperand* size = instr->size()->IsConstant()
- ? UseConstant(instr->size())
- : UseTempRegister(instr->size());
+ LOperand* size = UseRegisterOrConstant(instr->size());
LOperand* temp1 = TempRegister();
LOperand* temp2 = TempRegister();
LAllocate* result = new(zone()) LAllocate(context, size, temp1, temp2);
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 36aec45..14c34ca 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -5276,33 +5276,25 @@
}
} else {
Register size = ToRegister(instr->size());
- __ Allocate(size,
- result,
- scratch,
- scratch2,
- deferred->entry(),
- flags);
+ __ Allocate(size, result, scratch, scratch2, deferred->entry(), flags);
}
__ bind(deferred->exit());
if (instr->hydrogen()->MustPrefillWithFiller()) {
+ STATIC_ASSERT(kHeapObjectTag == 1);
if (instr->size()->IsConstantOperand()) {
int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
- __ mov(scratch, Operand(size));
+ __ mov(scratch, Operand(size - kHeapObjectTag));
} else {
- scratch = ToRegister(instr->size());
+ __ sub(scratch, ToRegister(instr->size()), Operand(kHeapObjectTag));
}
- __ sub(scratch, scratch, Operand(kPointerSize));
- __ sub(result, result, Operand(kHeapObjectTag));
+ __ mov(scratch2, Operand(isolate()->factory()->one_pointer_filler_map()));
Label loop;
__ bind(&loop);
- __ mov(scratch2, Operand(isolate()->factory()->one_pointer_filler_map()));
+ __ sub(scratch, scratch, Operand(kPointerSize), SetCC);
__ str(scratch2, MemOperand(result, scratch));
- __ sub(scratch, scratch, Operand(kPointerSize));
- __ cmp(scratch, Operand(0));
__ b(ge, &loop);
- __ add(result, result, Operand(kHeapObjectTag));
}
}
diff --git a/src/arm64/assembler-arm64.cc b/src/arm64/assembler-arm64.cc
index 484bf10..ee41875 100644
--- a/src/arm64/assembler-arm64.cc
+++ b/src/arm64/assembler-arm64.cc
@@ -455,7 +455,7 @@
// + 1 is for the crash guard.
// + 0/1 for alignment.
int word_count = EntryCount() * 2 + 1 +
- (IsAligned(assm_->pc_offset(), 8)) ? 0 : 1;
+ (IsAligned(assm_->pc_offset(), 8) ? 0 : 1);
assm_->Emit(LDR_x_lit |
Assembler::ImmLLiteral(word_count) |
Assembler::Rt(xzr));
diff --git a/src/arm64/debug-arm64.cc b/src/arm64/debug-arm64.cc
index 43ebd36..1a29ffb 100644
--- a/src/arm64/debug-arm64.cc
+++ b/src/arm64/debug-arm64.cc
@@ -132,12 +132,10 @@
FrameScope scope(masm, StackFrame::INTERNAL);
// Load padding words on stack.
- __ ldr(scratch, Smi::FromInt(LiveEdit::kFramePaddingValue));
- for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) {
- __ push(scratch);
- }
- __ ldr(scratch, Smi::FromInt(LiveEdit::kFramePaddingInitialSize));
- __ push(scratch);
+ __ Mov(scratch, Smi::FromInt(LiveEdit::kFramePaddingValue));
+ __ PushMultipleTimes(scratch, LiveEdit::kFramePaddingInitialSize);
+ __ Mov(scratch, Smi::FromInt(LiveEdit::kFramePaddingInitialSize));
+ __ Push(scratch);
// Any live values (object_regs and non_object_regs) in caller-saved
// registers (or lr) need to be stored on the stack so that their values are
@@ -360,25 +358,28 @@
ExternalReference restarter_frame_function_slot =
ExternalReference::debug_restarter_frame_function_pointer_address(
masm->isolate());
- __ mov(x1, xzr);
- __ Mov(ip0, restarter_frame_function_slot);
- __ str(x1, MemOperand(ip0, 0));
+ UseScratchRegisterScope temps(masm);
+ Register scratch = temps.AcquireX();
+
+ __ Mov(scratch, restarter_frame_function_slot);
+ __ Str(xzr, MemOperand(scratch));
// We do not know our frame height, but set sp based on fp.
- __ sub(jssp, fp, Operand(kPointerSize));
+ __ Sub(masm->StackPointer(), fp, kPointerSize);
+ __ AssertStackConsistency();
__ Pop(x1, fp, lr); // Function, Frame, Return address.
// Load context from the function.
- __ ldr(cp, FieldMemOperand(x1, JSFunction::kContextOffset));
+ __ Ldr(cp, FieldMemOperand(x1, JSFunction::kContextOffset));
// Get function code.
- __ ldr(ip0, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
- __ ldr(ip0, FieldMemOperand(ip0, SharedFunctionInfo::kCodeOffset));
- __ add(ip0, ip0, Operand(Code::kHeaderSize - kHeapObjectTag));
+ __ Ldr(scratch, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
+ __ Ldr(scratch, FieldMemOperand(scratch, SharedFunctionInfo::kCodeOffset));
+ __ Add(scratch, scratch, Code::kHeaderSize - kHeapObjectTag);
// Re-run JSFunction, x1 is function, cp is context.
- __ Jump(ip0);
+ __ Br(scratch);
}
diff --git a/src/ast-value-factory.cc b/src/ast-value-factory.cc
new file mode 100644
index 0000000..cb37902
--- /dev/null
+++ b/src/ast-value-factory.cc
@@ -0,0 +1,409 @@
+// Copyright 2014 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.
+
+#include "src/ast-value-factory.h"
+
+#include "src/api.h"
+#include "src/objects.h"
+
+namespace v8 {
+namespace internal {
+
+namespace {
+
+// For using StringToArrayIndex.
+class OneByteStringStream {
+ public:
+ explicit OneByteStringStream(Vector<const byte> lb) :
+ literal_bytes_(lb), pos_(0) {}
+
+ bool HasMore() { return pos_ < literal_bytes_.length(); }
+ uint16_t GetNext() { return literal_bytes_[pos_++]; }
+
+ private:
+ Vector<const byte> literal_bytes_;
+ int pos_;
+};
+
+}
+
+class AstRawStringInternalizationKey : public HashTableKey {
+ public:
+ explicit AstRawStringInternalizationKey(const AstRawString* string)
+ : string_(string) {}
+
+ virtual bool IsMatch(Object* other) V8_OVERRIDE {
+ if (string_->is_one_byte_)
+ return String::cast(other)->IsOneByteEqualTo(string_->literal_bytes_);
+ return String::cast(other)->IsTwoByteEqualTo(
+ Vector<const uint16_t>::cast(string_->literal_bytes_));
+ }
+
+ virtual uint32_t Hash() V8_OVERRIDE {
+ return string_->hash() >> Name::kHashShift;
+ }
+
+ virtual uint32_t HashForObject(Object* key) V8_OVERRIDE {
+ return String::cast(key)->Hash();
+ }
+
+ virtual Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE {
+ if (string_->is_one_byte_)
+ return isolate->factory()->NewOneByteInternalizedString(
+ string_->literal_bytes_, string_->hash());
+ return isolate->factory()->NewTwoByteInternalizedString(
+ Vector<const uint16_t>::cast(string_->literal_bytes_), string_->hash());
+ }
+
+ private:
+ const AstRawString* string_;
+};
+
+
+void AstRawString::Internalize(Isolate* isolate) {
+ if (!string_.is_null()) return;
+ if (literal_bytes_.length() == 0) {
+ string_ = isolate->factory()->empty_string();
+ } else {
+ AstRawStringInternalizationKey key(this);
+ string_ = StringTable::LookupKey(isolate, &key);
+ }
+}
+
+
+bool AstRawString::AsArrayIndex(uint32_t* index) const {
+ if (!string_.is_null())
+ return string_->AsArrayIndex(index);
+ if (!is_one_byte_ || literal_bytes_.length() == 0 ||
+ literal_bytes_.length() > String::kMaxArrayIndexSize)
+ return false;
+ OneByteStringStream stream(literal_bytes_);
+ return StringToArrayIndex(&stream, index);
+}
+
+
+bool AstRawString::IsOneByteEqualTo(const char* data) const {
+ int length = static_cast<int>(strlen(data));
+ if (is_one_byte_ && literal_bytes_.length() == length) {
+ const char* token = reinterpret_cast<const char*>(literal_bytes_.start());
+ return !strncmp(token, data, length);
+ }
+ return false;
+}
+
+
+bool AstRawString::Compare(void* a, void* b) {
+ AstRawString* string1 = reinterpret_cast<AstRawString*>(a);
+ AstRawString* string2 = reinterpret_cast<AstRawString*>(b);
+ if (string1->is_one_byte_ != string2->is_one_byte_) return false;
+ if (string1->hash_ != string2->hash_) return false;
+ int length = string1->literal_bytes_.length();
+ if (string2->literal_bytes_.length() != length) return false;
+ return memcmp(string1->literal_bytes_.start(),
+ string2->literal_bytes_.start(), length) == 0;
+}
+
+
+void AstConsString::Internalize(Isolate* isolate) {
+ // AstRawStrings are internalized before AstConsStrings so left and right are
+ // already internalized.
+ string_ = isolate->factory()
+ ->NewConsString(left_->string(), right_->string())
+ .ToHandleChecked();
+}
+
+
+bool AstValue::IsPropertyName() const {
+ if (type_ == STRING) {
+ uint32_t index;
+ return !string_->AsArrayIndex(&index);
+ }
+ return false;
+}
+
+
+bool AstValue::BooleanValue() const {
+ switch (type_) {
+ case STRING:
+ ASSERT(string_ != NULL);
+ return !string_->IsEmpty();
+ case SYMBOL:
+ UNREACHABLE();
+ break;
+ case NUMBER:
+ return DoubleToBoolean(number_);
+ case SMI:
+ return smi_ != 0;
+ case STRING_ARRAY:
+ UNREACHABLE();
+ break;
+ case BOOLEAN:
+ return bool_;
+ case NULL_TYPE:
+ return false;
+ case THE_HOLE:
+ UNREACHABLE();
+ break;
+ case UNDEFINED:
+ return false;
+ }
+ UNREACHABLE();
+ return false;
+}
+
+
+void AstValue::Internalize(Isolate* isolate) {
+ switch (type_) {
+ case STRING:
+ ASSERT(string_ != NULL);
+ // Strings are already internalized.
+ ASSERT(!string_->string().is_null());
+ break;
+ case SYMBOL:
+ value_ = Object::GetProperty(
+ isolate, handle(isolate->native_context()->builtins()),
+ symbol_name_).ToHandleChecked();
+ break;
+ case NUMBER:
+ value_ = isolate->factory()->NewNumber(number_, TENURED);
+ break;
+ case SMI:
+ value_ = handle(Smi::FromInt(smi_), isolate);
+ break;
+ case BOOLEAN:
+ if (bool_) {
+ value_ = isolate->factory()->true_value();
+ } else {
+ value_ = isolate->factory()->false_value();
+ }
+ break;
+ case STRING_ARRAY: {
+ ASSERT(strings_ != NULL);
+ Factory* factory = isolate->factory();
+ int len = strings_->length();
+ Handle<FixedArray> elements = factory->NewFixedArray(len, TENURED);
+ for (int i = 0; i < len; i++) {
+ const AstRawString* string = (*strings_)[i];
+ Handle<Object> element = string->string();
+ // Strings are already internalized.
+ ASSERT(!element.is_null());
+ elements->set(i, *element);
+ }
+ value_ =
+ factory->NewJSArrayWithElements(elements, FAST_ELEMENTS, TENURED);
+ break;
+ }
+ case NULL_TYPE:
+ value_ = isolate->factory()->null_value();
+ break;
+ case THE_HOLE:
+ value_ = isolate->factory()->the_hole_value();
+ break;
+ case UNDEFINED:
+ value_ = isolate->factory()->undefined_value();
+ break;
+ }
+}
+
+
+const AstRawString* AstValueFactory::GetOneByteString(
+ Vector<const uint8_t> literal) {
+ uint32_t hash = StringHasher::HashSequentialString<uint8_t>(
+ literal.start(), literal.length(), hash_seed_);
+ return GetString(hash, true, literal);
+}
+
+
+const AstRawString* AstValueFactory::GetTwoByteString(
+ Vector<const uint16_t> literal) {
+ uint32_t hash = StringHasher::HashSequentialString<uint16_t>(
+ literal.start(), literal.length(), hash_seed_);
+ return GetString(hash, false, Vector<const byte>::cast(literal));
+}
+
+
+const AstRawString* AstValueFactory::GetString(Handle<String> literal) {
+ DisallowHeapAllocation no_gc;
+ String::FlatContent content = literal->GetFlatContent();
+ if (content.IsAscii()) {
+ return GetOneByteString(content.ToOneByteVector());
+ }
+ ASSERT(content.IsTwoByte());
+ return GetTwoByteString(content.ToUC16Vector());
+}
+
+
+const AstConsString* AstValueFactory::NewConsString(
+ const AstString* left, const AstString* right) {
+ // This Vector will be valid as long as the Collector is alive (meaning that
+ // the AstRawString will not be moved).
+ AstConsString* new_string = new (zone_) AstConsString(left, right);
+ strings_.Add(new_string);
+ if (isolate_) {
+ new_string->Internalize(isolate_);
+ }
+ return new_string;
+}
+
+
+void AstValueFactory::Internalize(Isolate* isolate) {
+ if (isolate_) {
+ // Everything is already internalized.
+ return;
+ }
+ // Strings need to be internalized before values, because values refer to
+ // strings.
+ for (int i = 0; i < strings_.length(); ++i) {
+ strings_[i]->Internalize(isolate);
+ }
+ for (int i = 0; i < values_.length(); ++i) {
+ values_[i]->Internalize(isolate);
+ }
+ isolate_ = isolate;
+}
+
+
+const AstValue* AstValueFactory::NewString(const AstRawString* string) {
+ AstValue* value = new (zone_) AstValue(string);
+ ASSERT(string != NULL);
+ if (isolate_) {
+ value->Internalize(isolate_);
+ }
+ values_.Add(value);
+ return value;
+}
+
+
+const AstValue* AstValueFactory::NewSymbol(const char* name) {
+ AstValue* value = new (zone_) AstValue(name);
+ if (isolate_) {
+ value->Internalize(isolate_);
+ }
+ values_.Add(value);
+ return value;
+}
+
+
+const AstValue* AstValueFactory::NewNumber(double number) {
+ AstValue* value = new (zone_) AstValue(number);
+ if (isolate_) {
+ value->Internalize(isolate_);
+ }
+ values_.Add(value);
+ return value;
+}
+
+
+const AstValue* AstValueFactory::NewSmi(int number) {
+ AstValue* value =
+ new (zone_) AstValue(AstValue::SMI, number);
+ if (isolate_) {
+ value->Internalize(isolate_);
+ }
+ values_.Add(value);
+ return value;
+}
+
+
+const AstValue* AstValueFactory::NewBoolean(bool b) {
+ AstValue* value = new (zone_) AstValue(b);
+ if (isolate_) {
+ value->Internalize(isolate_);
+ }
+ values_.Add(value);
+ return value;
+}
+
+
+const AstValue* AstValueFactory::NewStringList(
+ ZoneList<const AstRawString*>* strings) {
+ AstValue* value = new (zone_) AstValue(strings);
+ if (isolate_) {
+ value->Internalize(isolate_);
+ }
+ values_.Add(value);
+ return value;
+}
+
+
+const AstValue* AstValueFactory::NewNull() {
+ AstValue* value = new (zone_) AstValue(AstValue::NULL_TYPE);
+ if (isolate_) {
+ value->Internalize(isolate_);
+ }
+ values_.Add(value);
+ return value;
+}
+
+
+const AstValue* AstValueFactory::NewUndefined() {
+ AstValue* value = new (zone_) AstValue(AstValue::UNDEFINED);
+ if (isolate_) {
+ value->Internalize(isolate_);
+ }
+ values_.Add(value);
+ return value;
+}
+
+
+const AstValue* AstValueFactory::NewTheHole() {
+ AstValue* value = new (zone_) AstValue(AstValue::THE_HOLE);
+ if (isolate_) {
+ value->Internalize(isolate_);
+ }
+ values_.Add(value);
+ return value;
+}
+
+
+const AstRawString* AstValueFactory::GetString(
+ uint32_t hash, bool is_one_byte, Vector<const byte> literal_bytes) {
+ // literal_bytes here points to whatever the user passed, and this is OK
+ // because we use vector_compare (which checks the contents) to compare
+ // against the AstRawStrings which are in the string_table_. We should not
+ // return this AstRawString.
+ AstRawString key(is_one_byte, literal_bytes, hash);
+ HashMap::Entry* entry = string_table_.Lookup(&key, hash, true);
+ if (entry->value == NULL) {
+ // Copy literal contents for later comparison.
+ int length = literal_bytes.length();
+ byte* new_literal_bytes = zone_->NewArray<byte>(length);
+ memcpy(new_literal_bytes, literal_bytes.start(), length);
+ AstRawString* new_string = new (zone_) AstRawString(
+ is_one_byte, Vector<const byte>(new_literal_bytes, length), hash);
+ entry->key = new_string;
+ strings_.Add(new_string);
+ if (isolate_) {
+ new_string->Internalize(isolate_);
+ }
+ entry->value = reinterpret_cast<void*>(1);
+ }
+ return reinterpret_cast<AstRawString*>(entry->key);
+}
+
+
+} } // namespace v8::internal
diff --git a/src/ast-value-factory.h b/src/ast-value-factory.h
new file mode 100644
index 0000000..51ee277
--- /dev/null
+++ b/src/ast-value-factory.h
@@ -0,0 +1,340 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_AST_VALUE_FACTORY_H_
+#define V8_AST_VALUE_FACTORY_H_
+
+#include "src/api.h"
+#include "src/hashmap.h"
+#include "src/utils.h"
+
+// AstString, AstValue and AstValueFactory are for storing strings and values
+// independent of the V8 heap and internalizing them later. During parsing,
+// AstStrings and AstValues are created and stored outside the heap, in
+// AstValueFactory. After parsing, the strings and values are internalized
+// (moved into the V8 heap).
+namespace v8 {
+namespace internal {
+
+class AstString : public ZoneObject {
+ public:
+ virtual ~AstString() {}
+
+ virtual int length() const = 0;
+ bool IsEmpty() const { return length() == 0; }
+
+ // Puts the string into the V8 heap.
+ virtual void Internalize(Isolate* isolate) = 0;
+
+ // This function can be called after internalizing.
+ V8_INLINE Handle<String> string() const {
+ ASSERT(!string_.is_null());
+ return string_;
+ }
+
+ protected:
+ // This is null until the string is internalized.
+ Handle<String> string_;
+};
+
+
+class AstRawString : public AstString {
+ public:
+ virtual int length() const V8_OVERRIDE {
+ if (is_one_byte_)
+ return literal_bytes_.length();
+ return literal_bytes_.length() / 2;
+ }
+
+ virtual void Internalize(Isolate* isolate) V8_OVERRIDE;
+
+ bool AsArrayIndex(uint32_t* index) const;
+
+ // The string is not null-terminated, use length() to find out the length.
+ const unsigned char* raw_data() const {
+ return literal_bytes_.start();
+ }
+ bool is_one_byte() const { return is_one_byte_; }
+ bool IsOneByteEqualTo(const char* data) const;
+ uint16_t FirstCharacter() const {
+ if (is_one_byte_)
+ return literal_bytes_[0];
+ const uint16_t* c =
+ reinterpret_cast<const uint16_t*>(literal_bytes_.start());
+ return *c;
+ }
+
+ // For storing AstRawStrings in a hash map.
+ uint32_t hash() const {
+ return hash_;
+ }
+ static bool Compare(void* a, void* b);
+
+ private:
+ friend class AstValueFactory;
+ friend class AstRawStringInternalizationKey;
+
+ AstRawString(bool is_one_byte, const Vector<const byte>& literal_bytes,
+ uint32_t hash)
+ : is_one_byte_(is_one_byte), literal_bytes_(literal_bytes), hash_(hash) {}
+
+ AstRawString()
+ : is_one_byte_(true),
+ hash_(0) {}
+
+ bool is_one_byte_;
+
+ // Points to memory owned by Zone.
+ Vector<const byte> literal_bytes_;
+ uint32_t hash_;
+};
+
+
+class AstConsString : public AstString {
+ public:
+ AstConsString(const AstString* left, const AstString* right)
+ : left_(left),
+ right_(right) {}
+
+ virtual int length() const V8_OVERRIDE {
+ return left_->length() + right_->length();
+ }
+
+ virtual void Internalize(Isolate* isolate) V8_OVERRIDE;
+
+ private:
+ friend class AstValueFactory;
+
+ const AstString* left_;
+ const AstString* right_;
+};
+
+
+// AstValue is either a string, a number, a string array, a boolean, or a
+// special value (null, undefined, the hole).
+class AstValue : public ZoneObject {
+ public:
+ bool IsString() const {
+ return type_ == STRING;
+ }
+
+ bool IsNumber() const {
+ return type_ == NUMBER || type_ == SMI;
+ }
+
+ const AstRawString* AsString() const {
+ if (type_ == STRING)
+ return string_;
+ UNREACHABLE();
+ return 0;
+ }
+
+ double AsNumber() const {
+ if (type_ == NUMBER)
+ return number_;
+ if (type_ == SMI)
+ return smi_;
+ UNREACHABLE();
+ return 0;
+ }
+
+ bool EqualsString(const AstRawString* string) const {
+ return type_ == STRING && string_ == string;
+ }
+
+ bool IsPropertyName() const;
+
+ bool BooleanValue() const;
+
+ void Internalize(Isolate* isolate);
+
+ // Can be called after Internalize has been called.
+ V8_INLINE Handle<Object> value() const {
+ if (type_ == STRING) {
+ return string_->string();
+ }
+ ASSERT(!value_.is_null());
+ return value_;
+ }
+
+ private:
+ friend class AstValueFactory;
+
+ enum Type {
+ STRING,
+ SYMBOL,
+ NUMBER,
+ SMI,
+ BOOLEAN,
+ STRING_ARRAY,
+ NULL_TYPE,
+ UNDEFINED,
+ THE_HOLE
+ };
+
+ explicit AstValue(const AstRawString* s) : type_(STRING) { string_ = s; }
+
+ explicit AstValue(const char* name) : type_(SYMBOL) { symbol_name_ = name; }
+
+ explicit AstValue(double n) : type_(NUMBER) { number_ = n; }
+
+ AstValue(Type t, int i) : type_(t) {
+ ASSERT(type_ == SMI);
+ smi_ = i;
+ }
+
+ explicit AstValue(bool b) : type_(BOOLEAN) { bool_ = b; }
+
+ explicit AstValue(ZoneList<const AstRawString*>* s) : type_(STRING_ARRAY) {
+ strings_ = s;
+ }
+
+ explicit AstValue(Type t) : type_(t) {
+ ASSERT(t == NULL_TYPE || t == UNDEFINED || t == THE_HOLE);
+ }
+
+ Type type_;
+
+ // Uninternalized value.
+ union {
+ const AstRawString* string_;
+ double number_;
+ int smi_;
+ bool bool_;
+ ZoneList<const AstRawString*>* strings_;
+ const char* symbol_name_;
+ };
+
+ // Internalized value (empty before internalized).
+ Handle<Object> value_;
+};
+
+
+// For generating string constants.
+#define STRING_CONSTANTS(F) \
+ F(anonymous_function, "(anonymous function)") \
+ F(arguments, "arguments") \
+ F(done, "done") \
+ F(dot, ".") \
+ F(dot_for, ".for") \
+ F(dot_generator, ".generator") \
+ F(dot_generator_object, ".generator_object") \
+ F(dot_iterable, ".iterable") \
+ F(dot_iterator, ".iterator") \
+ F(dot_module, ".module") \
+ F(dot_result, ".result") \
+ F(empty, "") \
+ F(eval, "eval") \
+ F(initialize_const_global, "initializeConstGlobal") \
+ F(initialize_var_global, "initializeVarGlobal") \
+ F(make_reference_error, "MakeReferenceError") \
+ F(make_syntax_error, "MakeSyntaxError") \
+ F(make_type_error, "MakeTypeError") \
+ F(module, "module") \
+ F(native, "native") \
+ F(next, "next") \
+ F(proto, "__proto__") \
+ F(prototype, "prototype") \
+ F(this, "this") \
+ F(use_strict, "use strict") \
+ F(value, "value")
+
+
+class AstValueFactory {
+ public:
+ AstValueFactory(Zone* zone, uint32_t hash_seed)
+ : string_table_(AstRawString::Compare),
+ zone_(zone),
+ isolate_(NULL),
+ hash_seed_(hash_seed) {
+#define F(name, str) \
+ name##_string_ = NULL;
+ STRING_CONSTANTS(F)
+#undef F
+ }
+
+ const AstRawString* GetOneByteString(Vector<const uint8_t> literal);
+ const AstRawString* GetTwoByteString(Vector<const uint16_t> literal);
+ const AstRawString* GetString(Handle<String> literal);
+ const AstConsString* NewConsString(const AstString* left,
+ const AstString* right);
+
+ void Internalize(Isolate* isolate);
+ bool IsInternalized() {
+ return isolate_ != NULL;
+ }
+
+#define F(name, str) \
+ const AstRawString* name##_string() { \
+ if (name##_string_ == NULL) { \
+ const char* data = str; \
+ name##_string_ = GetOneByteString( \
+ Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), \
+ static_cast<int>(strlen(data)))); \
+ } \
+ return name##_string_; \
+ }
+ STRING_CONSTANTS(F)
+#undef F
+
+ const AstValue* NewString(const AstRawString* string);
+ // A JavaScript symbol (ECMA-262 edition 6).
+ const AstValue* NewSymbol(const char* name);
+ const AstValue* NewNumber(double number);
+ const AstValue* NewSmi(int number);
+ const AstValue* NewBoolean(bool b);
+ const AstValue* NewStringList(ZoneList<const AstRawString*>* strings);
+ const AstValue* NewNull();
+ const AstValue* NewUndefined();
+ const AstValue* NewTheHole();
+
+ private:
+ const AstRawString* GetString(uint32_t hash, bool is_one_byte,
+ Vector<const byte> literal_bytes);
+
+ // All strings are copied here, one after another (no NULLs inbetween).
+ HashMap string_table_;
+ // For keeping track of all AstValues and AstRawStrings we've created (so that
+ // they can be internalized later).
+ List<AstValue*> values_;
+ List<AstString*> strings_;
+ Zone* zone_;
+ Isolate* isolate_;
+
+ uint32_t hash_seed_;
+
+#define F(name, str) \
+ const AstRawString* name##_string_;
+ STRING_CONSTANTS(F)
+#undef F
+};
+
+} } // namespace v8::internal
+
+#undef STRING_CONSTANTS
+
+#endif // V8_AST_VALUE_FACTORY_H_
diff --git a/src/ast.cc b/src/ast.cc
index 3f19fbf..53d2799 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -55,14 +55,13 @@
// The global identifier "undefined" is immutable. Everything
// else could be reassigned.
return var != NULL && var->location() == Variable::UNALLOCATED &&
- String::Equals(var_proxy->name(),
- isolate->factory()->undefined_string());
+ var_proxy->raw_name()->IsOneByteEqualTo("undefined");
}
VariableProxy::VariableProxy(Zone* zone, Variable* var, int position)
: Expression(zone, position),
- name_(var->name()),
+ name_(var->raw_name()),
var_(NULL), // Will be set by the call to BindTo.
is_this_(var->is_this()),
is_trivial_(false),
@@ -73,7 +72,7 @@
VariableProxy::VariableProxy(Zone* zone,
- Handle<String> name,
+ const AstRawString* name,
bool is_this,
Interface* interface,
int position)
@@ -84,8 +83,6 @@
is_trivial_(false),
is_lvalue_(false),
interface_(interface) {
- // Names must be canonicalized for fast equality checks.
- ASSERT(name->IsInternalizedString());
}
@@ -93,7 +90,7 @@
ASSERT(var_ == NULL); // must be bound only once
ASSERT(var != NULL); // must bind
ASSERT(!FLAG_harmony_modules || interface_->IsUnified(var->interface()));
- ASSERT((is_this() && var->is_this()) || name_.is_identical_to(var->name()));
+ ASSERT((is_this() && var->is_this()) || name_ == var->raw_name());
// Ideally CONST-ness should match. However, this is very hard to achieve
// because we don't know the exact semantics of conflicting (const and
// non-const) multiple variable declarations, const vars introduced via
@@ -180,15 +177,13 @@
}
-ObjectLiteralProperty::ObjectLiteralProperty(
- Zone* zone, Literal* key, Expression* value) {
+ObjectLiteralProperty::ObjectLiteralProperty(Zone* zone,
+ AstValueFactory* ast_value_factory,
+ Literal* key, Expression* value) {
emit_store_ = true;
key_ = key;
value_ = value;
- Handle<Object> k = key->value();
- if (k->IsInternalizedString() &&
- String::Equals(Handle<String>::cast(k),
- zone->isolate()->factory()->proto_string())) {
+ if (key->raw_value()->EqualsString(ast_value_factory->proto_string())) {
kind_ = PROTOTYPE;
} else if (value_->AsMaterializedLiteral() != NULL) {
kind_ = MATERIALIZED_LITERAL;
@@ -1122,9 +1117,8 @@
// optimize them.
add_flag(kDontInline);
} else if (node->function()->intrinsic_type == Runtime::INLINE &&
- (node->name()->IsOneByteEqualTo(
- STATIC_ASCII_VECTOR("_ArgumentsLength")) ||
- node->name()->IsOneByteEqualTo(STATIC_ASCII_VECTOR("_Arguments")))) {
+ (node->raw_name()->IsOneByteEqualTo("_ArgumentsLength") ||
+ node->raw_name()->IsOneByteEqualTo("_Arguments"))) {
// Don't inline the %_ArgumentsLength or %_Arguments because their
// implementation will not work. There is no stack frame to get them
// from.
@@ -1139,17 +1133,17 @@
Handle<String> Literal::ToString() {
- if (value_->IsString()) return Handle<String>::cast(value_);
+ if (value_->IsString()) return value_->AsString()->string();
ASSERT(value_->IsNumber());
char arr[100];
Vector<char> buffer(arr, ARRAY_SIZE(arr));
const char* str;
- if (value_->IsSmi()) {
+ if (value()->IsSmi()) {
// Optimization only, the heap number case would subsume this.
- SNPrintF(buffer, "%d", Smi::cast(*value_)->value());
+ SNPrintF(buffer, "%d", Smi::cast(*value())->value());
str = arr;
} else {
- str = DoubleToCString(value_->Number(), buffer);
+ str = DoubleToCString(value()->Number(), buffer);
}
return isolate_->factory()->NewStringFromAsciiChecked(str);
}
diff --git a/src/ast.h b/src/ast.h
index d56b972..23f9eef 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -8,6 +8,7 @@
#include "src/v8.h"
#include "src/assembler.h"
+#include "src/ast-value-factory.h"
#include "src/factory.h"
#include "src/feedback-slots.h"
#include "src/interface.h"
@@ -367,11 +368,14 @@
protected:
Expression(Zone* zone, int pos)
: AstNode(pos),
+ zone_(zone),
bounds_(Bounds::Unbounded(zone)),
id_(GetNextId(zone)),
test_id_(GetNextId(zone)) {}
void set_to_boolean_types(byte types) { to_boolean_types_ = types; }
+ Zone* zone_;
+
private:
Bounds bounds_;
byte to_boolean_types_;
@@ -390,7 +394,7 @@
// The labels associated with this statement. May be NULL;
// if it is != NULL, guaranteed to contain at least one entry.
- ZoneStringList* labels() const { return labels_; }
+ ZoneList<const AstRawString*>* labels() const { return labels_; }
// Type testing & conversion.
virtual BreakableStatement* AsBreakableStatement() V8_FINAL V8_OVERRIDE {
@@ -410,7 +414,7 @@
protected:
BreakableStatement(
- Zone* zone, ZoneStringList* labels,
+ Zone* zone, ZoneList<const AstRawString*>* labels,
BreakableType breakable_type, int position)
: Statement(zone, position),
labels_(labels),
@@ -422,7 +426,7 @@
private:
- ZoneStringList* labels_;
+ ZoneList<const AstRawString*>* labels_;
BreakableType breakable_type_;
Label break_target_;
const BailoutId entry_id_;
@@ -453,7 +457,7 @@
protected:
Block(Zone* zone,
- ZoneStringList* labels,
+ ZoneList<const AstRawString*>* labels,
int capacity,
bool is_initializer_block,
int pos)
@@ -662,18 +666,15 @@
DECLARE_NODE_TYPE(ModulePath)
Module* module() const { return module_; }
- Handle<String> name() const { return name_; }
+ Handle<String> name() const { return name_->string(); }
protected:
- ModulePath(Zone* zone, Module* module, Handle<String> name, int pos)
- : Module(zone, pos),
- module_(module),
- name_(name) {
- }
+ ModulePath(Zone* zone, Module* module, const AstRawString* name, int pos)
+ : Module(zone, pos), module_(module), name_(name) {}
private:
Module* module_;
- Handle<String> name_;
+ const AstRawString* name_;
};
@@ -730,7 +731,7 @@
Label* continue_target() { return &continue_target_; }
protected:
- IterationStatement(Zone* zone, ZoneStringList* labels, int pos)
+ IterationStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
: BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos),
body_(NULL),
osr_entry_id_(GetNextId(zone)) {
@@ -764,7 +765,7 @@
BailoutId BackEdgeId() const { return back_edge_id_; }
protected:
- DoWhileStatement(Zone* zone, ZoneStringList* labels, int pos)
+ DoWhileStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
: IterationStatement(zone, labels, pos),
cond_(NULL),
continue_id_(GetNextId(zone)),
@@ -801,7 +802,7 @@
BailoutId BodyId() const { return body_id_; }
protected:
- WhileStatement(Zone* zone, ZoneStringList* labels, int pos)
+ WhileStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
: IterationStatement(zone, labels, pos),
cond_(NULL),
may_have_function_literal_(true),
@@ -852,7 +853,7 @@
void set_loop_variable(Variable* var) { loop_variable_ = var; }
protected:
- ForStatement(Zone* zone, ZoneStringList* labels, int pos)
+ ForStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
: IterationStatement(zone, labels, pos),
init_(NULL),
cond_(NULL),
@@ -894,11 +895,8 @@
Expression* subject() const { return subject_; }
protected:
- ForEachStatement(Zone* zone, ZoneStringList* labels, int pos)
- : IterationStatement(zone, labels, pos),
- each_(NULL),
- subject_(NULL) {
- }
+ ForEachStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
+ : IterationStatement(zone, labels, pos), each_(NULL), subject_(NULL) {}
private:
Expression* each_;
@@ -934,7 +932,7 @@
virtual BailoutId StackCheckId() const V8_OVERRIDE { return body_id_; }
protected:
- ForInStatement(Zone* zone, ZoneStringList* labels, int pos)
+ ForInStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
: ForEachStatement(zone, labels, pos),
for_in_type_(SLOW_FOR_IN),
for_in_feedback_slot_(kInvalidFeedbackSlot),
@@ -1004,7 +1002,7 @@
BailoutId BackEdgeId() const { return back_edge_id_; }
protected:
- ForOfStatement(Zone* zone, ZoneStringList* labels, int pos)
+ ForOfStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
: ForEachStatement(zone, labels, pos),
assign_iterator_(NULL),
next_result_(NULL),
@@ -1165,7 +1163,7 @@
ZoneList<CaseClause*>* cases() const { return cases_; }
protected:
- SwitchStatement(Zone* zone, ZoneStringList* labels, int pos)
+ SwitchStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
: BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos),
tag_(NULL),
cases_(NULL) { }
@@ -1345,26 +1343,28 @@
DECLARE_NODE_TYPE(Literal)
virtual bool IsPropertyName() const V8_OVERRIDE {
- if (value_->IsInternalizedString()) {
- uint32_t ignored;
- return !String::cast(*value_)->AsArrayIndex(&ignored);
- }
- return false;
+ return value_->IsPropertyName();
}
Handle<String> AsPropertyName() {
ASSERT(IsPropertyName());
- return Handle<String>::cast(value_);
+ return Handle<String>::cast(value());
+ }
+
+ const AstRawString* AsRawPropertyName() {
+ ASSERT(IsPropertyName());
+ return value_->AsString();
}
virtual bool ToBooleanIsTrue() const V8_OVERRIDE {
- return value_->BooleanValue();
+ return value()->BooleanValue();
}
virtual bool ToBooleanIsFalse() const V8_OVERRIDE {
- return !value_->BooleanValue();
+ return !value()->BooleanValue();
}
- Handle<Object> value() const { return value_; }
+ Handle<Object> value() const { return value_->value(); }
+ const AstValue* raw_value() const { return value_; }
// Support for using Literal as a HashMap key. NOTE: Currently, this works
// only for string and number literals!
@@ -1379,7 +1379,7 @@
TypeFeedbackId LiteralFeedbackId() const { return reuse(id()); }
protected:
- Literal(Zone* zone, Handle<Object> value, int position)
+ Literal(Zone* zone, const AstValue* value, int position)
: Expression(zone, position),
value_(value),
isolate_(zone->isolate()) { }
@@ -1387,7 +1387,7 @@
private:
Handle<String> ToString();
- Handle<Object> value_;
+ const AstValue* value_;
// TODO(dcarney): remove. this is only needed for Match and Hash.
Isolate* isolate_;
};
@@ -1458,7 +1458,8 @@
PROTOTYPE // Property is __proto__.
};
- ObjectLiteralProperty(Zone* zone, Literal* key, Expression* value);
+ ObjectLiteralProperty(Zone* zone, AstValueFactory* ast_value_factory,
+ Literal* key, Expression* value);
Literal* key() { return key_; }
Expression* value() { return value_; }
@@ -1557,13 +1558,13 @@
public:
DECLARE_NODE_TYPE(RegExpLiteral)
- Handle<String> pattern() const { return pattern_; }
- Handle<String> flags() const { return flags_; }
+ Handle<String> pattern() const { return pattern_->string(); }
+ Handle<String> flags() const { return flags_->string(); }
protected:
RegExpLiteral(Zone* zone,
- Handle<String> pattern,
- Handle<String> flags,
+ const AstRawString* pattern,
+ const AstRawString* flags,
int literal_index,
int pos)
: MaterializedLiteral(zone, literal_index, pos),
@@ -1573,8 +1574,8 @@
}
private:
- Handle<String> pattern_;
- Handle<String> flags_;
+ const AstRawString* pattern_;
+ const AstRawString* flags_;
};
@@ -1625,15 +1626,12 @@
return var_ == NULL ? true : var_->IsValidReference();
}
- bool IsVariable(Handle<String> n) const {
- return !is_this() && name().is_identical_to(n);
- }
-
bool IsArguments() const { return var_ != NULL && var_->is_arguments(); }
bool IsLValue() const { return is_lvalue_; }
- Handle<String> name() const { return name_; }
+ Handle<String> name() const { return name_->string(); }
+ const AstRawString* raw_name() const { return name_; }
Variable* var() const { return var_; }
bool is_this() const { return is_this_; }
Interface* interface() const { return interface_; }
@@ -1649,12 +1647,12 @@
VariableProxy(Zone* zone, Variable* var, int position);
VariableProxy(Zone* zone,
- Handle<String> name,
+ const AstRawString* name,
bool is_this,
Interface* interface,
int position);
- Handle<String> name_;
+ const AstRawString* name_;
Variable* var_; // resolved variable, or NULL
bool is_this_;
bool is_trivial_;
@@ -1900,7 +1898,8 @@
public:
DECLARE_NODE_TYPE(CallRuntime)
- Handle<String> name() const { return name_; }
+ Handle<String> name() const { return raw_name_->string(); }
+ const AstRawString* raw_name() const { return raw_name_; }
const Runtime::Function* function() const { return function_; }
ZoneList<Expression*>* arguments() const { return arguments_; }
bool is_jsruntime() const { return function_ == NULL; }
@@ -1909,17 +1908,17 @@
protected:
CallRuntime(Zone* zone,
- Handle<String> name,
+ const AstRawString* name,
const Runtime::Function* function,
ZoneList<Expression*>* arguments,
int pos)
: Expression(zone, pos),
- name_(name),
+ raw_name_(name),
function_(function),
arguments_(arguments) { }
private:
- Handle<String> name_;
+ const AstRawString* raw_name_;
const Runtime::Function* function_;
ZoneList<Expression*>* arguments_;
};
@@ -2313,7 +2312,8 @@
DECLARE_NODE_TYPE(FunctionLiteral)
- Handle<String> name() const { return name_; }
+ Handle<String> name() const { return raw_name_->string(); }
+ const AstRawString* raw_name() const { return raw_name_; }
Scope* scope() const { return scope_; }
ZoneList<Statement*>* body() const { return body_; }
void set_function_token_position(int pos) { function_token_position_ = pos; }
@@ -2336,13 +2336,37 @@
void InitializeSharedInfo(Handle<Code> code);
Handle<String> debug_name() const {
- if (name_->length() > 0) return name_;
+ if (raw_name_ != NULL && !raw_name_->IsEmpty()) {
+ return raw_name_->string();
+ }
return inferred_name();
}
- Handle<String> inferred_name() const { return inferred_name_; }
+ Handle<String> inferred_name() const {
+ if (!inferred_name_.is_null()) {
+ ASSERT(raw_inferred_name_ == NULL);
+ return inferred_name_;
+ }
+ if (raw_inferred_name_ != NULL) {
+ return raw_inferred_name_->string();
+ }
+ UNREACHABLE();
+ return Handle<String>();
+ }
+
+ // Only one of {set_inferred_name, set_raw_inferred_name} should be called.
void set_inferred_name(Handle<String> inferred_name) {
+ ASSERT(!inferred_name.is_null());
inferred_name_ = inferred_name;
+ ASSERT(raw_inferred_name_== NULL || raw_inferred_name_->IsEmpty());
+ raw_inferred_name_ = NULL;
+ }
+
+ void set_raw_inferred_name(const AstString* raw_inferred_name) {
+ ASSERT(raw_inferred_name != NULL);
+ raw_inferred_name_ = raw_inferred_name;
+ ASSERT(inferred_name_.is_null());
+ inferred_name_ = Handle<String>();
}
// shared_info may be null if it's not cached in full code.
@@ -2389,7 +2413,8 @@
protected:
FunctionLiteral(Zone* zone,
- Handle<String> name,
+ const AstRawString* name,
+ AstValueFactory* ast_value_factory,
Scope* scope,
ZoneList<Statement*>* body,
int materialized_literal_count,
@@ -2403,10 +2428,10 @@
IsGeneratorFlag is_generator,
int position)
: Expression(zone, position),
- name_(name),
+ raw_name_(name),
scope_(scope),
body_(body),
- inferred_name_(zone->isolate()->factory()->empty_string()),
+ raw_inferred_name_(ast_value_factory->empty_string()),
dont_optimize_reason_(kNoReason),
materialized_literal_count_(materialized_literal_count),
expected_property_count_(expected_property_count),
@@ -2424,10 +2449,12 @@
}
private:
+ const AstRawString* raw_name_;
Handle<String> name_;
Handle<SharedFunctionInfo> shared_info_;
Scope* scope_;
ZoneList<Statement*>* body_;
+ const AstString* raw_inferred_name_;
Handle<String> inferred_name_;
AstProperties ast_properties_;
BailoutReason dont_optimize_reason_;
@@ -2453,16 +2480,16 @@
public:
DECLARE_NODE_TYPE(NativeFunctionLiteral)
- Handle<String> name() const { return name_; }
+ Handle<String> name() const { return name_->string(); }
v8::Extension* extension() const { return extension_; }
protected:
- NativeFunctionLiteral(
- Zone* zone, Handle<String> name, v8::Extension* extension, int pos)
+ NativeFunctionLiteral(Zone* zone, const AstRawString* name,
+ v8::Extension* extension, int pos)
: Expression(zone, pos), name_(name), extension_(extension) {}
private:
- Handle<String> name_;
+ const AstRawString* name_;
v8::Extension* extension_;
};
@@ -2954,7 +2981,8 @@
template<class Visitor>
class AstNodeFactory V8_FINAL BASE_EMBEDDED {
public:
- explicit AstNodeFactory(Zone* zone) : zone_(zone) { }
+ explicit AstNodeFactory(Zone* zone, AstValueFactory* ast_value_factory)
+ : zone_(zone), ast_value_factory_(ast_value_factory) {}
Visitor* visitor() { return &visitor_; }
@@ -3018,8 +3046,8 @@
VISIT_AND_RETURN(ModuleVariable, module)
}
- ModulePath* NewModulePath(Module* origin, Handle<String> name, int pos) {
- ModulePath* module = new(zone_) ModulePath(zone_, origin, name, pos);
+ ModulePath* NewModulePath(Module* origin, const AstRawString* name, int pos) {
+ ModulePath* module = new (zone_) ModulePath(zone_, origin, name, pos);
VISIT_AND_RETURN(ModulePath, module)
}
@@ -3028,7 +3056,7 @@
VISIT_AND_RETURN(ModuleUrl, module)
}
- Block* NewBlock(ZoneStringList* labels,
+ Block* NewBlock(ZoneList<const AstRawString*>* labels,
int capacity,
bool is_initializer_block,
int pos) {
@@ -3038,7 +3066,7 @@
}
#define STATEMENT_WITH_LABELS(NodeType) \
- NodeType* New##NodeType(ZoneStringList* labels, int pos) { \
+ NodeType* New##NodeType(ZoneList<const AstRawString*>* labels, int pos) { \
NodeType* stmt = new(zone_) NodeType(zone_, labels, pos); \
VISIT_AND_RETURN(NodeType, stmt); \
}
@@ -3049,7 +3077,7 @@
#undef STATEMENT_WITH_LABELS
ForEachStatement* NewForEachStatement(ForEachStatement::VisitMode visit_mode,
- ZoneStringList* labels,
+ ZoneList<const AstRawString*>* labels,
int pos) {
switch (visit_mode) {
case ForEachStatement::ENUMERATE: {
@@ -3146,14 +3174,60 @@
VISIT_AND_RETURN(CaseClause, clause)
}
- Literal* NewLiteral(Handle<Object> handle, int pos) {
- Literal* lit = new(zone_) Literal(zone_, handle, pos);
+ Literal* NewStringLiteral(const AstRawString* string, int pos) {
+ Literal* lit =
+ new (zone_) Literal(zone_, ast_value_factory_->NewString(string), pos);
+ VISIT_AND_RETURN(Literal, lit)
+ }
+
+ // A JavaScript symbol (ECMA-262 edition 6).
+ Literal* NewSymbolLiteral(const char* name, int pos) {
+ Literal* lit =
+ new (zone_) Literal(zone_, ast_value_factory_->NewSymbol(name), pos);
VISIT_AND_RETURN(Literal, lit)
}
Literal* NewNumberLiteral(double number, int pos) {
- return NewLiteral(
- zone_->isolate()->factory()->NewNumber(number, TENURED), pos);
+ Literal* lit = new (zone_)
+ Literal(zone_, ast_value_factory_->NewNumber(number), pos);
+ VISIT_AND_RETURN(Literal, lit)
+ }
+
+ Literal* NewSmiLiteral(int number, int pos) {
+ Literal* lit =
+ new (zone_) Literal(zone_, ast_value_factory_->NewSmi(number), pos);
+ VISIT_AND_RETURN(Literal, lit)
+ }
+
+ Literal* NewBooleanLiteral(bool b, int pos) {
+ Literal* lit =
+ new (zone_) Literal(zone_, ast_value_factory_->NewBoolean(b), pos);
+ VISIT_AND_RETURN(Literal, lit)
+ }
+
+ Literal* NewStringListLiteral(ZoneList<const AstRawString*>* strings,
+ int pos) {
+ Literal* lit = new (zone_)
+ Literal(zone_, ast_value_factory_->NewStringList(strings), pos);
+ VISIT_AND_RETURN(Literal, lit)
+ }
+
+ Literal* NewNullLiteral(int pos) {
+ Literal* lit =
+ new (zone_) Literal(zone_, ast_value_factory_->NewNull(), pos);
+ VISIT_AND_RETURN(Literal, lit)
+ }
+
+ Literal* NewUndefinedLiteral(int pos) {
+ Literal* lit =
+ new (zone_) Literal(zone_, ast_value_factory_->NewUndefined(), pos);
+ VISIT_AND_RETURN(Literal, lit)
+ }
+
+ Literal* NewTheHoleLiteral(int pos) {
+ Literal* lit =
+ new (zone_) Literal(zone_, ast_value_factory_->NewTheHole(), pos);
+ VISIT_AND_RETURN(Literal, lit)
}
ObjectLiteral* NewObjectLiteral(
@@ -3170,7 +3244,8 @@
ObjectLiteral::Property* NewObjectLiteralProperty(Literal* key,
Expression* value) {
- return new(zone_) ObjectLiteral::Property(zone_, key, value);
+ return new (zone_)
+ ObjectLiteral::Property(zone_, ast_value_factory_, key, value);
}
ObjectLiteral::Property* NewObjectLiteralProperty(bool is_getter,
@@ -3178,12 +3253,12 @@
int pos) {
ObjectLiteral::Property* prop =
new(zone_) ObjectLiteral::Property(zone_, is_getter, value);
- prop->set_key(NewLiteral(value->name(), pos));
+ prop->set_key(NewStringLiteral(value->raw_name(), pos));
return prop; // Not an AST node, will not be visited.
}
- RegExpLiteral* NewRegExpLiteral(Handle<String> pattern,
- Handle<String> flags,
+ RegExpLiteral* NewRegExpLiteral(const AstRawString* pattern,
+ const AstRawString* flags,
int literal_index,
int pos) {
RegExpLiteral* lit =
@@ -3205,7 +3280,7 @@
VISIT_AND_RETURN(VariableProxy, proxy)
}
- VariableProxy* NewVariableProxy(Handle<String> name,
+ VariableProxy* NewVariableProxy(const AstRawString* name,
bool is_this,
Interface* interface = Interface::NewValue(),
int position = RelocInfo::kNoPosition) {
@@ -3233,7 +3308,7 @@
VISIT_AND_RETURN(CallNew, call)
}
- CallRuntime* NewCallRuntime(Handle<String> name,
+ CallRuntime* NewCallRuntime(const AstRawString* name,
const Runtime::Function* function,
ZoneList<Expression*>* arguments,
int pos) {
@@ -3311,7 +3386,8 @@
}
FunctionLiteral* NewFunctionLiteral(
- Handle<String> name,
+ const AstRawString* name,
+ AstValueFactory* ast_value_factory,
Scope* scope,
ZoneList<Statement*>* body,
int materialized_literal_count,
@@ -3325,7 +3401,7 @@
FunctionLiteral::IsGeneratorFlag is_generator,
int position) {
FunctionLiteral* lit = new(zone_) FunctionLiteral(
- zone_, name, scope, body,
+ zone_, name, ast_value_factory, scope, body,
materialized_literal_count, expected_property_count, handler_count,
parameter_count, function_type, has_duplicate_parameters, is_function,
is_parenthesized, is_generator, position);
@@ -3337,7 +3413,8 @@
}
NativeFunctionLiteral* NewNativeFunctionLiteral(
- Handle<String> name, v8::Extension* extension, int pos) {
+ const AstRawString* name, v8::Extension* extension,
+ int pos) {
NativeFunctionLiteral* lit =
new(zone_) NativeFunctionLiteral(zone_, name, extension, pos);
VISIT_AND_RETURN(NativeFunctionLiteral, lit)
@@ -3353,6 +3430,7 @@
private:
Zone* zone_;
Visitor visitor_;
+ AstValueFactory* ast_value_factory_;
};
diff --git a/src/base/build_config.h b/src/base/build_config.h
index e412b92d..bdee4b4 100644
--- a/src/base/build_config.h
+++ b/src/base/build_config.h
@@ -24,7 +24,11 @@
#define V8_HOST_CAN_READ_UNALIGNED 1
#else
#define V8_HOST_ARCH_X64 1
+#if defined(__x86_64__) && !defined(__LP64__)
+#define V8_HOST_ARCH_32_BIT 1
+#else
#define V8_HOST_ARCH_64_BIT 1
+#endif
#define V8_HOST_CAN_READ_UNALIGNED 1
#endif // __native_client__
#elif defined(_M_IX86) || defined(__i386__)
@@ -75,13 +79,41 @@
#endif
#endif
+// Determine architecture pointer size.
+#if V8_TARGET_ARCH_IA32
+#define V8_TARGET_ARCH_32_BIT 1
+#elif V8_TARGET_ARCH_X64
+#if !V8_TARGET_ARCH_32_BIT && !V8_TARGET_ARCH_64_BIT
+#if defined(__x86_64__) && !defined(__LP64__)
+#define V8_TARGET_ARCH_32_BIT 1
+#else
+#define V8_TARGET_ARCH_64_BIT 1
+#endif
+#endif
+#elif V8_TARGET_ARCH_ARM
+#define V8_TARGET_ARCH_32_BIT 1
+#elif V8_TARGET_ARCH_ARM64
+#define V8_TARGET_ARCH_64_BIT 1
+#elif V8_TARGET_ARCH_MIPS
+#define V8_TARGET_ARCH_32_BIT 1
+#elif V8_TARGET_ARCH_X87
+#define V8_TARGET_ARCH_32_BIT 1
+#else
+#error Unknown target architecture pointer size
+#endif
+
// Check for supported combinations of host and target architectures.
#if V8_TARGET_ARCH_IA32 && !V8_HOST_ARCH_IA32
#error Target architecture ia32 is only supported on ia32 host
#endif
-#if V8_TARGET_ARCH_X64 && !V8_HOST_ARCH_X64
+#if (V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT && \
+ !(V8_HOST_ARCH_X64 && V8_HOST_ARCH_64_BIT))
#error Target architecture x64 is only supported on x64 host
#endif
+#if (V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT && \
+ !(V8_HOST_ARCH_X64 && V8_HOST_ARCH_32_BIT))
+#error Target architecture x32 is only supported on x64 host with x32 support
+#endif
#if (V8_TARGET_ARCH_ARM && !(V8_HOST_ARCH_IA32 || V8_HOST_ARCH_ARM))
#error Target architecture arm is only supported on arm and ia32 host
#endif
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 7dc4100..771b5b2 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -342,10 +342,10 @@
static void SetObjectPrototype(Handle<JSObject> object, Handle<Object> proto) {
// object.__proto__ = proto;
- Handle<Map> old_to_map = Handle<Map>(object->map());
- Handle<Map> new_to_map = Map::Copy(old_to_map);
- new_to_map->set_prototype(*proto);
- object->set_map(*new_to_map);
+ Handle<Map> old_map = Handle<Map>(object->map());
+ Handle<Map> new_map = Map::Copy(old_map);
+ new_map->set_prototype(*proto);
+ JSObject::MigrateToMap(object, new_map);
}
@@ -2540,10 +2540,8 @@
TransferIndexedProperties(from, to);
// Transfer the prototype (new map is needed).
- Handle<Map> old_to_map = Handle<Map>(to->map());
- Handle<Map> new_to_map = Map::Copy(old_to_map);
- new_to_map->set_prototype(from->map()->prototype());
- to->set_map(*new_to_map);
+ Handle<Object> proto(from->map()->prototype(), isolate());
+ SetObjectPrototype(to, proto);
}
diff --git a/src/collection.js b/src/collection.js
index a1342a3..8ddf8e1 100644
--- a/src/collection.js
+++ b/src/collection.js
@@ -12,15 +12,64 @@
var $Map = global.Map;
+// TODO(arv): Move these general functions to v8natives.js when Map and Set are
+// no longer experimental.
+
+
+// 7.4.1 CheckIterable ( obj )
+function ToIterable(obj) {
+ if (!IS_SPEC_OBJECT(obj)) {
+ return UNDEFINED;
+ }
+ return obj[symbolIterator];
+}
+
+
+// 7.4.2 GetIterator ( obj, method )
+function GetIterator(obj, method) {
+ if (IS_UNDEFINED(method)) {
+ method = ToIterable(obj);
+ }
+ if (!IS_SPEC_FUNCTION(method)) {
+ throw MakeTypeError('not_iterable', [obj]);
+ }
+ var iterator = %_CallFunction(obj, method);
+ if (!IS_SPEC_OBJECT(iterator)) {
+ throw MakeTypeError('not_an_iterator', [iterator]);
+ }
+ return iterator;
+}
+
+
// -------------------------------------------------------------------
// Harmony Set
-function SetConstructor() {
- if (%_IsConstructCall()) {
- %SetInitialize(this);
- } else {
+function SetConstructor(iterable) {
+ if (!%_IsConstructCall()) {
throw MakeTypeError('constructor_not_function', ['Set']);
}
+
+ var iter, adder;
+
+ if (!IS_NULL_OR_UNDEFINED(iterable)) {
+ iter = GetIterator(iterable);
+ adder = this.add;
+ if (!IS_SPEC_FUNCTION(adder)) {
+ throw MakeTypeError('property_not_function', ['add', this]);
+ }
+ }
+
+ %SetInitialize(this);
+
+ if (IS_UNDEFINED(iter)) return;
+
+ var next, done;
+ while (!(next = iter.next()).done) {
+ if (!IS_SPEC_OBJECT(next)) {
+ throw MakeTypeError('iterator_result_not_an_object', [next]);
+ }
+ %_CallFunction(this, next.value, adder);
+ }
}
@@ -117,12 +166,36 @@
// -------------------------------------------------------------------
// Harmony Map
-function MapConstructor() {
- if (%_IsConstructCall()) {
- %MapInitialize(this);
- } else {
+function MapConstructor(iterable) {
+ if (!%_IsConstructCall()) {
throw MakeTypeError('constructor_not_function', ['Map']);
}
+
+ var iter, adder;
+
+ if (!IS_NULL_OR_UNDEFINED(iterable)) {
+ iter = GetIterator(iterable);
+ adder = this.set;
+ if (!IS_SPEC_FUNCTION(adder)) {
+ throw MakeTypeError('property_not_function', ['set', this]);
+ }
+ }
+
+ %MapInitialize(this);
+
+ if (IS_UNDEFINED(iter)) return;
+
+ var next, done, nextItem;
+ while (!(next = iter.next()).done) {
+ if (!IS_SPEC_OBJECT(next)) {
+ throw MakeTypeError('iterator_result_not_an_object', [next]);
+ }
+ nextItem = next.value;
+ if (!IS_SPEC_OBJECT(nextItem)) {
+ throw MakeTypeError('iterator_value_not_an_object', [nextItem]);
+ }
+ %_CallFunction(this, nextItem[0], nextItem[1], adder);
+ }
}
diff --git a/src/compiler.cc b/src/compiler.cc
index 1d6fb1f..d9fb4a9 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -38,7 +38,9 @@
osr_ast_id_(BailoutId::None()),
parameter_count_(0),
this_has_uses_(true),
- optimization_id_(-1) {
+ optimization_id_(-1),
+ ast_value_factory_(NULL),
+ ast_value_factory_owned_(false) {
Initialize(script->GetIsolate(), BASE, zone);
}
@@ -51,7 +53,9 @@
osr_ast_id_(BailoutId::None()),
parameter_count_(0),
this_has_uses_(true),
- optimization_id_(-1) {
+ optimization_id_(-1),
+ ast_value_factory_(NULL),
+ ast_value_factory_owned_(false) {
Initialize(script_->GetIsolate(), BASE, zone);
}
@@ -66,7 +70,9 @@
osr_ast_id_(BailoutId::None()),
parameter_count_(0),
this_has_uses_(true),
- optimization_id_(-1) {
+ optimization_id_(-1),
+ ast_value_factory_(NULL),
+ ast_value_factory_owned_(false) {
Initialize(script_->GetIsolate(), BASE, zone);
}
@@ -78,7 +84,9 @@
osr_ast_id_(BailoutId::None()),
parameter_count_(0),
this_has_uses_(true),
- optimization_id_(-1) {
+ optimization_id_(-1),
+ ast_value_factory_(NULL),
+ ast_value_factory_owned_(false) {
Initialize(isolate, STUB, zone);
code_stub_ = stub;
}
@@ -131,6 +139,7 @@
CompilationInfo::~CompilationInfo() {
delete deferred_handles_;
delete no_frame_ranges_;
+ if (ast_value_factory_owned_) delete ast_value_factory_;
#ifdef DEBUG
// Check that no dependent maps have been added or added dependent maps have
// been rolled back or committed.
diff --git a/src/compiler.h b/src/compiler.h
index 6531474..fdb7900 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -12,6 +12,7 @@
namespace v8 {
namespace internal {
+class AstValueFactory;
class ScriptData;
class HydrogenCodeStub;
@@ -321,6 +322,13 @@
int optimization_id() const { return optimization_id_; }
+ AstValueFactory* ast_value_factory() const { return ast_value_factory_; }
+ void SetAstValueFactory(AstValueFactory* ast_value_factory,
+ bool owned = true) {
+ ast_value_factory_ = ast_value_factory;
+ ast_value_factory_owned_ = owned;
+ }
+
protected:
CompilationInfo(Handle<Script> script,
Zone* zone);
@@ -464,6 +472,9 @@
int optimization_id_;
+ AstValueFactory* ast_value_factory_;
+ bool ast_value_factory_owned_;
+
DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
};
diff --git a/src/execution.h b/src/execution.h
index 74d0feb..81fbbb8 100644
--- a/src/execution.h
+++ b/src/execution.h
@@ -227,7 +227,7 @@
void EnableInterrupts();
void DisableInterrupts();
-#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64
+#if V8_TARGET_ARCH_64_BIT
static const uintptr_t kInterruptLimit = V8_UINT64_C(0xfffffffffffffffe);
static const uintptr_t kIllegalLimit = V8_UINT64_C(0xfffffffffffffff8);
#else
diff --git a/src/factory.cc b/src/factory.cc
index 1996e73..6618357 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -1818,8 +1818,15 @@
// before object re-initialization is finished and filler object is installed.
DisallowHeapAllocation no_allocation;
+ // Put in filler if the new object is smaller than the old.
+ if (size_difference > 0) {
+ Address address = object->address() + map->instance_size();
+ heap->CreateFillerObjectAt(address, size_difference);
+ heap->AdjustLiveBytes(address, -size_difference, Heap::FROM_MUTATOR);
+ }
+
// Reset the map for the object.
- object->set_map(*map);
+ object->synchronized_set_map(*map);
Handle<JSObject> jsobj = Handle<JSObject>::cast(object);
// Reinitialize the object from the constructor map.
@@ -1832,12 +1839,6 @@
Handle<Context> context(isolate()->context()->native_context());
InitializeFunction(js_function, shared.ToHandleChecked(), context);
}
-
- // Put in filler if the new object is smaller than the old.
- if (size_difference > 0) {
- heap->CreateFillerObjectAt(
- object->address() + map->instance_size(), size_difference);
- }
}
@@ -1863,7 +1864,7 @@
DisallowHeapAllocation no_allocation;
// Reset the map for the object.
- object->set_map(constructor->initial_map());
+ object->synchronized_set_map(*map);
Heap* heap = isolate()->heap();
// Reinitialize the object from the constructor map.
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index 32241c2..088a9c9 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -328,7 +328,6 @@
code->set_allow_osr_at_loop_nesting_level(0);
code->set_profiler_ticks(0);
code->set_back_edge_table_offset(table_offset);
- code->set_back_edges_patched_for_osr(false);
CodeGenerator::PrintCode(code, info);
info->SetCode(code);
#ifdef ENABLE_GDB_JIT_INTERFACE
@@ -348,7 +347,7 @@
// The back edge table consists of a length (in number of entries)
// field, and then a sequence of entries. Each entry is a pair of AST id
// and code-relative pc offset.
- masm()->Align(kIntSize);
+ masm()->Align(kPointerSize);
unsigned offset = masm()->pc_offset();
unsigned length = back_edges_.length();
__ dd(length);
@@ -1617,9 +1616,11 @@
DisallowHeapAllocation no_gc;
Code* patch = isolate->builtins()->builtin(Builtins::kOnStackReplacement);
- // Iterate over the back edge table and patch every interrupt
+ // Increment loop nesting level by one and iterate over the back edge table
+ // to find the matching loops to patch the interrupt
// call to an unconditional call to the replacement code.
- int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level();
+ int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level() + 1;
+ if (loop_nesting_level > Code::kMaxLoopNestingMarker) return;
BackEdgeTable back_edges(unoptimized, &no_gc);
for (uint32_t i = 0; i < back_edges.length(); i++) {
@@ -1631,8 +1632,8 @@
}
}
- unoptimized->set_back_edges_patched_for_osr(true);
- ASSERT(Verify(isolate, unoptimized, loop_nesting_level));
+ unoptimized->set_allow_osr_at_loop_nesting_level(loop_nesting_level);
+ ASSERT(Verify(isolate, unoptimized));
}
@@ -1641,7 +1642,6 @@
Code* patch = isolate->builtins()->builtin(Builtins::kInterruptCheck);
// Iterate over the back edge table and revert the patched interrupt calls.
- ASSERT(unoptimized->back_edges_patched_for_osr());
int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level();
BackEdgeTable back_edges(unoptimized, &no_gc);
@@ -1654,10 +1654,9 @@
}
}
- unoptimized->set_back_edges_patched_for_osr(false);
unoptimized->set_allow_osr_at_loop_nesting_level(0);
// Assert that none of the back edges are patched anymore.
- ASSERT(Verify(isolate, unoptimized, -1));
+ ASSERT(Verify(isolate, unoptimized));
}
@@ -1683,10 +1682,9 @@
#ifdef DEBUG
-bool BackEdgeTable::Verify(Isolate* isolate,
- Code* unoptimized,
- int loop_nesting_level) {
+bool BackEdgeTable::Verify(Isolate* isolate, Code* unoptimized) {
DisallowHeapAllocation no_gc;
+ int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level();
BackEdgeTable back_edges(unoptimized, &no_gc);
for (uint32_t i = 0; i < back_edges.length(); i++) {
uint32_t loop_depth = back_edges.loop_depth(i);
diff --git a/src/full-codegen.h b/src/full-codegen.h
index bd6aa13..cede9ac 100644
--- a/src/full-codegen.h
+++ b/src/full-codegen.h
@@ -890,10 +890,8 @@
OSR_AFTER_STACK_CHECK
};
- // Patch all interrupts with allowed loop depth in the unoptimized code to
- // unconditionally call replacement_code.
- static void Patch(Isolate* isolate,
- Code* unoptimized_code);
+ // Increase allowed loop nesting level by one and patch those matching loops.
+ static void Patch(Isolate* isolate, Code* unoptimized_code);
// Patch the back edge to the target state, provided the correct callee.
static void PatchAt(Code* unoptimized_code,
@@ -919,9 +917,7 @@
#ifdef DEBUG
// Verify that all back edges of a certain loop depth are patched.
- static bool Verify(Isolate* isolate,
- Code* unoptimized_code,
- int loop_nesting_level);
+ static bool Verify(Isolate* isolate, Code* unoptimized_code);
#endif // DEBUG
private:
diff --git a/src/func-name-inferrer.cc b/src/func-name-inferrer.cc
index a3c2f08..b3a64b2 100644
--- a/src/func-name-inferrer.cc
+++ b/src/func-name-inferrer.cc
@@ -5,14 +5,16 @@
#include "src/v8.h"
#include "src/ast.h"
+#include "src/ast-value-factory.h"
#include "src/func-name-inferrer.h"
#include "src/list-inl.h"
namespace v8 {
namespace internal {
-FuncNameInferrer::FuncNameInferrer(Isolate* isolate, Zone* zone)
- : isolate_(isolate),
+FuncNameInferrer::FuncNameInferrer(AstValueFactory* ast_value_factory,
+ Zone* zone)
+ : ast_value_factory_(ast_value_factory),
entries_stack_(10, zone),
names_stack_(5, zone),
funcs_to_infer_(4, zone),
@@ -20,40 +22,36 @@
}
-void FuncNameInferrer::PushEnclosingName(Handle<String> name) {
+void FuncNameInferrer::PushEnclosingName(const AstRawString* name) {
// Enclosing name is a name of a constructor function. To check
// that it is really a constructor, we check that it is not empty
// and starts with a capital letter.
- if (name->length() > 0 && Runtime::IsUpperCaseChar(
- isolate()->runtime_state(), name->Get(0))) {
+ if (!name->IsEmpty() && unibrow::Uppercase::Is(name->FirstCharacter())) {
names_stack_.Add(Name(name, kEnclosingConstructorName), zone());
}
}
-void FuncNameInferrer::PushLiteralName(Handle<String> name) {
- if (IsOpen() &&
- !String::Equals(isolate()->factory()->prototype_string(), name)) {
+void FuncNameInferrer::PushLiteralName(const AstRawString* name) {
+ if (IsOpen() && name != ast_value_factory_->prototype_string()) {
names_stack_.Add(Name(name, kLiteralName), zone());
}
}
-void FuncNameInferrer::PushVariableName(Handle<String> name) {
- if (IsOpen() &&
- !String::Equals(isolate()->factory()->dot_result_string(), name)) {
+void FuncNameInferrer::PushVariableName(const AstRawString* name) {
+ if (IsOpen() && name != ast_value_factory_->dot_result_string()) {
names_stack_.Add(Name(name, kVariableName), zone());
}
}
-Handle<String> FuncNameInferrer::MakeNameFromStack() {
- return MakeNameFromStackHelper(0, isolate()->factory()->empty_string());
+const AstString* FuncNameInferrer::MakeNameFromStack() {
+ return MakeNameFromStackHelper(0, ast_value_factory_->empty_string());
}
-
-Handle<String> FuncNameInferrer::MakeNameFromStackHelper(int pos,
- Handle<String> prev) {
+const AstString* FuncNameInferrer::MakeNameFromStackHelper(
+ int pos, const AstString* prev) {
if (pos >= names_stack_.length()) return prev;
if (pos < names_stack_.length() - 1 &&
names_stack_.at(pos).type == kVariableName &&
@@ -62,12 +60,11 @@
return MakeNameFromStackHelper(pos + 1, prev);
} else {
if (prev->length() > 0) {
- Handle<String> name = names_stack_.at(pos).name;
+ const AstRawString* name = names_stack_.at(pos).name;
if (prev->length() + name->length() + 1 > String::kMaxLength) return prev;
- Factory* factory = isolate()->factory();
- Handle<String> curr =
- factory->NewConsString(factory->dot_string(), name).ToHandleChecked();
- curr = factory->NewConsString(prev, curr).ToHandleChecked();
+ const AstConsString* curr = ast_value_factory_->NewConsString(
+ ast_value_factory_->dot_string(), name);
+ curr = ast_value_factory_->NewConsString(prev, curr);
return MakeNameFromStackHelper(pos + 1, curr);
} else {
return MakeNameFromStackHelper(pos + 1, names_stack_.at(pos).name);
@@ -77,9 +74,9 @@
void FuncNameInferrer::InferFunctionsNames() {
- Handle<String> func_name = MakeNameFromStack();
+ const AstString* func_name = MakeNameFromStack();
for (int i = 0; i < funcs_to_infer_.length(); ++i) {
- funcs_to_infer_[i]->set_inferred_name(func_name);
+ funcs_to_infer_[i]->set_raw_inferred_name(func_name);
}
funcs_to_infer_.Rewind(0);
}
diff --git a/src/func-name-inferrer.h b/src/func-name-inferrer.h
index 0c5399c..43ef761 100644
--- a/src/func-name-inferrer.h
+++ b/src/func-name-inferrer.h
@@ -11,8 +11,10 @@
namespace v8 {
namespace internal {
+class AstRawString;
+class AstString;
+class AstValueFactory;
class FunctionLiteral;
-class Isolate;
// FuncNameInferrer is a stateful class that is used to perform name
// inference for anonymous functions during static analysis of source code.
@@ -26,13 +28,13 @@
// a name.
class FuncNameInferrer : public ZoneObject {
public:
- FuncNameInferrer(Isolate* isolate, Zone* zone);
+ FuncNameInferrer(AstValueFactory* ast_value_factory, Zone* zone);
// Returns whether we have entered name collection state.
bool IsOpen() const { return !entries_stack_.is_empty(); }
// Pushes an enclosing the name of enclosing function onto names stack.
- void PushEnclosingName(Handle<String> name);
+ void PushEnclosingName(const AstRawString* name);
// Enters name collection state.
void Enter() {
@@ -40,9 +42,9 @@
}
// Pushes an encountered name onto names stack when in collection state.
- void PushLiteralName(Handle<String> name);
+ void PushLiteralName(const AstRawString* name);
- void PushVariableName(Handle<String> name);
+ void PushVariableName(const AstRawString* name);
// Adds a function to infer name for.
void AddFunction(FunctionLiteral* func_to_infer) {
@@ -80,24 +82,24 @@
kVariableName
};
struct Name {
- Name(Handle<String> name, NameType type) : name(name), type(type) { }
- Handle<String> name;
+ Name(const AstRawString* name, NameType type) : name(name), type(type) {}
+ const AstRawString* name;
NameType type;
};
- Isolate* isolate() { return isolate_; }
Zone* zone() const { return zone_; }
// Constructs a full name in dotted notation from gathered names.
- Handle<String> MakeNameFromStack();
+ const AstString* MakeNameFromStack();
// A helper function for MakeNameFromStack.
- Handle<String> MakeNameFromStackHelper(int pos, Handle<String> prev);
+ const AstString* MakeNameFromStackHelper(int pos,
+ const AstString* prev);
// Performs name inferring for added functions.
void InferFunctionsNames();
- Isolate* isolate_;
+ AstValueFactory* ast_value_factory_;
ZoneList<int> entries_stack_;
ZoneList<Name> names_stack_;
ZoneList<FunctionLiteral*> funcs_to_infer_;
diff --git a/src/gdb-jit.cc b/src/gdb-jit.cc
index 20e3f2a..09da388 100644
--- a/src/gdb-jit.cc
+++ b/src/gdb-jit.cc
@@ -649,10 +649,11 @@
void WriteHeader(Writer* w) {
ASSERT(w->position() == 0);
Writer::Slot<ELFHeader> header = w->CreateSlotHere<ELFHeader>();
-#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_X87
+#if (V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_X87 || \
+ (V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT))
const uint8_t ident[16] =
{ 0x7f, 'E', 'L', 'F', 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-#elif V8_TARGET_ARCH_X64
+#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT
const uint8_t ident[16] =
{ 0x7f, 'E', 'L', 'F', 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
#else
@@ -762,7 +763,8 @@
Binding binding() const {
return static_cast<Binding>(info >> 4);
}
-#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_X87
+#if (V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_X87 || \
+ (V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT))
struct SerializedLayout {
SerializedLayout(uint32_t name,
uintptr_t value,
@@ -785,7 +787,7 @@
uint8_t other;
uint16_t section;
};
-#elif V8_TARGET_ARCH_X64
+#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT
struct SerializedLayout {
SerializedLayout(uint32_t name,
uintptr_t value,
diff --git a/src/globals.h b/src/globals.h
index 595ecc3..c76dc85 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -138,7 +138,11 @@
const int kDoubleSize = sizeof(double); // NOLINT
const int kIntptrSize = sizeof(intptr_t); // NOLINT
const int kPointerSize = sizeof(void*); // NOLINT
+#if V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
+const int kRegisterSize = kPointerSize + kPointerSize;
+#else
const int kRegisterSize = kPointerSize;
+#endif
const int kPCOnStackSize = kRegisterSize;
const int kFPOnStackSize = kRegisterSize;
@@ -154,9 +158,17 @@
const int kPointerSizeLog2 = 2;
const intptr_t kIntptrSignBit = 0x80000000;
const uintptr_t kUintptrAllBitsSet = 0xFFFFFFFFu;
+#if V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
+// x32 port also requires code range.
+const bool kRequiresCodeRange = true;
+const size_t kMaximalCodeRangeSize = 256 * MB;
+#else
const bool kRequiresCodeRange = false;
const size_t kMaximalCodeRangeSize = 0 * MB;
#endif
+#endif
+
+STATIC_ASSERT(kPointerSize == (1 << kPointerSizeLog2));
const int kBitsPerByte = 8;
const int kBitsPerByteLog2 = 3;
diff --git a/src/heap.cc b/src/heap.cc
index f8e6d49..4dea510 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -2026,6 +2026,19 @@
AllocationResult allocation =
heap->new_space()->AllocateRaw(allocation_size);
heap->promotion_queue()->SetNewLimit(heap->new_space()->top());
+
+ // Allocation in the other semi-space may fail due to fragmentation.
+ // In that case we allocate in the old generation.
+ if (allocation.IsRetry()) {
+ if (object_contents == DATA_OBJECT) {
+ ASSERT(heap->AllowedToBeMigrated(object, OLD_DATA_SPACE));
+ allocation = heap->old_data_space()->AllocateRaw(allocation_size);
+ } else {
+ ASSERT(heap->AllowedToBeMigrated(object, OLD_POINTER_SPACE));
+ allocation = heap->old_pointer_space()->AllocateRaw(allocation_size);
+ }
+ }
+
HeapObject* target = HeapObject::cast(allocation.ToObjectChecked());
if (alignment != kObjectAlignment) {
diff --git a/src/heap.h b/src/heap.h
index cf1d0ab..cb438b1 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -277,16 +277,11 @@
V(constructor_string, "constructor") \
V(dot_result_string, ".result") \
V(dot_for_string, ".for.") \
- V(dot_iterable_string, ".iterable") \
- V(dot_iterator_string, ".iterator") \
- V(dot_generator_object_string, ".generator_object") \
V(eval_string, "eval") \
V(empty_string, "") \
V(function_string, "function") \
V(length_string, "length") \
- V(module_string, "module") \
V(name_string, "name") \
- V(native_string, "native") \
V(null_string, "null") \
V(number_string, "number") \
V(Number_string, "Number") \
@@ -312,7 +307,6 @@
V(private_api_string, "private_api") \
V(private_intern_string, "private_intern") \
V(Date_string, "Date") \
- V(this_string, "this") \
V(to_string_string, "toString") \
V(char_at_string, "CharAt") \
V(undefined_string, "undefined") \
@@ -335,19 +329,13 @@
V(cell_value_string, "%cell_value") \
V(function_class_string, "Function") \
V(illegal_argument_string, "illegal argument") \
- V(MakeReferenceError_string, "MakeReferenceError") \
- V(MakeSyntaxError_string, "MakeSyntaxError") \
- V(MakeTypeError_string, "MakeTypeError") \
- V(unknown_label_string, "unknown_label") \
V(space_string, " ") \
V(exec_string, "exec") \
V(zero_string, "0") \
V(global_eval_string, "GlobalEval") \
V(identity_hash_string, "v8::IdentityHash") \
V(closure_string, "(closure)") \
- V(use_strict_string, "use strict") \
V(dot_string, ".") \
- V(anonymous_function_string, "(anonymous function)") \
V(compare_ic_string, "==") \
V(strict_compare_ic_string, "===") \
V(infinity_string, "Infinity") \
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index d691cbe..ef42425 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -4383,12 +4383,6 @@
HBasicBlock* true_target = NULL,
HBasicBlock* false_target = NULL)
: known_successor_index_(kNoKnownSuccessorIndex) {
- ASSERT(!left->IsConstant() ||
- (!HConstant::cast(left)->HasInteger32Value() ||
- HConstant::cast(left)->HasSmiValue()));
- ASSERT(!right->IsConstant() ||
- (!HConstant::cast(right)->HasInteger32Value() ||
- HConstant::cast(right)->HasSmiValue()));
SetOperandAt(0, left);
SetOperandAt(1, right);
SetSuccessorAt(0, true_target);
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index a2f6320..339e0d3 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -7626,6 +7626,9 @@
// Parse and allocate variables.
CompilationInfo target_info(target, zone());
+ // Use the same AstValueFactory for creating strings in the sub-compilation
+ // step, but don't transfer ownership to target_info.
+ target_info.SetAstValueFactory(top_info()->ast_value_factory(), false);
Handle<SharedFunctionInfo> target_shared(target->shared());
if (!Parser::Parse(&target_info) || !Scope::Analyze(&target_info)) {
if (target_info.isolate()->has_pending_exception()) {
diff --git a/src/interface.cc b/src/interface.cc
index d6e8406..364de39 100644
--- a/src/interface.cc
+++ b/src/interface.cc
@@ -9,15 +9,6 @@
namespace v8 {
namespace internal {
-static bool Match(void* key1, void* key2) {
- String* name1 = *static_cast<String**>(key1);
- String* name2 = *static_cast<String**>(key2);
- ASSERT(name1->IsInternalizedString());
- ASSERT(name2->IsInternalizedString());
- return name1 == name2;
-}
-
-
Interface* Interface::Lookup(Handle<String> name, Zone* zone) {
ASSERT(IsModule());
ZoneHashMap* map = Chase()->exports_;
@@ -47,8 +38,8 @@
#endif
-void Interface::DoAdd(
- void* name, uint32_t hash, Interface* interface, Zone* zone, bool* ok) {
+void Interface::DoAdd(const void* name, uint32_t hash, Interface* interface,
+ Zone* zone, bool* ok) {
MakeModule(ok);
if (!*ok) return;
@@ -57,8 +48,9 @@
PrintF("%*s# Adding...\n", Nesting::current(), "");
PrintF("%*sthis = ", Nesting::current(), "");
this->Print(Nesting::current());
- PrintF("%*s%s : ", Nesting::current(), "",
- (*static_cast<String**>(name))->ToAsciiArray());
+ const AstRawString* symbol = static_cast<const AstRawString*>(name);
+ PrintF("%*s%.*s : ", Nesting::current(), "", symbol->length(),
+ symbol->raw_data());
interface->Print(Nesting::current());
}
#endif
@@ -68,10 +60,12 @@
if (*map == NULL) {
*map = new(zone->New(sizeof(ZoneHashMap)))
- ZoneHashMap(Match, ZoneHashMap::kDefaultHashMapCapacity, allocator);
+ ZoneHashMap(ZoneHashMap::PointersMatch,
+ ZoneHashMap::kDefaultHashMapCapacity, allocator);
}
- ZoneHashMap::Entry* p = (*map)->Lookup(name, hash, !IsFrozen(), allocator);
+ ZoneHashMap::Entry* p =
+ (*map)->Lookup(const_cast<void*>(name), hash, !IsFrozen(), allocator);
if (p == NULL) {
// This didn't have name but was frozen already, that's an error.
*ok = false;
diff --git a/src/interface.h b/src/interface.h
index 086facf..2076364 100644
--- a/src/interface.h
+++ b/src/interface.h
@@ -5,6 +5,7 @@
#ifndef V8_INTERFACE_H_
#define V8_INTERFACE_H_
+#include "src/ast-value-factory.h"
#include "src/zone-inl.h" // For operator new.
namespace v8 {
@@ -59,8 +60,9 @@
// Add a name to the list of exports. If it already exists, unify with
// interface, otherwise insert unless this is closed.
- void Add(Handle<String> name, Interface* interface, Zone* zone, bool* ok) {
- DoAdd(name.location(), name->Hash(), interface, zone, ok);
+ void Add(const AstRawString* name, Interface* interface, Zone* zone,
+ bool* ok) {
+ DoAdd(name, name->hash(), interface, zone, ok);
}
// Unify with another interface. If successful, both interface objects will
@@ -146,9 +148,9 @@
class Iterator {
public:
bool done() const { return entry_ == NULL; }
- Handle<String> name() const {
+ const AstRawString* name() const {
ASSERT(!done());
- return Handle<String>(*static_cast<String**>(entry_->key));
+ return static_cast<const AstRawString*>(entry_->key);
}
Interface* interface() const {
ASSERT(!done());
@@ -207,7 +209,7 @@
return result;
}
- void DoAdd(void* name, uint32_t hash, Interface* interface, Zone* zone,
+ void DoAdd(const void* name, uint32_t hash, Interface* interface, Zone* zone,
bool* ok);
void DoUnify(Interface* that, bool* ok, Zone* zone);
};
diff --git a/src/list-inl.h b/src/list-inl.h
index 8a4cf56..fd1050e 100644
--- a/src/list-inl.h
+++ b/src/list-inl.h
@@ -219,7 +219,7 @@
int low = 0;
int high = list.length() - 1;
while (low <= high) {
- int mid = (low + high) / 2;
+ int mid = low + (high - low) / 2;
T mid_elem = list[mid];
if (cmp(&mid_elem) > 0) {
diff --git a/src/log.cc b/src/log.cc
index e8af5d0..9603fc1 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -554,14 +554,18 @@
void LowLevelLogger::LogCodeInfo() {
#if V8_TARGET_ARCH_IA32
const char arch[] = "ia32";
-#elif V8_TARGET_ARCH_X64
+#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT
const char arch[] = "x64";
+#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
+ const char arch[] = "x32";
#elif V8_TARGET_ARCH_ARM
const char arch[] = "arm";
#elif V8_TARGET_ARCH_MIPS
const char arch[] = "mips";
#elif V8_TARGET_ARCH_X87
const char arch[] = "x87";
+#elif V8_TARGET_ARCH_ARM64
+ const char arch[] = "arm64";
#else
const char arch[] = "unknown";
#endif
@@ -1711,7 +1715,7 @@
if (overflow) {
msg.Append(",overflow");
}
- for (int i = 0; i < sample->frames_count; ++i) {
+ for (unsigned i = 0; i < sample->frames_count; ++i) {
msg.Append(',');
msg.AppendAddress(sample->stack[i]);
}
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index b31d6ae..b7575b3 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -2015,7 +2015,6 @@
continue;
}
- // Promotion failed. Just migrate object to another semispace.
AllocationResult allocation = new_space->AllocateRaw(size);
if (allocation.IsRetry()) {
if (!new_space->AddFreshPage()) {
diff --git a/src/messages.js b/src/messages.js
index 859bc0d..fd94cc0 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -89,6 +89,10 @@
array_functions_on_frozen: ["Cannot modify frozen array elements"],
array_functions_change_sealed: ["Cannot add/remove sealed array elements"],
first_argument_not_regexp: ["First argument to ", "%0", " must not be a regular expression"],
+ not_iterable: ["%0", " is not iterable"],
+ not_an_iterator: ["%0", " is not an iterator"],
+ iterator_result_not_an_object: ["Iterator result ", "%0", " is not an object"],
+ iterator_value_not_an_object: ["Iterator value ", "%0", " is not an entry object"],
// RangeError
invalid_array_length: ["Invalid array length"],
invalid_array_buffer_length: ["Invalid array buffer length"],
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 7640a76..a56792c 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -54,22 +54,19 @@
#define TYPE_CHECKER(type, instancetype) \
- bool Object::Is##type() { \
+ bool Object::Is##type() const { \
return Object::IsHeapObject() && \
HeapObject::cast(this)->map()->instance_type() == instancetype; \
}
-// TODO(svenpanne) We use const_cast here and at a few other places to break our
-// dependency cycle between the cast methods and the predicates. This can be
-// removed when the predicates are const-correct, too.
#define CAST_ACCESSOR(type) \
type* type::cast(Object* object) { \
SLOW_ASSERT(object->Is##type()); \
return reinterpret_cast<type*>(object); \
} \
const type* type::cast(const Object* object) { \
- SLOW_ASSERT(const_cast<Object*>(object)->Is##type()); \
+ SLOW_ASSERT(object->Is##type()); \
return reinterpret_cast<const type*>(object); \
}
@@ -138,31 +135,31 @@
}
-bool Object::IsFixedArrayBase() {
+bool Object::IsFixedArrayBase() const {
return IsFixedArray() || IsFixedDoubleArray() || IsConstantPoolArray() ||
IsFixedTypedArrayBase() || IsExternalArray();
}
// External objects are not extensible, so the map check is enough.
-bool Object::IsExternal() {
+bool Object::IsExternal() const {
return Object::IsHeapObject() &&
HeapObject::cast(this)->map() ==
HeapObject::cast(this)->GetHeap()->external_map();
}
-bool Object::IsAccessorInfo() {
+bool Object::IsAccessorInfo() const {
return IsExecutableAccessorInfo() || IsDeclaredAccessorInfo();
}
-bool Object::IsSmi() {
+bool Object::IsSmi() const {
return HAS_SMI_TAG(this);
}
-bool Object::IsHeapObject() {
+bool Object::IsHeapObject() const {
return Internals::HasHeapObjectTag(this);
}
@@ -171,41 +168,41 @@
TYPE_CHECKER(Symbol, SYMBOL_TYPE)
-bool Object::IsString() {
+bool Object::IsString() const {
return Object::IsHeapObject()
&& HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
}
-bool Object::IsName() {
+bool Object::IsName() const {
return IsString() || IsSymbol();
}
-bool Object::IsUniqueName() {
+bool Object::IsUniqueName() const {
return IsInternalizedString() || IsSymbol();
}
-bool Object::IsSpecObject() {
+bool Object::IsSpecObject() const {
return Object::IsHeapObject()
&& HeapObject::cast(this)->map()->instance_type() >= FIRST_SPEC_OBJECT_TYPE;
}
-bool Object::IsSpecFunction() {
+bool Object::IsSpecFunction() const {
if (!Object::IsHeapObject()) return false;
InstanceType type = HeapObject::cast(this)->map()->instance_type();
return type == JS_FUNCTION_TYPE || type == JS_FUNCTION_PROXY_TYPE;
}
-bool Object::IsTemplateInfo() {
+bool Object::IsTemplateInfo() const {
return IsObjectTemplateInfo() || IsFunctionTemplateInfo();
}
-bool Object::IsInternalizedString() {
+bool Object::IsInternalizedString() const {
if (!this->IsHeapObject()) return false;
uint32_t type = HeapObject::cast(this)->map()->instance_type();
STATIC_ASSERT(kNotInternalizedTag != 0);
@@ -214,52 +211,52 @@
}
-bool Object::IsConsString() {
+bool Object::IsConsString() const {
if (!IsString()) return false;
return StringShape(String::cast(this)).IsCons();
}
-bool Object::IsSlicedString() {
+bool Object::IsSlicedString() const {
if (!IsString()) return false;
return StringShape(String::cast(this)).IsSliced();
}
-bool Object::IsSeqString() {
+bool Object::IsSeqString() const {
if (!IsString()) return false;
return StringShape(String::cast(this)).IsSequential();
}
-bool Object::IsSeqOneByteString() {
+bool Object::IsSeqOneByteString() const {
if (!IsString()) return false;
return StringShape(String::cast(this)).IsSequential() &&
String::cast(this)->IsOneByteRepresentation();
}
-bool Object::IsSeqTwoByteString() {
+bool Object::IsSeqTwoByteString() const {
if (!IsString()) return false;
return StringShape(String::cast(this)).IsSequential() &&
String::cast(this)->IsTwoByteRepresentation();
}
-bool Object::IsExternalString() {
+bool Object::IsExternalString() const {
if (!IsString()) return false;
return StringShape(String::cast(this)).IsExternal();
}
-bool Object::IsExternalAsciiString() {
+bool Object::IsExternalAsciiString() const {
if (!IsString()) return false;
return StringShape(String::cast(this)).IsExternal() &&
String::cast(this)->IsOneByteRepresentation();
}
-bool Object::IsExternalTwoByteString() {
+bool Object::IsExternalTwoByteString() const {
if (!IsString()) return false;
return StringShape(String::cast(this)).IsExternal() &&
String::cast(this)->IsTwoByteRepresentation();
@@ -287,7 +284,7 @@
}
-StringShape::StringShape(String* str)
+StringShape::StringShape(const String* str)
: type_(str->map()->instance_type()) {
set_valid();
ASSERT((type_ & kIsNotStringMask) == kStringTag);
@@ -316,13 +313,13 @@
}
-bool String::IsOneByteRepresentation() {
+bool String::IsOneByteRepresentation() const {
uint32_t type = map()->instance_type();
return (type & kStringEncodingMask) == kOneByteStringTag;
}
-bool String::IsTwoByteRepresentation() {
+bool String::IsTwoByteRepresentation() const {
uint32_t type = map()->instance_type();
return (type & kStringEncodingMask) == kTwoByteStringTag;
}
@@ -612,7 +609,7 @@
};
-bool Object::IsNumber() {
+bool Object::IsNumber() const {
return IsSmi() || IsHeapNumber();
}
@@ -621,14 +618,14 @@
TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE)
-bool Object::IsFiller() {
+bool Object::IsFiller() const {
if (!Object::IsHeapObject()) return false;
InstanceType instance_type = HeapObject::cast(this)->map()->instance_type();
return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
}
-bool Object::IsExternalArray() {
+bool Object::IsExternalArray() const {
if (!Object::IsHeapObject())
return false;
InstanceType instance_type =
@@ -646,7 +643,7 @@
#undef TYPED_ARRAY_TYPE_CHECKER
-bool Object::IsFixedTypedArrayBase() {
+bool Object::IsFixedTypedArrayBase() const {
if (!Object::IsHeapObject()) return false;
InstanceType instance_type =
@@ -656,21 +653,21 @@
}
-bool Object::IsJSReceiver() {
+bool Object::IsJSReceiver() const {
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
return IsHeapObject() &&
HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_RECEIVER_TYPE;
}
-bool Object::IsJSObject() {
+bool Object::IsJSObject() const {
STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
return IsHeapObject() &&
HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
}
-bool Object::IsJSProxy() {
+bool Object::IsJSProxy() const {
if (!Object::IsHeapObject()) return false;
return HeapObject::cast(this)->map()->IsJSProxyMap();
}
@@ -690,22 +687,22 @@
TYPE_CHECKER(ConstantPoolArray, CONSTANT_POOL_ARRAY_TYPE)
-bool Object::IsJSWeakCollection() {
+bool Object::IsJSWeakCollection() const {
return IsJSWeakMap() || IsJSWeakSet();
}
-bool Object::IsDescriptorArray() {
+bool Object::IsDescriptorArray() const {
return IsFixedArray();
}
-bool Object::IsTransitionArray() {
+bool Object::IsTransitionArray() const {
return IsFixedArray();
}
-bool Object::IsDeoptimizationInputData() {
+bool Object::IsDeoptimizationInputData() const {
// Must be a fixed array.
if (!IsFixedArray()) return false;
@@ -722,7 +719,7 @@
}
-bool Object::IsDeoptimizationOutputData() {
+bool Object::IsDeoptimizationOutputData() const {
if (!IsFixedArray()) return false;
// There's actually no way to see the difference between a fixed array and
// a deoptimization data array. Since this is used for asserts we can check
@@ -732,7 +729,7 @@
}
-bool Object::IsDependentCode() {
+bool Object::IsDependentCode() const {
if (!IsFixedArray()) return false;
// There's actually no way to see the difference between a fixed array and
// a dependent codes array.
@@ -740,7 +737,7 @@
}
-bool Object::IsContext() {
+bool Object::IsContext() const {
if (!Object::IsHeapObject()) return false;
Map* map = HeapObject::cast(this)->map();
Heap* heap = map->GetHeap();
@@ -754,14 +751,14 @@
}
-bool Object::IsNativeContext() {
+bool Object::IsNativeContext() const {
return Object::IsHeapObject() &&
HeapObject::cast(this)->map() ==
HeapObject::cast(this)->GetHeap()->native_context_map();
}
-bool Object::IsScopeInfo() {
+bool Object::IsScopeInfo() const {
return Object::IsHeapObject() &&
HeapObject::cast(this)->map() ==
HeapObject::cast(this)->GetHeap()->scope_info_map();
@@ -788,7 +785,7 @@
TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE)
-bool Object::IsStringWrapper() {
+bool Object::IsStringWrapper() const {
return IsJSValue() && JSValue::cast(this)->value()->IsString();
}
@@ -796,7 +793,7 @@
TYPE_CHECKER(Foreign, FOREIGN_TYPE)
-bool Object::IsBoolean() {
+bool Object::IsBoolean() const {
return IsOddball() &&
((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
}
@@ -808,7 +805,7 @@
TYPE_CHECKER(JSDataView, JS_DATA_VIEW_TYPE)
-bool Object::IsJSArrayBufferView() {
+bool Object::IsJSArrayBufferView() const {
return IsJSDataView() || IsJSTypedArray();
}
@@ -821,47 +818,47 @@
}
-bool Object::IsHashTable() {
+bool Object::IsHashTable() const {
return Object::IsHeapObject() &&
HeapObject::cast(this)->map() ==
HeapObject::cast(this)->GetHeap()->hash_table_map();
}
-bool Object::IsWeakHashTable() {
+bool Object::IsWeakHashTable() const {
return IsHashTable();
}
-bool Object::IsDictionary() {
+bool Object::IsDictionary() const {
return IsHashTable() &&
this != HeapObject::cast(this)->GetHeap()->string_table();
}
-bool Object::IsNameDictionary() {
+bool Object::IsNameDictionary() const {
return IsDictionary();
}
-bool Object::IsSeededNumberDictionary() {
+bool Object::IsSeededNumberDictionary() const {
return IsDictionary();
}
-bool Object::IsUnseededNumberDictionary() {
+bool Object::IsUnseededNumberDictionary() const {
return IsDictionary();
}
-bool Object::IsStringTable() {
+bool Object::IsStringTable() const {
return IsHashTable();
}
-bool Object::IsJSFunctionResultCache() {
+bool Object::IsJSFunctionResultCache() const {
if (!IsFixedArray()) return false;
- FixedArray* self = FixedArray::cast(this);
+ const FixedArray* self = FixedArray::cast(this);
int length = self->length();
if (length < JSFunctionResultCache::kEntriesIndex) return false;
if ((length - JSFunctionResultCache::kEntriesIndex)
@@ -870,7 +867,10 @@
}
#ifdef VERIFY_HEAP
if (FLAG_verify_heap) {
- reinterpret_cast<JSFunctionResultCache*>(this)->
+ // TODO(svenpanne) We use const_cast here and below to break our dependency
+ // cycle between the predicates and the verifiers. This can be removed when
+ // the verifiers are const-correct, too.
+ reinterpret_cast<JSFunctionResultCache*>(const_cast<Object*>(this))->
JSFunctionResultCacheVerify();
}
#endif
@@ -878,7 +878,7 @@
}
-bool Object::IsNormalizedMapCache() {
+bool Object::IsNormalizedMapCache() const {
return NormalizedMapCache::IsNormalizedMapCache(this);
}
@@ -888,68 +888,69 @@
}
-bool NormalizedMapCache::IsNormalizedMapCache(Object* obj) {
+bool NormalizedMapCache::IsNormalizedMapCache(const Object* obj) {
if (!obj->IsFixedArray()) return false;
if (FixedArray::cast(obj)->length() != NormalizedMapCache::kEntries) {
return false;
}
#ifdef VERIFY_HEAP
if (FLAG_verify_heap) {
- reinterpret_cast<NormalizedMapCache*>(obj)->NormalizedMapCacheVerify();
+ reinterpret_cast<NormalizedMapCache*>(const_cast<Object*>(obj))->
+ NormalizedMapCacheVerify();
}
#endif
return true;
}
-bool Object::IsCompilationCacheTable() {
+bool Object::IsCompilationCacheTable() const {
return IsHashTable();
}
-bool Object::IsCodeCacheHashTable() {
+bool Object::IsCodeCacheHashTable() const {
return IsHashTable();
}
-bool Object::IsPolymorphicCodeCacheHashTable() {
+bool Object::IsPolymorphicCodeCacheHashTable() const {
return IsHashTable();
}
-bool Object::IsMapCache() {
+bool Object::IsMapCache() const {
return IsHashTable();
}
-bool Object::IsObjectHashTable() {
+bool Object::IsObjectHashTable() const {
return IsHashTable();
}
-bool Object::IsOrderedHashTable() {
+bool Object::IsOrderedHashTable() const {
return IsHeapObject() &&
HeapObject::cast(this)->map() ==
HeapObject::cast(this)->GetHeap()->ordered_hash_table_map();
}
-bool Object::IsOrderedHashSet() {
+bool Object::IsOrderedHashSet() const {
return IsOrderedHashTable();
}
-bool Object::IsOrderedHashMap() {
+bool Object::IsOrderedHashMap() const {
return IsOrderedHashTable();
}
-bool Object::IsPrimitive() {
+bool Object::IsPrimitive() const {
return IsOddball() || IsNumber() || IsString();
}
-bool Object::IsJSGlobalProxy() {
+bool Object::IsJSGlobalProxy() const {
bool result = IsHeapObject() &&
(HeapObject::cast(this)->map()->instance_type() ==
JS_GLOBAL_PROXY_TYPE);
@@ -959,7 +960,7 @@
}
-bool Object::IsGlobalObject() {
+bool Object::IsGlobalObject() const {
if (!IsHeapObject()) return false;
InstanceType type = HeapObject::cast(this)->map()->instance_type();
@@ -972,25 +973,24 @@
TYPE_CHECKER(JSBuiltinsObject, JS_BUILTINS_OBJECT_TYPE)
-bool Object::IsUndetectableObject() {
+bool Object::IsUndetectableObject() const {
return IsHeapObject()
&& HeapObject::cast(this)->map()->is_undetectable();
}
-bool Object::IsAccessCheckNeeded() {
+bool Object::IsAccessCheckNeeded() const {
if (!IsHeapObject()) return false;
if (IsJSGlobalProxy()) {
- JSGlobalProxy* proxy = JSGlobalProxy::cast(this);
- GlobalObject* global =
- proxy->GetIsolate()->context()->global_object();
+ const JSGlobalProxy* proxy = JSGlobalProxy::cast(this);
+ GlobalObject* global = proxy->GetIsolate()->context()->global_object();
return proxy->IsDetachedFrom(global);
}
return HeapObject::cast(this)->map()->is_access_check_needed();
}
-bool Object::IsStruct() {
+bool Object::IsStruct() const {
if (!IsHeapObject()) return false;
switch (HeapObject::cast(this)->map()->instance_type()) {
#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
@@ -1001,51 +1001,51 @@
}
-#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
- bool Object::Is##Name() { \
- return Object::IsHeapObject() \
+#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
+ bool Object::Is##Name() const { \
+ return Object::IsHeapObject() \
&& HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
}
STRUCT_LIST(MAKE_STRUCT_PREDICATE)
#undef MAKE_STRUCT_PREDICATE
-bool Object::IsUndefined() {
+bool Object::IsUndefined() const {
return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUndefined;
}
-bool Object::IsNull() {
+bool Object::IsNull() const {
return IsOddball() && Oddball::cast(this)->kind() == Oddball::kNull;
}
-bool Object::IsTheHole() {
+bool Object::IsTheHole() const {
return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTheHole;
}
-bool Object::IsException() {
+bool Object::IsException() const {
return IsOddball() && Oddball::cast(this)->kind() == Oddball::kException;
}
-bool Object::IsUninitialized() {
+bool Object::IsUninitialized() const {
return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUninitialized;
}
-bool Object::IsTrue() {
+bool Object::IsTrue() const {
return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTrue;
}
-bool Object::IsFalse() {
+bool Object::IsFalse() const {
return IsOddball() && Oddball::cast(this)->kind() == Oddball::kFalse;
}
-bool Object::IsArgumentsMarker() {
+bool Object::IsArgumentsMarker() const {
return IsOddball() && Oddball::cast(this)->kind() == Oddball::kArgumentMarker;
}
@@ -1058,7 +1058,7 @@
}
-bool Object::IsNaN() {
+bool Object::IsNaN() const {
return this->IsHeapNumber() && std::isnan(HeapNumber::cast(this)->value());
}
@@ -1369,7 +1369,7 @@
}
-Isolate* HeapObject::GetIsolate() {
+Isolate* HeapObject::GetIsolate() const {
return GetHeap()->isolate();
}
@@ -1478,7 +1478,7 @@
}
-double HeapNumber::value() {
+double HeapNumber::value() const {
return READ_DOUBLE_FIELD(this, kValueOffset);
}
@@ -1849,7 +1849,7 @@
ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
-byte Oddball::kind() {
+byte Oddball::kind() const {
return Smi::cast(READ_FIELD(this, kKindOffset))->value();
}
@@ -3147,7 +3147,7 @@
template <class Traits>
const FixedTypedArray<Traits>*
FixedTypedArray<Traits>::cast(const Object* object) {
- SLOW_ASSERT(const_cast<Object*>(object)->IsHeapObject() &&
+ SLOW_ASSERT(object->IsHeapObject() &&
HeapObject::cast(object)->map()->instance_type() ==
Traits::kInstanceType);
return reinterpret_cast<FixedTypedArray<Traits>*>(object);
@@ -3170,7 +3170,7 @@
template <typename Derived, typename Shape, typename Key>
const HashTable<Derived, Shape, Key>*
HashTable<Derived, Shape, Key>::cast(const Object* obj) {
- SLOW_ASSERT(const_cast<Object*>(obj)->IsHashTable());
+ SLOW_ASSERT(obj->IsHashTable());
return reinterpret_cast<const HashTable*>(obj);
}
@@ -4651,14 +4651,17 @@
int Code::allow_osr_at_loop_nesting_level() {
ASSERT_EQ(FUNCTION, kind());
- return READ_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset);
+ int fields = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
+ return AllowOSRAtLoopNestingLevelField::decode(fields);
}
void Code::set_allow_osr_at_loop_nesting_level(int level) {
ASSERT_EQ(FUNCTION, kind());
ASSERT(level >= 0 && level <= kMaxLoopNestingMarker);
- WRITE_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset, level);
+ int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
+ int updated = AllowOSRAtLoopNestingLevelField::update(previous, level);
+ WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
}
@@ -4711,13 +4714,14 @@
unsigned Code::back_edge_table_offset() {
ASSERT_EQ(FUNCTION, kind());
return BackEdgeTableOffsetField::decode(
- READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
+ READ_UINT32_FIELD(this, kKindSpecificFlags2Offset)) << kPointerSizeLog2;
}
void Code::set_back_edge_table_offset(unsigned offset) {
ASSERT_EQ(FUNCTION, kind());
- ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
+ ASSERT(IsAligned(offset, static_cast<unsigned>(kPointerSize)));
+ offset = offset >> kPointerSizeLog2;
int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
int updated = BackEdgeTableOffsetField::update(previous, offset);
WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
@@ -4726,20 +4730,10 @@
bool Code::back_edges_patched_for_osr() {
ASSERT_EQ(FUNCTION, kind());
- return BackEdgesPatchedForOSRField::decode(
- READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
+ return allow_osr_at_loop_nesting_level() > 0;
}
-void Code::set_back_edges_patched_for_osr(bool value) {
- ASSERT_EQ(FUNCTION, kind());
- int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
- int updated = BackEdgesPatchedForOSRField::update(previous, value);
- WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
-}
-
-
-
byte Code::to_boolean_state() {
return extra_ic_state();
}
@@ -6438,7 +6432,7 @@
}
-Object* JSReceiver::GetPrototype() {
+Object* JSReceiver::GetPrototype() const {
return map()->prototype();
}
@@ -6494,7 +6488,7 @@
}
-bool JSGlobalProxy::IsDetachedFrom(GlobalObject* global) {
+bool JSGlobalProxy::IsDetachedFrom(GlobalObject* global) const {
return GetPrototype() != global;
}
diff --git a/src/objects.cc b/src/objects.cc
index e9bedca..08a192f 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -92,8 +92,8 @@
}
-bool Object::IsCallable() {
- Object* fun = this;
+bool Object::IsCallable() const {
+ const Object* fun = this;
while (fun->IsJSFunctionProxy()) {
fun = JSFunctionProxy::cast(fun)->call_trap();
}
@@ -761,7 +761,7 @@
// the hole value.
Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
ASSERT(new_map->is_dictionary_map());
- object->set_map(*new_map);
+ JSObject::MigrateToMap(object, new_map);
}
Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
Handle<Object> value = isolate->factory()->the_hole_value();
@@ -1701,22 +1701,7 @@
bool HeapNumber::HeapNumberBooleanValue() {
- // NaN, +0, and -0 should return the false object
-#if __BYTE_ORDER == __LITTLE_ENDIAN
- union IeeeDoubleLittleEndianArchType u;
-#elif __BYTE_ORDER == __BIG_ENDIAN
- union IeeeDoubleBigEndianArchType u;
-#endif
- u.d = value();
- if (u.bits.exp == 2047) {
- // Detect NaN for IEEE double precision floating point.
- if ((u.bits.man_low | u.bits.man_high) != 0) return false;
- }
- if (u.bits.exp == 0) {
- // Detect +0, and -0 for IEEE double precision floating point.
- if ((u.bits.man_low | u.bits.man_high) == 0) return false;
- }
- return true;
+ return DoubleToBoolean(value());
}
@@ -2119,7 +2104,26 @@
}
-// To migrate an instance to a map:
+void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
+ if (object->map() == *new_map) return;
+ if (object->HasFastProperties()) {
+ if (!new_map->is_dictionary_map()) {
+ MigrateFastToFast(object, new_map);
+ } else {
+ MigrateFastToSlow(object, new_map, 0);
+ }
+ } else {
+ // For slow-to-fast migrations JSObject::TransformToFastProperties()
+ // must be used instead.
+ CHECK(new_map->is_dictionary_map());
+
+ // Slow-to-slow migration is trivial.
+ object->set_map(*new_map);
+ }
+}
+
+
+// To migrate a fast instance to a fast map:
// - First check whether the instance needs to be rewritten. If not, simply
// change the map.
// - Otherwise, allocate a fixed array large enough to hold all fields, in
@@ -2134,7 +2138,7 @@
// to temporarily store the inobject properties.
// * If there are properties left in the backing store, install the backing
// store.
-void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
+void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
Isolate* isolate = object->GetIsolate();
Handle<Map> old_map(object->map());
int number_of_fields = new_map->NumberOfFields();
@@ -2145,8 +2149,6 @@
// converted to doubles.
if (!old_map->InstancesNeedRewriting(
*new_map, number_of_fields, inobject, unused)) {
- // Writing the new map here does not require synchronization since it does
- // not change the actual object size.
object->synchronized_set_map(*new_map);
return;
}
@@ -2180,9 +2182,7 @@
// Set the new property value and do the map transition.
object->set_properties(*new_storage);
- // Writing the new map here does not require synchronization since it does
- // not change the actual object size.
- object->set_map(*new_map);
+ object->synchronized_set_map(*new_map);
return;
}
Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
@@ -2254,24 +2254,21 @@
ASSERT(instance_size_delta >= 0);
Address address = object->address() + new_instance_size;
- // The trimming is performed on a newly allocated object, which is on a
- // freshly allocated page or on an already swept page. Hence, the sweeper
- // thread can not get confused with the filler creation. No synchronization
- // needed.
- isolate->heap()->CreateFillerObjectAt(address, instance_size_delta);
+ Heap* heap = isolate->heap();
// If there are properties in the new backing store, trim it to the correct
// size and install the backing store into the object.
if (external > 0) {
- RightTrimFixedArray<Heap::FROM_MUTATOR>(isolate->heap(), *array, inobject);
+ RightTrimFixedArray<Heap::FROM_MUTATOR>(heap, *array, inobject);
object->set_properties(*array);
}
- // The trimming is performed on a newly allocated object, which is on a
- // freshly allocated page or on an already swept page. Hence, the sweeper
- // thread can not get confused with the filler creation. No synchronization
- // needed.
- object->set_map(*new_map);
+ heap->CreateFillerObjectAt(address, instance_size_delta);
+ heap->AdjustLiveBytes(address, -instance_size_delta, Heap::FROM_MUTATOR);
+
+ // We are storing the new map using release store after creating a filler for
+ // the left-over space to avoid races with the sweeper thread.
+ object->synchronized_set_map(*new_map);
}
@@ -2283,8 +2280,7 @@
Handle<Map> new_map = Map::GeneralizeRepresentation(
handle(object->map()), modify_index, new_representation,
new_field_type, store_mode);
- if (object->map() == *new_map) return;
- return MigrateToMap(object, new_map);
+ MigrateToMap(object, new_map);
}
@@ -3983,8 +3979,7 @@
}
-static void SetPropertyToField(LookupResult* lookup,
- Handle<Object> value) {
+void JSObject::SetPropertyToField(LookupResult* lookup, Handle<Object> value) {
if (lookup->type() == CONSTANT || !lookup->CanHoldValue(value)) {
Representation field_representation = value->OptimalRepresentation();
Handle<HeapType> field_type = value->OptimalType(
@@ -3998,10 +3993,10 @@
}
-static void ConvertAndSetOwnProperty(LookupResult* lookup,
- Handle<Name> name,
- Handle<Object> value,
- PropertyAttributes attributes) {
+void JSObject::ConvertAndSetOwnProperty(LookupResult* lookup,
+ Handle<Name> name,
+ Handle<Object> value,
+ PropertyAttributes attributes) {
Handle<JSObject> object(lookup->holder());
if (object->TooManyFastProperties()) {
JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
@@ -4028,10 +4023,10 @@
}
-static void SetPropertyToFieldWithAttributes(LookupResult* lookup,
- Handle<Name> name,
- Handle<Object> value,
- PropertyAttributes attributes) {
+void JSObject::SetPropertyToFieldWithAttributes(LookupResult* lookup,
+ Handle<Name> name,
+ Handle<Object> value,
+ PropertyAttributes attributes) {
if (lookup->GetAttributes() == attributes) {
if (value->IsUninitialized()) return;
SetPropertyToField(lookup, value);
@@ -4577,6 +4572,16 @@
int expected_additional_properties) {
if (!object->HasFastProperties()) return;
+ Handle<Map> map(object->map());
+ Handle<Map> new_map = Map::Normalize(map, mode);
+
+ MigrateFastToSlow(object, new_map, expected_additional_properties);
+}
+
+
+void JSObject::MigrateFastToSlow(Handle<JSObject> object,
+ Handle<Map> new_map,
+ int expected_additional_properties) {
// The global object is always normalized.
ASSERT(!object->IsGlobalObject());
// JSGlobalProxy must never be normalized
@@ -4585,7 +4590,6 @@
Isolate* isolate = object->GetIsolate();
HandleScope scope(isolate);
Handle<Map> map(object->map());
- Handle<Map> new_map = Map::Normalize(map, mode);
// Allocate new content.
int real_size = map->NumberOfOwnDescriptors();
@@ -4672,8 +4676,8 @@
}
-void JSObject::TransformToFastProperties(Handle<JSObject> object,
- int unused_property_fields) {
+void JSObject::MigrateSlowToFast(Handle<JSObject> object,
+ int unused_property_fields) {
if (object->HasFastProperties()) return;
ASSERT(!object->IsGlobalObject());
Isolate* isolate = object->GetIsolate();
@@ -4718,7 +4722,7 @@
ASSERT_LE(unused_property_fields, inobject_props);
// Transform the object.
new_map->set_unused_property_fields(inobject_props);
- object->set_map(*new_map);
+ object->synchronized_set_map(*new_map);
object->set_properties(isolate->heap()->empty_fixed_array());
// Check that it really works.
ASSERT(object->HasFastProperties());
@@ -4799,7 +4803,7 @@
new_map->set_unused_property_fields(unused_property_fields);
// Transform the object.
- object->set_map(*new_map);
+ object->synchronized_set_map(*new_map);
object->set_properties(*fields);
ASSERT(object->IsJSObject());
@@ -6641,7 +6645,7 @@
if (object->IsGlobalObject()) {
Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
ASSERT(new_map->is_dictionary_map());
- object->set_map(*new_map);
+ JSObject::MigrateToMap(object, new_map);
// When running crankshaft, changing the map is not enough. We
// need to deoptimize all functions that rely on this global
@@ -9362,29 +9366,7 @@
if (length == 0 || length > kMaxArrayIndexSize) return false;
ConsStringIteratorOp op;
StringCharacterStream stream(this, &op);
- uint16_t ch = stream.GetNext();
-
- // If the string begins with a '0' character, it must only consist
- // of it to be a legal array index.
- if (ch == '0') {
- *index = 0;
- return length == 1;
- }
-
- // Convert string to uint32 array index; character by character.
- int d = ch - '0';
- if (d < 0 || d > 9) return false;
- uint32_t result = d;
- while (stream.HasMore()) {
- d = stream.GetNext() - '0';
- if (d < 0 || d > 9) return false;
- // Check that the new result is below the 32 bit limit.
- if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
- result = (result * 10) + d;
- }
-
- *index = result;
- return true;
+ return StringToArrayIndex(&stream, index);
}
@@ -9930,7 +9912,7 @@
// Make sure prototypes are fast objects and their maps have the bit set
// so they remain fast.
if (!object->HasFastProperties()) {
- TransformToFastProperties(object, 0);
+ MigrateSlowToFast(object, 0);
}
}
diff --git a/src/objects.h b/src/objects.h
index 23924ca..259f60d 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1350,48 +1350,49 @@
class Object {
public:
// Type testing.
- bool IsObject() { return true; }
+ bool IsObject() const { return true; }
-#define IS_TYPE_FUNCTION_DECL(type_) inline bool Is##type_();
+#define IS_TYPE_FUNCTION_DECL(type_) INLINE(bool Is##type_() const);
OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
#undef IS_TYPE_FUNCTION_DECL
- inline bool IsFixedArrayBase();
- inline bool IsExternal();
- inline bool IsAccessorInfo();
+ INLINE(bool IsFixedArrayBase() const);
+ INLINE(bool IsExternal() const);
+ INLINE(bool IsAccessorInfo() const);
- inline bool IsStruct();
-#define DECLARE_STRUCT_PREDICATE(NAME, Name, name) inline bool Is##Name();
+ INLINE(bool IsStruct() const);
+#define DECLARE_STRUCT_PREDICATE(NAME, Name, name) \
+ INLINE(bool Is##Name() const);
STRUCT_LIST(DECLARE_STRUCT_PREDICATE)
#undef DECLARE_STRUCT_PREDICATE
- INLINE(bool IsSpecObject());
- INLINE(bool IsSpecFunction());
- INLINE(bool IsTemplateInfo());
- INLINE(bool IsNameDictionary());
- INLINE(bool IsSeededNumberDictionary());
- INLINE(bool IsUnseededNumberDictionary());
- INLINE(bool IsOrderedHashSet());
- INLINE(bool IsOrderedHashMap());
- bool IsCallable();
+ INLINE(bool IsSpecObject()) const;
+ INLINE(bool IsSpecFunction()) const;
+ INLINE(bool IsTemplateInfo()) const;
+ INLINE(bool IsNameDictionary() const);
+ INLINE(bool IsSeededNumberDictionary() const);
+ INLINE(bool IsUnseededNumberDictionary() const);
+ INLINE(bool IsOrderedHashSet() const);
+ INLINE(bool IsOrderedHashMap() const);
+ bool IsCallable() const;
// Oddball testing.
- INLINE(bool IsUndefined());
- INLINE(bool IsNull());
- INLINE(bool IsTheHole());
- INLINE(bool IsException());
- INLINE(bool IsUninitialized());
- INLINE(bool IsTrue());
- INLINE(bool IsFalse());
- inline bool IsArgumentsMarker();
+ INLINE(bool IsUndefined() const);
+ INLINE(bool IsNull() const);
+ INLINE(bool IsTheHole() const);
+ INLINE(bool IsException() const);
+ INLINE(bool IsUninitialized() const);
+ INLINE(bool IsTrue() const);
+ INLINE(bool IsFalse() const);
+ INLINE(bool IsArgumentsMarker() const);
// Filler objects (fillers and free space objects).
- inline bool IsFiller();
+ INLINE(bool IsFiller() const);
// Extract the number.
inline double Number();
- inline bool IsNaN();
+ INLINE(bool IsNaN() const);
bool ToInt32(int32_t* value);
bool ToUint32(uint32_t* value);
@@ -1683,7 +1684,7 @@
inline Heap* GetHeap() const;
// Convenience method to get current isolate.
- inline Isolate* GetIsolate();
+ inline Isolate* GetIsolate() const;
// Converts an address to a HeapObject pointer.
static inline HeapObject* FromAddress(Address address);
@@ -1813,7 +1814,7 @@
class HeapNumber: public HeapObject {
public:
// [value]: number value.
- inline double value();
+ inline double value() const;
inline void set_value(double value);
DECLARE_CAST(HeapNumber)
@@ -1969,7 +1970,7 @@
uint32_t index);
// Return the object's prototype (might be Heap::null_value()).
- inline Object* GetPrototype();
+ inline Object* GetPrototype() const;
// Return the constructor function (may be Heap::null_value()).
inline Object* GetConstructor();
@@ -2425,13 +2426,7 @@
static void TransitionElementsKind(Handle<JSObject> object,
ElementsKind to_kind);
- // TODO(mstarzinger): Both public because of ConvertAndSetOwnProperty().
static void MigrateToMap(Handle<JSObject> object, Handle<Map> new_map);
- static void GeneralizeFieldRepresentation(Handle<JSObject> object,
- int modify_index,
- Representation new_representation,
- Handle<HeapType> new_field_type,
- StoreMode store_mode);
// Convert the object to use the canonical dictionary
// representation. If the object is expected to have additional properties
@@ -2447,8 +2442,8 @@
Handle<JSObject> object);
// Transform slow named properties to fast variants.
- static void TransformToFastProperties(Handle<JSObject> object,
- int unused_property_fields);
+ static void MigrateSlowToFast(Handle<JSObject> object,
+ int unused_property_fields);
// Access fast-case object properties at index.
static Handle<Object> FastPropertyAt(Handle<JSObject> object,
@@ -2632,6 +2627,28 @@
friend class JSReceiver;
friend class Object;
+ static void MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map);
+ static void MigrateFastToSlow(Handle<JSObject> object,
+ Handle<Map> new_map,
+ int expected_additional_properties);
+
+ static void SetPropertyToField(LookupResult* lookup, Handle<Object> value);
+
+ static void ConvertAndSetOwnProperty(LookupResult* lookup,
+ Handle<Name> name,
+ Handle<Object> value,
+ PropertyAttributes attributes);
+
+ static void SetPropertyToFieldWithAttributes(LookupResult* lookup,
+ Handle<Name> name,
+ Handle<Object> value,
+ PropertyAttributes attributes);
+ static void GeneralizeFieldRepresentation(Handle<JSObject> object,
+ int modify_index,
+ Representation new_representation,
+ Handle<HeapType> new_field_type,
+ StoreMode store_mode);
+
static void UpdateAllocationSite(Handle<JSObject> object,
ElementsKind to_kind);
@@ -4770,7 +4787,7 @@
DECLARE_CAST(NormalizedMapCache)
- static inline bool IsNormalizedMapCache(Object* obj);
+ static inline bool IsNormalizedMapCache(const Object* obj);
DECLARE_VERIFIER(NormalizedMapCache)
private:
@@ -5569,7 +5586,6 @@
inline void set_back_edge_table_offset(unsigned offset);
inline bool back_edges_patched_for_osr();
- inline void set_back_edges_patched_for_osr(bool value);
// [to_boolean_foo]: For kind TO_BOOLEAN_IC tells what state the stub is in.
inline byte to_boolean_state();
@@ -5814,8 +5830,7 @@
class FullCodeFlagsHasDebugBreakSlotsField: public BitField<bool, 1, 1> {};
class FullCodeFlagsIsCompiledOptimizable: public BitField<bool, 2, 1> {};
- static const int kAllowOSRAtLoopNestingLevelOffset = kFullCodeFlags + 1;
- static const int kProfilerTicksOffset = kAllowOSRAtLoopNestingLevelOffset + 1;
+ static const int kProfilerTicksOffset = kFullCodeFlags + 1;
// Flags layout. BitField<type, shift, size>.
class ICStateField: public BitField<InlineCacheState, 0, 3> {};
@@ -5886,9 +5901,10 @@
// KindSpecificFlags2 layout (FUNCTION)
class BackEdgeTableOffsetField: public BitField<int,
- kIsCrankshaftedBit + 1, 29> {}; // NOLINT
- class BackEdgesPatchedForOSRField: public BitField<bool,
- kIsCrankshaftedBit + 1 + 29, 1> {}; // NOLINT
+ kIsCrankshaftedBit + 1, 27> {}; // NOLINT
+ class AllowOSRAtLoopNestingLevelField: public BitField<int,
+ kIsCrankshaftedBit + 1 + 27, 4> {}; // NOLINT
+ STATIC_ASSERT(AllowOSRAtLoopNestingLevelField::kMax >= kMaxLoopNestingMarker);
static const int kArgumentsBits = 16;
static const int kMaxArguments = (1 << kArgumentsBits) - 1;
@@ -7809,7 +7825,7 @@
DECLARE_CAST(JSGlobalProxy)
- inline bool IsDetachedFrom(GlobalObject* global);
+ inline bool IsDetachedFrom(GlobalObject* global) const;
// Dispatched behavior.
DECLARE_PRINTER(JSGlobalProxy)
@@ -8805,7 +8821,7 @@
// concrete performance benefit at that particular point in the code.
class StringShape BASE_EMBEDDED {
public:
- inline explicit StringShape(String* s);
+ inline explicit StringShape(const String* s);
inline explicit StringShape(Map* s);
inline explicit StringShape(InstanceType t);
inline bool IsSequential();
@@ -9064,8 +9080,8 @@
// be ASCII encoded. This might be the case even if the string is
// two-byte. Such strings may appear when the embedder prefers
// two-byte external representations even for ASCII data.
- inline bool IsOneByteRepresentation();
- inline bool IsTwoByteRepresentation();
+ inline bool IsOneByteRepresentation() const;
+ inline bool IsTwoByteRepresentation() const;
// Cons and slices have an encoding flag that may not represent the actual
// encoding of the underlying string. This is taken into account here.
@@ -9733,7 +9749,7 @@
// [to_number]: Cached to_number computed at startup.
DECL_ACCESSORS(to_number, Object)
- inline byte kind();
+ inline byte kind() const;
inline void set_kind(byte kind);
DECLARE_CAST(Oddball)
diff --git a/src/parser.cc b/src/parser.cc
index 49e9a81..dd91b1a 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -326,7 +326,9 @@
Scope* Parser::NewScope(Scope* parent, ScopeType scope_type) {
- Scope* result = new(zone()) Scope(parent, scope_type, zone());
+ ASSERT(ast_value_factory_);
+ Scope* result =
+ new (zone()) Scope(parent, scope_type, ast_value_factory_, zone());
result->Initialize();
return result;
}
@@ -399,10 +401,9 @@
// ----------------------------------------------------------------------------
// Implementation of Parser
-bool ParserTraits::IsEvalOrArguments(Handle<String> identifier) const {
- Factory* factory = parser_->isolate()->factory();
- return identifier.is_identical_to(factory->eval_string())
- || identifier.is_identical_to(factory->arguments_string());
+bool ParserTraits::IsEvalOrArguments(const AstRawString* identifier) const {
+ return identifier == parser_->ast_value_factory_->eval_string() ||
+ identifier == parser_->ast_value_factory_->arguments_string();
}
@@ -424,10 +425,10 @@
void ParserTraits::PushPropertyName(FuncNameInferrer* fni,
Expression* expression) {
if (expression->IsPropertyName()) {
- fni->PushLiteralName(expression->AsLiteral()->AsPropertyName());
+ fni->PushLiteralName(expression->AsLiteral()->AsRawPropertyName());
} else {
fni->PushLiteralName(
- parser_->isolate()->factory()->anonymous_function_string());
+ parser_->ast_value_factory_->anonymous_function_string());
}
}
@@ -446,7 +447,7 @@
Scope* scope) {
VariableProxy* callee = expression->AsVariableProxy();
if (callee != NULL &&
- callee->IsVariable(parser_->isolate()->factory()->eval_string())) {
+ callee->raw_name() == parser_->ast_value_factory_->eval_string()) {
scope->DeclarationScope()->RecordEvalCall();
}
}
@@ -464,10 +465,10 @@
bool ParserTraits::ShortcutNumericLiteralBinaryExpression(
Expression** x, Expression* y, Token::Value op, int pos,
AstNodeFactory<AstConstructionVisitor>* factory) {
- if ((*x)->AsLiteral() && (*x)->AsLiteral()->value()->IsNumber() &&
- y->AsLiteral() && y->AsLiteral()->value()->IsNumber()) {
- double x_val = (*x)->AsLiteral()->value()->Number();
- double y_val = y->AsLiteral()->value()->Number();
+ if ((*x)->AsLiteral() && (*x)->AsLiteral()->raw_value()->IsNumber() &&
+ y->AsLiteral() && y->AsLiteral()->raw_value()->IsNumber()) {
+ double x_val = (*x)->AsLiteral()->raw_value()->AsNumber();
+ double y_val = y->AsLiteral()->raw_value()->AsNumber();
switch (op) {
case Token::ADD:
*x = factory->NewNumberLiteral(x_val + y_val, pos);
@@ -526,16 +527,14 @@
AstNodeFactory<AstConstructionVisitor>* factory) {
ASSERT(expression != NULL);
if (expression->IsLiteral()) {
- Handle<Object> literal = expression->AsLiteral()->value();
+ const AstValue* literal = expression->AsLiteral()->raw_value();
if (op == Token::NOT) {
// Convert the literal to a boolean condition and negate it.
bool condition = literal->BooleanValue();
- Handle<Object> result =
- parser_->isolate()->factory()->ToBoolean(!condition);
- return factory->NewLiteral(result, pos);
+ return factory->NewBooleanLiteral(!condition, pos);
} else if (literal->IsNumber()) {
// Compute some expressions involving only number literals.
- double value = literal->Number();
+ double value = literal->AsNumber();
switch (op) {
case Token::ADD:
return expression;
@@ -569,51 +568,41 @@
Expression* ParserTraits::NewThrowReferenceError(const char* message, int pos) {
return NewThrowError(
- parser_->isolate()->factory()->MakeReferenceError_string(),
- message, HandleVector<Object>(NULL, 0), pos);
+ parser_->ast_value_factory_->make_reference_error_string(), message, NULL,
+ pos);
}
Expression* ParserTraits::NewThrowSyntaxError(
- const char* message, Handle<Object> arg, int pos) {
- int argc = arg.is_null() ? 0 : 1;
- Vector< Handle<Object> > arguments = HandleVector<Object>(&arg, argc);
- return NewThrowError(
- parser_->isolate()->factory()->MakeSyntaxError_string(),
- message, arguments, pos);
+ const char* message, const AstRawString* arg, int pos) {
+ return NewThrowError(parser_->ast_value_factory_->make_syntax_error_string(),
+ message, arg, pos);
}
Expression* ParserTraits::NewThrowTypeError(
- const char* message, Handle<Object> arg, int pos) {
- int argc = arg.is_null() ? 0 : 1;
- Vector< Handle<Object> > arguments = HandleVector<Object>(&arg, argc);
- return NewThrowError(
- parser_->isolate()->factory()->MakeTypeError_string(),
- message, arguments, pos);
+ const char* message, const AstRawString* arg, int pos) {
+ return NewThrowError(parser_->ast_value_factory_->make_type_error_string(),
+ message, arg, pos);
}
Expression* ParserTraits::NewThrowError(
- Handle<String> constructor, const char* message,
- Vector<Handle<Object> > arguments, int pos) {
+ const AstRawString* constructor, const char* message,
+ const AstRawString* arg, int pos) {
Zone* zone = parser_->zone();
- Factory* factory = parser_->isolate()->factory();
- int argc = arguments.length();
- Handle<FixedArray> elements = factory->NewFixedArray(argc, TENURED);
- for (int i = 0; i < argc; i++) {
- Handle<Object> element = arguments[i];
- if (!element.is_null()) {
- elements->set(i, *element);
- }
+ int argc = arg != NULL ? 1 : 0;
+ const AstRawString* type =
+ parser_->ast_value_factory_->GetOneByteString(Vector<const uint8_t>(
+ reinterpret_cast<const uint8_t*>(message), StrLength(message)));
+ ZoneList<const AstRawString*>* array =
+ new (zone) ZoneList<const AstRawString*>(argc, zone);
+ if (arg != NULL) {
+ array->Add(arg, zone);
}
- Handle<JSArray> array =
- factory->NewJSArrayWithElements(elements, FAST_ELEMENTS, TENURED);
-
- ZoneList<Expression*>* args = new(zone) ZoneList<Expression*>(2, zone);
- Handle<String> type = factory->InternalizeUtf8String(message);
- args->Add(parser_->factory()->NewLiteral(type, pos), zone);
- args->Add(parser_->factory()->NewLiteral(array, pos), zone);
+ ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(2, zone);
+ args->Add(parser_->factory()->NewStringLiteral(type, pos), zone);
+ args->Add(parser_->factory()->NewStringListLiteral(array, pos), zone);
CallRuntime* call_constructor =
parser_->factory()->NewCallRuntime(constructor, NULL, args, pos);
return parser_->factory()->NewThrow(call_constructor, pos);
@@ -634,13 +623,21 @@
parser_->pending_error_location_ = source_location;
parser_->pending_error_message_ = message;
parser_->pending_error_char_arg_ = arg;
- parser_->pending_error_arg_ = Handle<String>();
+ parser_->pending_error_arg_ = NULL;
parser_->pending_error_is_reference_error_ = is_reference_error;
}
void ParserTraits::ReportMessage(const char* message,
- MaybeHandle<String> arg,
+ const char* arg,
+ bool is_reference_error) {
+ Scanner::Location source_location = parser_->scanner()->location();
+ ReportMessageAt(source_location, message, arg, is_reference_error);
+}
+
+
+void ParserTraits::ReportMessage(const char* message,
+ const AstRawString* arg,
bool is_reference_error) {
Scanner::Location source_location = parser_->scanner()->location();
ReportMessageAt(source_location, message, arg, is_reference_error);
@@ -649,7 +646,7 @@
void ParserTraits::ReportMessageAt(Scanner::Location source_location,
const char* message,
- MaybeHandle<String> arg,
+ const AstRawString* arg,
bool is_reference_error) {
if (parser_->stack_overflow()) {
// Suppress the error message (syntax error or such) in the presence of a
@@ -666,17 +663,16 @@
}
-Handle<String> ParserTraits::GetSymbol(Scanner* scanner) {
- Handle<String> result =
- parser_->scanner()->AllocateInternalizedString(parser_->isolate());
- ASSERT(!result.is_null());
+const AstRawString* ParserTraits::GetSymbol(Scanner* scanner) {
+ const AstRawString* result =
+ parser_->scanner()->CurrentSymbol(parser_->ast_value_factory_);
+ ASSERT(result != NULL);
return result;
}
-Handle<String> ParserTraits::NextLiteralString(Scanner* scanner,
- PretenureFlag tenured) {
- return scanner->AllocateNextLiteralString(parser_->isolate(), tenured);
+const AstRawString* ParserTraits::GetNextSymbol(Scanner* scanner) {
+ return parser_->scanner()->NextSymbol(parser_->ast_value_factory_);
}
@@ -691,14 +687,13 @@
Token::Value token, int pos,
Scanner* scanner,
AstNodeFactory<AstConstructionVisitor>* factory) {
- Factory* isolate_factory = parser_->isolate()->factory();
switch (token) {
case Token::NULL_LITERAL:
- return factory->NewLiteral(isolate_factory->null_value(), pos);
+ return factory->NewNullLiteral(pos);
case Token::TRUE_LITERAL:
- return factory->NewLiteral(isolate_factory->true_value(), pos);
+ return factory->NewBooleanLiteral(true, pos);
case Token::FALSE_LITERAL:
- return factory->NewLiteral(isolate_factory->false_value(), pos);
+ return factory->NewBooleanLiteral(false, pos);
case Token::NUMBER: {
double value = scanner->DoubleValue();
return factory->NewNumberLiteral(value, pos);
@@ -711,13 +706,13 @@
Expression* ParserTraits::ExpressionFromIdentifier(
- Handle<String> name, int pos, Scope* scope,
+ const AstRawString* name, int pos, Scope* scope,
AstNodeFactory<AstConstructionVisitor>* factory) {
if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name);
// The name may refer to a module instance object, so its type is unknown.
#ifdef DEBUG
if (FLAG_print_interface_details)
- PrintF("# Variable %s ", name->ToAsciiArray());
+ PrintF("# Variable %.*s ", name->length(), name->raw_data());
#endif
Interface* interface = Interface::NewUnknown(parser_->zone());
return scope->NewUnresolved(factory, name, interface, pos);
@@ -727,16 +722,15 @@
Expression* ParserTraits::ExpressionFromString(
int pos, Scanner* scanner,
AstNodeFactory<AstConstructionVisitor>* factory) {
- Handle<String> symbol = GetSymbol(scanner);
+ const AstRawString* symbol = GetSymbol(scanner);
if (parser_->fni_ != NULL) parser_->fni_->PushLiteralName(symbol);
- return factory->NewLiteral(symbol, pos);
+ return factory->NewStringLiteral(symbol, pos);
}
Literal* ParserTraits::GetLiteralTheHole(
int position, AstNodeFactory<AstConstructionVisitor>* factory) {
- return factory->NewLiteral(parser_->isolate()->factory()->the_hole_value(),
- RelocInfo::kNoPosition);
+ return factory->NewTheHoleLiteral(RelocInfo::kNoPosition);
}
@@ -746,7 +740,7 @@
FunctionLiteral* ParserTraits::ParseFunctionLiteral(
- Handle<String> name,
+ const AstRawString* name,
Scanner::Location function_name_location,
bool name_is_strict_reserved,
bool is_generator,
@@ -776,9 +770,11 @@
target_stack_(NULL),
cached_data_(NULL),
cached_data_mode_(NO_CACHED_DATA),
+ ast_value_factory_(NULL),
info_(info),
has_pending_error_(false),
pending_error_message_(NULL),
+ pending_error_arg_(NULL),
pending_error_char_arg_(NULL) {
ASSERT(!script_.is_null());
isolate_->set_ast_node_id(0);
@@ -802,7 +798,7 @@
if (FLAG_trace_parse) {
timer.Start();
}
- fni_ = new(zone()) FuncNameInferrer(isolate(), zone());
+ fni_ = new(zone()) FuncNameInferrer(ast_value_factory_, zone());
// Initialize parser state.
CompleteParserRecorder recorder;
@@ -857,13 +853,16 @@
ASSERT(scope_ == NULL);
ASSERT(target_stack_ == NULL);
- Handle<String> no_name = isolate()->factory()->empty_string();
-
FunctionLiteral* result = NULL;
{ Scope* scope = NewScope(scope_, GLOBAL_SCOPE);
info->SetGlobalScope(scope);
if (!info->context().is_null()) {
scope = Scope::DeserializeScopeChain(*info->context(), scope, zone());
+ // The Scope is backed up by ScopeInfo (which is in the V8 heap); this
+ // means the Parser cannot operate independent of the V8 heap. Tell the
+ // string table to internalize strings and values right after they're
+ // created.
+ ast_value_factory_->Internalize(isolate());
}
original_scope_ = scope;
if (info->is_eval()) {
@@ -886,7 +885,8 @@
ParsingModeScope parsing_mode(this, mode);
// Enters 'scope'.
- FunctionState function_state(&function_state_, &scope_, scope, zone());
+ FunctionState function_state(&function_state_, &scope_, scope, zone(),
+ ast_value_factory_);
scope_->SetStrictMode(info->strict_mode());
ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
@@ -911,9 +911,11 @@
}
}
+ ast_value_factory_->Internalize(isolate());
if (ok) {
result = factory()->NewFunctionLiteral(
- no_name,
+ ast_value_factory_->empty_string(),
+ ast_value_factory_,
scope_,
body,
function_state.materialized_literal_count(),
@@ -985,8 +987,10 @@
ASSERT(target_stack_ == NULL);
Handle<String> name(String::cast(shared_info->name()));
- fni_ = new(zone()) FuncNameInferrer(isolate(), zone());
- fni_->PushEnclosingName(name);
+ ASSERT(ast_value_factory_);
+ fni_ = new(zone()) FuncNameInferrer(ast_value_factory_, zone());
+ const AstRawString* raw_name = ast_value_factory_->GetString(name);
+ fni_->PushEnclosingName(raw_name);
ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
@@ -1002,7 +1006,8 @@
zone());
}
original_scope_ = scope;
- FunctionState function_state(&function_state_, &scope_, scope, zone());
+ FunctionState function_state(&function_state_, &scope_, scope, zone(),
+ ast_value_factory_);
ASSERT(scope->strict_mode() == SLOPPY || info()->strict_mode() == STRICT);
ASSERT(info()->strict_mode() == shared_info->strict_mode());
scope->SetStrictMode(shared_info->strict_mode());
@@ -1012,7 +1017,7 @@
: FunctionLiteral::NAMED_EXPRESSION)
: FunctionLiteral::DECLARATION;
bool ok = true;
- result = ParseFunctionLiteral(name,
+ result = ParseFunctionLiteral(raw_name,
Scanner::Location::invalid(),
false, // Strict mode name already checked.
shared_info->is_generator(),
@@ -1027,6 +1032,7 @@
// Make sure the target stack is empty.
ASSERT(target_stack_ == NULL);
+ ast_value_factory_->Internalize(isolate());
if (result == NULL) {
if (stack_overflow()) {
isolate()->StackOverflow();
@@ -1082,15 +1088,12 @@
// Still processing directive prologue?
if ((e_stat = stat->AsExpressionStatement()) != NULL &&
(literal = e_stat->expression()->AsLiteral()) != NULL &&
- literal->value()->IsString()) {
- Handle<String> directive = Handle<String>::cast(literal->value());
-
+ literal->raw_value()->IsString()) {
// Check "use strict" directive (ES5 14.1).
if (strict_mode() == SLOPPY &&
- String::Equals(isolate()->factory()->use_strict_string(),
- directive) &&
- token_loc.end_pos - token_loc.beg_pos ==
- isolate()->heap()->use_strict_string()->length() + 2) {
+ literal->raw_value()->AsString() ==
+ ast_value_factory_->use_strict_string() &&
+ token_loc.end_pos - token_loc.beg_pos == 12) {
// TODO(mstarzinger): Global strict eval calls, need their own scope
// as specified in ES5 10.4.2(3). The correct fix would be to always
// add this scope in DoParseProgram(), but that requires adaptations
@@ -1121,7 +1124,7 @@
}
-Statement* Parser::ParseModuleElement(ZoneStringList* labels,
+Statement* Parser::ParseModuleElement(ZoneList<const AstRawString*>* labels,
bool* ok) {
// (Ecma 262 5th Edition, clause 14):
// SourceElement:
@@ -1155,10 +1158,9 @@
!scanner()->HasAnyLineTerminatorBeforeNext() &&
stmt != NULL) {
ExpressionStatement* estmt = stmt->AsExpressionStatement();
- if (estmt != NULL &&
- estmt->expression()->AsVariableProxy() != NULL &&
- String::Equals(isolate()->factory()->module_string(),
- estmt->expression()->AsVariableProxy()->name()) &&
+ if (estmt != NULL && estmt->expression()->AsVariableProxy() != NULL &&
+ estmt->expression()->AsVariableProxy()->raw_name() ==
+ ast_value_factory_->module_string() &&
!scanner()->literal_contains_escapes()) {
return ParseModuleDeclaration(NULL, ok);
}
@@ -1169,16 +1171,18 @@
}
-Statement* Parser::ParseModuleDeclaration(ZoneStringList* names, bool* ok) {
+Statement* Parser::ParseModuleDeclaration(ZoneList<const AstRawString*>* names,
+ bool* ok) {
// ModuleDeclaration:
// 'module' Identifier Module
int pos = peek_position();
- Handle<String> name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
+ const AstRawString* name =
+ ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
#ifdef DEBUG
if (FLAG_print_interface_details)
- PrintF("# Module %s...\n", name->ToAsciiArray());
+ PrintF("# Module %.*s ", name->length(), name->raw_data());
#endif
Module* module = ParseModule(CHECK_OK);
@@ -1189,10 +1193,9 @@
#ifdef DEBUG
if (FLAG_print_interface_details)
- PrintF("# Module %s.\n", name->ToAsciiArray());
-
+ PrintF("# Module %.*s ", name->length(), name->raw_data());
if (FLAG_print_interfaces) {
- PrintF("module %s : ", name->ToAsciiArray());
+ PrintF("module %.*s: ", name->length(), name->raw_data());
module->interface()->Print();
}
#endif
@@ -1293,17 +1296,17 @@
int pos = peek_position();
Module* result = ParseModuleVariable(CHECK_OK);
while (Check(Token::PERIOD)) {
- Handle<String> name = ParseIdentifierName(CHECK_OK);
+ const AstRawString* name = ParseIdentifierName(CHECK_OK);
#ifdef DEBUG
if (FLAG_print_interface_details)
- PrintF("# Path .%s ", name->ToAsciiArray());
+ PrintF("# Path .%.*s ", name->length(), name->raw_data());
#endif
Module* member = factory()->NewModulePath(result, name, pos);
result->interface()->Add(name, member->interface(), zone(), ok);
if (!*ok) {
#ifdef DEBUG
if (FLAG_print_interfaces) {
- PrintF("PATH TYPE ERROR at '%s'\n", name->ToAsciiArray());
+ PrintF("PATH TYPE ERROR at '%.*s'\n", name->length(), name->raw_data());
PrintF("result: ");
result->interface()->Print();
PrintF("member: ");
@@ -1325,10 +1328,11 @@
// Identifier
int pos = peek_position();
- Handle<String> name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
+ const AstRawString* name =
+ ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
#ifdef DEBUG
if (FLAG_print_interface_details)
- PrintF("# Module variable %s ", name->ToAsciiArray());
+ PrintF("# Module variable %.*s ", name->length(), name->raw_data());
#endif
VariableProxy* proxy = scope_->NewUnresolved(
factory(), name, Interface::NewModule(zone()),
@@ -1344,7 +1348,7 @@
int pos = peek_position();
Expect(Token::STRING, CHECK_OK);
- Handle<String> symbol = GetSymbol();
+ const AstRawString* symbol = GetSymbol(scanner());
// TODO(ES6): Request JS resource from environment...
@@ -1388,9 +1392,9 @@
int pos = peek_position();
Expect(Token::IMPORT, CHECK_OK);
- ZoneStringList names(1, zone());
+ ZoneList<const AstRawString*> names(1, zone());
- Handle<String> name = ParseIdentifierName(CHECK_OK);
+ const AstRawString* name = ParseIdentifierName(CHECK_OK);
names.Add(name, zone());
while (peek() == Token::COMMA) {
Consume(Token::COMMA);
@@ -1408,14 +1412,15 @@
for (int i = 0; i < names.length(); ++i) {
#ifdef DEBUG
if (FLAG_print_interface_details)
- PrintF("# Import %s ", names[i]->ToAsciiArray());
+ PrintF("# Import %.*s ", name->length(), name->raw_data());
#endif
Interface* interface = Interface::NewUnknown(zone());
module->interface()->Add(names[i], interface, zone(), ok);
if (!*ok) {
#ifdef DEBUG
if (FLAG_print_interfaces) {
- PrintF("IMPORT TYPE ERROR at '%s'\n", names[i]->ToAsciiArray());
+ PrintF("IMPORT TYPE ERROR at '%.*s'\n", name->length(),
+ name->raw_data());
PrintF("module: ");
module->interface()->Print();
}
@@ -1446,14 +1451,14 @@
Expect(Token::EXPORT, CHECK_OK);
Statement* result = NULL;
- ZoneStringList names(1, zone());
+ ZoneList<const AstRawString*> names(1, zone());
switch (peek()) {
case Token::IDENTIFIER: {
int pos = position();
- Handle<String> name =
+ const AstRawString* name =
ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
// Handle 'module' as a context-sensitive keyword.
- if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("module"))) {
+ if (name != ast_value_factory_->module_string()) {
names.Add(name, zone());
while (peek() == Token::COMMA) {
Consume(Token::COMMA);
@@ -1489,7 +1494,7 @@
for (int i = 0; i < names.length(); ++i) {
#ifdef DEBUG
if (FLAG_print_interface_details)
- PrintF("# Export %s ", names[i]->ToAsciiArray());
+ PrintF("# Export %.*s ", names[i]->length(), names[i]->raw_data());
#endif
Interface* inner = Interface::NewUnknown(zone());
interface->Add(names[i], inner, zone(), CHECK_OK);
@@ -1509,7 +1514,7 @@
}
-Statement* Parser::ParseBlockElement(ZoneStringList* labels,
+Statement* Parser::ParseBlockElement(ZoneList<const AstRawString*>* labels,
bool* ok) {
// (Ecma 262 5th Edition, clause 14):
// SourceElement:
@@ -1534,7 +1539,8 @@
}
-Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
+Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels,
+ bool* ok) {
// Statement ::
// Block
// VariableStatement
@@ -1644,8 +1650,8 @@
}
-VariableProxy* Parser::NewUnresolved(
- Handle<String> name, VariableMode mode, Interface* interface) {
+VariableProxy* Parser::NewUnresolved(const AstRawString* name,
+ VariableMode mode, Interface* interface) {
// If we are inside a function, a declaration of a var/const variable is a
// truly local variable, and the scope of the variable is always the function
// scope.
@@ -1658,7 +1664,8 @@
void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
VariableProxy* proxy = declaration->proxy();
- Handle<String> name = proxy->name();
+ ASSERT(proxy->raw_name() != NULL);
+ const AstRawString* name = proxy->raw_name();
VariableMode mode = declaration->mode();
Scope* declaration_scope = DeclarationScope(mode);
Variable* var = NULL;
@@ -1786,8 +1793,10 @@
if (FLAG_harmony_modules) {
bool ok;
#ifdef DEBUG
- if (FLAG_print_interface_details)
- PrintF("# Declare %s\n", var->name()->ToAsciiArray());
+ if (FLAG_print_interface_details) {
+ PrintF("# Declare %.*s ", var->raw_name()->length(),
+ var->raw_name()->raw_data());
+ }
#endif
proxy->interface()->Unify(var->interface(), zone(), &ok);
if (!ok) {
@@ -1815,7 +1824,7 @@
int pos = peek_position();
Expect(Token::FUNCTION, CHECK_OK);
// Allow "eval" or "arguments" for backward compatibility.
- Handle<String> name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
+ const AstRawString* name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
bool done = (peek() == Token::RPAREN);
while (!done) {
@@ -1850,7 +1859,8 @@
}
-Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
+Statement* Parser::ParseFunctionDeclaration(
+ ZoneList<const AstRawString*>* names, bool* ok) {
// FunctionDeclaration ::
// 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
// GeneratorDeclaration ::
@@ -1860,7 +1870,7 @@
int pos = position();
bool is_generator = allow_generators() && Check(Token::MUL);
bool is_strict_reserved = false;
- Handle<String> name = ParseIdentifierOrStrictReservedWord(
+ const AstRawString* name = ParseIdentifierOrStrictReservedWord(
&is_strict_reserved, CHECK_OK);
FunctionLiteral* fun = ParseFunctionLiteral(name,
scanner()->location(),
@@ -1887,7 +1897,7 @@
}
-Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
+Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) {
if (allow_harmony_scoping() && strict_mode() == STRICT) {
return ParseScopedBlock(labels, ok);
}
@@ -1914,7 +1924,8 @@
}
-Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
+Block* Parser::ParseScopedBlock(ZoneList<const AstRawString*>* labels,
+ bool* ok) {
// The harmony mode uses block elements instead of statements.
//
// Block ::
@@ -1949,12 +1960,12 @@
Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
- ZoneStringList* names,
+ ZoneList<const AstRawString*>* names,
bool* ok) {
// VariableStatement ::
// VariableDeclarations ';'
- Handle<String> ignore;
+ const AstRawString* ignore;
Block* result =
ParseVariableDeclarations(var_context, NULL, names, &ignore, CHECK_OK);
ExpectSemicolon(CHECK_OK);
@@ -1970,8 +1981,8 @@
Block* Parser::ParseVariableDeclarations(
VariableDeclarationContext var_context,
VariableDeclarationProperties* decl_props,
- ZoneStringList* names,
- Handle<String>* out,
+ ZoneList<const AstRawString*>* names,
+ const AstRawString** out,
bool* ok) {
// VariableDeclarations ::
// ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
@@ -2079,7 +2090,7 @@
// Create new block with one expected declaration.
Block* block = factory()->NewBlock(NULL, 1, true, pos);
int nvars = 0; // the number of variables declared
- Handle<String> name;
+ const AstRawString* name = NULL;
do {
if (fni_ != NULL) fni_->Enter();
@@ -2198,7 +2209,7 @@
ZoneList<Expression*>* arguments =
new(zone()) ZoneList<Expression*>(3, zone());
// We have at least 1 parameter.
- arguments->Add(factory()->NewLiteral(name, pos), zone());
+ arguments->Add(factory()->NewStringLiteral(name, pos), zone());
CallRuntime* initialize;
if (is_const) {
@@ -2210,7 +2221,7 @@
// Note that the function does different things depending on
// the number of arguments (1 or 2).
initialize = factory()->NewCallRuntime(
- isolate()->factory()->InitializeConstGlobal_string(),
+ ast_value_factory_->initialize_const_global_string(),
Runtime::FunctionForId(Runtime::kHiddenInitializeConstGlobal),
arguments, pos);
} else {
@@ -2233,7 +2244,7 @@
// Note that the function does different things depending on
// the number of arguments (2 or 3).
initialize = factory()->NewCallRuntime(
- isolate()->factory()->InitializeVarGlobal_string(),
+ ast_value_factory_->initialize_var_global_string(),
Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
arguments, pos);
}
@@ -2289,11 +2300,12 @@
}
-static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) {
- ASSERT(!label.is_null());
+static bool ContainsLabel(ZoneList<const AstRawString*>* labels,
+ const AstRawString* label) {
+ ASSERT(label != NULL);
if (labels != NULL) {
for (int i = labels->length(); i-- > 0; ) {
- if (labels->at(i).is_identical_to(label)) {
+ if (labels->at(i) == label) {
return true;
}
}
@@ -2302,8 +2314,8 @@
}
-Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
- bool* ok) {
+Statement* Parser::ParseExpressionOrLabelledStatement(
+ ZoneList<const AstRawString*>* labels, bool* ok) {
// ExpressionStatement | LabelledStatement ::
// Expression ';'
// Identifier ':' Statement
@@ -2316,7 +2328,7 @@
// Expression is a single identifier, and not, e.g., a parenthesized
// identifier.
VariableProxy* var = expr->AsVariableProxy();
- Handle<String> label = var->name();
+ const AstRawString* label = var->raw_name();
// TODO(1240780): We don't check for redeclaration of labels
// during preparsing since keeping track of the set of active
// labels requires nontrivial changes to the way scopes are
@@ -2328,7 +2340,7 @@
return NULL;
}
if (labels == NULL) {
- labels = new(zone()) ZoneStringList(4, zone());
+ labels = new(zone()) ZoneList<const AstRawString*>(4, zone());
}
labels->Add(label, zone());
// Remove the "ghost" variable that turned out to be a label
@@ -2347,8 +2359,8 @@
!scanner()->HasAnyLineTerminatorBeforeNext() &&
expr != NULL &&
expr->AsVariableProxy() != NULL &&
- String::Equals(isolate()->factory()->native_string(),
- expr->AsVariableProxy()->name()) &&
+ expr->AsVariableProxy()->raw_name() ==
+ ast_value_factory_->native_string() &&
!scanner()->literal_contains_escapes()) {
return ParseNativeDeclaration(ok);
}
@@ -2359,8 +2371,8 @@
peek() != Token::IDENTIFIER ||
scanner()->HasAnyLineTerminatorBeforeNext() ||
expr->AsVariableProxy() == NULL ||
- !String::Equals(isolate()->factory()->module_string(),
- expr->AsVariableProxy()->name()) ||
+ expr->AsVariableProxy()->raw_name() !=
+ ast_value_factory_->module_string() ||
scanner()->literal_contains_escapes()) {
ExpectSemicolon(CHECK_OK);
}
@@ -2368,7 +2380,8 @@
}
-IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
+IfStatement* Parser::ParseIfStatement(ZoneList<const AstRawString*>* labels,
+ bool* ok) {
// IfStatement ::
// 'if' '(' Expression ')' Statement ('else' Statement)?
@@ -2396,19 +2409,18 @@
int pos = peek_position();
Expect(Token::CONTINUE, CHECK_OK);
- Handle<String> label = Handle<String>::null();
+ const AstRawString* label = NULL;
Token::Value tok = peek();
if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
// ECMA allows "eval" or "arguments" as labels even in strict mode.
label = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
}
- IterationStatement* target = NULL;
- target = LookupContinueTarget(label, CHECK_OK);
+ IterationStatement* target = LookupContinueTarget(label, CHECK_OK);
if (target == NULL) {
// Illegal continue statement.
const char* message = "illegal_continue";
- if (!label.is_null()) {
+ if (label != NULL) {
message = "unknown_label";
}
ParserTraits::ReportMessage(message, label);
@@ -2420,13 +2432,14 @@
}
-Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
+Statement* Parser::ParseBreakStatement(ZoneList<const AstRawString*>* labels,
+ bool* ok) {
// BreakStatement ::
// 'break' Identifier? ';'
int pos = peek_position();
Expect(Token::BREAK, CHECK_OK);
- Handle<String> label;
+ const AstRawString* label = NULL;
Token::Value tok = peek();
if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
@@ -2435,7 +2448,7 @@
}
// Parse labeled break statements that target themselves into
// empty statements, e.g. 'l1: l2: l3: break l2;'
- if (!label.is_null() && ContainsLabel(labels, label)) {
+ if (label != NULL && ContainsLabel(labels, label)) {
ExpectSemicolon(CHECK_OK);
return factory()->NewEmptyStatement(pos);
}
@@ -2444,7 +2457,7 @@
if (target == NULL) {
// Illegal break statement.
const char* message = "illegal_break";
- if (!label.is_null()) {
+ if (label != NULL) {
message = "unknown_label";
}
ParserTraits::ReportMessage(message, label);
@@ -2498,7 +2511,8 @@
}
-Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
+Statement* Parser::ParseWithStatement(ZoneList<const AstRawString*>* labels,
+ bool* ok) {
// WithStatement ::
// 'with' '(' Expression ')' Statement
@@ -2560,8 +2574,8 @@
}
-SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
- bool* ok) {
+SwitchStatement* Parser::ParseSwitchStatement(
+ ZoneList<const AstRawString*>* labels, bool* ok) {
// SwitchStatement ::
// 'switch' '(' Expression ')' '{' CaseClause* '}'
@@ -2644,7 +2658,7 @@
Scope* catch_scope = NULL;
Variable* catch_variable = NULL;
Block* catch_block = NULL;
- Handle<String> name;
+ const AstRawString* name = NULL;
if (tok == Token::CATCH) {
Consume(Token::CATCH);
@@ -2714,8 +2728,8 @@
}
-DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
- bool* ok) {
+DoWhileStatement* Parser::ParseDoWhileStatement(
+ ZoneList<const AstRawString*>* labels, bool* ok) {
// DoStatement ::
// 'do' Statement 'while' '(' Expression ')' ';'
@@ -2742,7 +2756,8 @@
}
-WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
+WhileStatement* Parser::ParseWhileStatement(
+ ZoneList<const AstRawString*>* labels, bool* ok) {
// WhileStatement ::
// 'while' '(' Expression ')' Statement
@@ -2781,13 +2796,12 @@
ForOfStatement* for_of = stmt->AsForOfStatement();
if (for_of != NULL) {
- Factory* heap_factory = isolate()->factory();
Variable* iterable = scope_->DeclarationScope()->NewTemporary(
- heap_factory->dot_iterable_string());
+ ast_value_factory_->dot_iterable_string());
Variable* iterator = scope_->DeclarationScope()->NewTemporary(
- heap_factory->dot_iterator_string());
+ ast_value_factory_->dot_iterator_string());
Variable* result = scope_->DeclarationScope()->NewTemporary(
- heap_factory->dot_result_string());
+ ast_value_factory_->dot_result_string());
Expression* assign_iterable;
Expression* assign_iterator;
@@ -2805,10 +2819,8 @@
// var iterator = iterable[Symbol.iterator]();
{
Expression* iterable_proxy = factory()->NewVariableProxy(iterable);
- Handle<Symbol> iterator_symbol(
- isolate()->native_context()->iterator_symbol(), isolate());
- Expression* iterator_symbol_literal = factory()->NewLiteral(
- iterator_symbol, RelocInfo::kNoPosition);
+ Expression* iterator_symbol_literal =
+ factory()->NewSymbolLiteral("symbolIterator", RelocInfo::kNoPosition);
// FIXME(wingo): Unhappily, it will be a common error that the RHS of a
// for-of doesn't have a Symbol.iterator property. We should do better
// than informing the user that "undefined is not a function".
@@ -2827,8 +2839,8 @@
// var result = iterator.next();
{
Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
- Expression* next_literal = factory()->NewLiteral(
- heap_factory->next_string(), RelocInfo::kNoPosition);
+ Expression* next_literal = factory()->NewStringLiteral(
+ ast_value_factory_->next_string(), RelocInfo::kNoPosition);
Expression* next_property = factory()->NewProperty(
iterator_proxy, next_literal, RelocInfo::kNoPosition);
ZoneList<Expression*>* next_arguments =
@@ -2842,8 +2854,8 @@
// result.done
{
- Expression* done_literal = factory()->NewLiteral(
- heap_factory->done_string(), RelocInfo::kNoPosition);
+ Expression* done_literal = factory()->NewStringLiteral(
+ ast_value_factory_->done_string(), RelocInfo::kNoPosition);
Expression* result_proxy = factory()->NewVariableProxy(result);
result_done = factory()->NewProperty(
result_proxy, done_literal, RelocInfo::kNoPosition);
@@ -2851,8 +2863,8 @@
// each = result.value
{
- Expression* value_literal = factory()->NewLiteral(
- heap_factory->value_string(), RelocInfo::kNoPosition);
+ Expression* value_literal = factory()->NewStringLiteral(
+ ast_value_factory_->value_string(), RelocInfo::kNoPosition);
Expression* result_proxy = factory()->NewVariableProxy(result);
Expression* result_value = factory()->NewProperty(
result_proxy, value_literal, RelocInfo::kNoPosition);
@@ -2873,9 +2885,9 @@
Statement* Parser::DesugarLetBindingsInForStatement(
- Scope* inner_scope, ZoneStringList* names, ForStatement* loop,
- Statement* init, Expression* cond, Statement* next, Statement* body,
- bool* ok) {
+ Scope* inner_scope, ZoneList<const AstRawString*>* names,
+ ForStatement* loop, Statement* init, Expression* cond, Statement* next,
+ Statement* body, bool* ok) {
// ES6 13.6.3.4 specifies that on each loop iteration the let variables are
// copied into a new environment. After copying, the "next" statement of the
// loop is executed to update the loop variables. The loop condition is
@@ -2916,10 +2928,7 @@
RelocInfo::kNoPosition);
outer_block->AddStatement(init, zone());
- Handle<String> temp_name = isolate()->factory()->dot_for_string();
- Handle<Smi> smi0 = handle(Smi::FromInt(0), isolate());
- Handle<Smi> smi1 = handle(Smi::FromInt(1), isolate());
-
+ const AstRawString* temp_name = ast_value_factory_->dot_for_string();
// For each let variable x:
// make statement: temp_x = x.
@@ -2940,7 +2949,7 @@
// Make statement: flag = 1.
{
VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
- Expression* const1 = factory()->NewLiteral(smi1, RelocInfo::kNoPosition);
+ Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
Assignment* assignment = factory()->NewAssignment(
Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition);
Statement* assignment_statement = factory()->NewExpressionStatement(
@@ -2980,7 +2989,7 @@
Expression* compare = NULL;
// Make compare expresion: flag == 1.
{
- Expression* const1 = factory()->NewLiteral(smi1, RelocInfo::kNoPosition);
+ Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
compare = factory()->NewCompareOperation(
Token::EQ, flag_proxy, const1, pos);
@@ -2989,7 +2998,7 @@
// Make statement: flag = 0.
{
VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
- Expression* const0 = factory()->NewLiteral(smi0, RelocInfo::kNoPosition);
+ Expression* const0 = factory()->NewSmiLiteral(0, RelocInfo::kNoPosition);
Assignment* assignment = factory()->NewAssignment(
Token::ASSIGN, flag_proxy, const0, RelocInfo::kNoPosition);
clear_flag = factory()->NewExpressionStatement(assignment, pos);
@@ -3003,7 +3012,7 @@
// Make statement: if (cond) { } else { break; }.
{
Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
- BreakableStatement* t = LookupBreakTarget(Handle<String>(), CHECK_OK);
+ BreakableStatement* t = LookupBreakTarget(NULL, CHECK_OK);
Statement* stop = factory()->NewBreakStatement(t, RelocInfo::kNoPosition);
Statement* if_not_cond_break = factory()->NewIfStatement(
cond, empty, stop, cond->position());
@@ -3034,13 +3043,14 @@
}
-Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
+Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
+ bool* ok) {
// ForStatement ::
// 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
int pos = peek_position();
Statement* init = NULL;
- ZoneStringList let_bindings(1, zone());
+ ZoneList<const AstRawString*> let_bindings(1, zone());
// Create an in-between scope for let-bound iteration variables.
Scope* saved_scope = scope_;
@@ -3053,7 +3063,7 @@
if (peek() != Token::SEMICOLON) {
if (peek() == Token::VAR || peek() == Token::CONST) {
bool is_const = peek() == Token::CONST;
- Handle<String> name;
+ const AstRawString* name = NULL;
VariableDeclarationProperties decl_props = kHasNoInitializers;
Block* variable_statement =
ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name,
@@ -3061,7 +3071,7 @@
bool accept_OF = decl_props == kHasNoInitializers;
ForEachStatement::VisitMode mode;
- if (!name.is_null() && CheckInOrOf(accept_OF, &mode)) {
+ if (name != NULL && CheckInOrOf(accept_OF, &mode)) {
Interface* interface =
is_const ? Interface::NewConst() : Interface::NewValue();
ForEachStatement* loop =
@@ -3089,12 +3099,12 @@
init = variable_statement;
}
} else if (peek() == Token::LET) {
- Handle<String> name;
+ const AstRawString* name = NULL;
VariableDeclarationProperties decl_props = kHasNoInitializers;
Block* variable_statement =
- ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings,
- &name, CHECK_OK);
- bool accept_IN = !name.is_null() && decl_props != kHasInitializers;
+ ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings,
+ &name, CHECK_OK);
+ bool accept_IN = name != NULL && decl_props != kHasInitializers;
bool accept_OF = decl_props == kHasNoInitializers;
ForEachStatement::VisitMode mode;
@@ -3114,14 +3124,8 @@
// TODO(keuchel): Move the temporary variable to the block scope, after
// implementing stack allocated block scoped variables.
- Factory* heap_factory = isolate()->factory();
- Handle<String> tempstr;
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate(), tempstr,
- heap_factory->NewConsString(heap_factory->dot_for_string(), name),
- 0);
- Handle<String> tempname = heap_factory->InternalizeString(tempstr);
- Variable* temp = scope_->DeclarationScope()->NewTemporary(tempname);
+ Variable* temp = scope_->DeclarationScope()->NewTemporary(
+ ast_value_factory_->dot_for_string());
VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
ForEachStatement* loop =
factory()->NewForEachStatement(mode, labels, pos);
@@ -3252,7 +3256,7 @@
}
-void Parser::ReportInvalidCachedData(Handle<String> name, bool* ok) {
+void Parser::ReportInvalidCachedData(const AstRawString* name, bool* ok) {
ParserTraits::ReportMessage("invalid_cached_data_function", name);
*ok = false;
}
@@ -3302,7 +3306,7 @@
FunctionLiteral* Parser::ParseFunctionLiteral(
- Handle<String> function_name,
+ const AstRawString* function_name,
Scanner::Location function_name_location,
bool name_is_strict_reserved,
bool is_generator,
@@ -3325,11 +3329,11 @@
// Anonymous functions were passed either the empty symbol or a null
// handle as the function name. Remember if we were passed a non-empty
// handle to decide whether to invoke function name inference.
- bool should_infer_name = function_name.is_null();
+ bool should_infer_name = function_name == NULL;
// We want a non-null handle as the function name.
if (should_infer_name) {
- function_name = isolate()->factory()->empty_string();
+ function_name = ast_value_factory_->empty_string();
}
int num_parameters = 0;
@@ -3381,7 +3385,9 @@
AstProperties ast_properties;
BailoutReason dont_optimize_reason = kNoReason;
// Parse function body.
- { FunctionState function_state(&function_state_, &scope_, scope, zone());
+ {
+ FunctionState function_state(&function_state_, &scope_, scope, zone(),
+ ast_value_factory_);
scope_->SetScopeName(function_name);
if (is_generator) {
@@ -3394,7 +3400,7 @@
// in a temporary variable, a definition that is used by "yield"
// expressions. This also marks the FunctionState as a generator.
Variable* temp = scope_->DeclarationScope()->NewTemporary(
- isolate()->factory()->dot_generator_object_string());
+ ast_value_factory_->dot_generator_object_string());
function_state.set_generator_object_variable(temp);
}
@@ -3415,7 +3421,7 @@
arity_restriction != FunctionLiteral::SETTER_ARITY);
while (!done) {
bool is_strict_reserved = false;
- Handle<String> param_name =
+ const AstRawString* param_name =
ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
// Store locations for possible future error reports.
@@ -3460,6 +3466,7 @@
VariableMode fvar_mode =
allow_harmony_scoping() && strict_mode() == STRICT ? CONST
: CONST_LEGACY;
+ ASSERT(function_name != NULL);
fvar = new(zone()) Variable(scope_,
function_name, fvar_mode, true /* is valid LHS */,
Variable::NORMAL, kCreatedInitialized, Interface::NewConst());
@@ -3544,6 +3551,7 @@
: FunctionLiteral::kNotGenerator;
FunctionLiteral* function_literal =
factory()->NewFunctionLiteral(function_name,
+ ast_value_factory_,
scope,
body,
materialized_literal_count,
@@ -3565,7 +3573,7 @@
}
-void Parser::SkipLazyFunctionBody(Handle<String> function_name,
+void Parser::SkipLazyFunctionBody(const AstRawString* function_name,
int* materialized_literal_count,
int* expected_property_count,
bool* ok) {
@@ -3644,7 +3652,7 @@
ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
- Handle<String> function_name, int pos, Variable* fvar,
+ const AstRawString* function_name, int pos, Variable* fvar,
Token::Value fvar_init_op, bool is_generator, bool* ok) {
// Everything inside an eagerly parsed function will be parsed eagerly
// (see comment above).
@@ -3667,7 +3675,7 @@
ZoneList<Expression*>* arguments =
new(zone()) ZoneList<Expression*>(0, zone());
CallRuntime* allocation = factory()->NewCallRuntime(
- isolate()->factory()->empty_string(),
+ ast_value_factory_->empty_string(),
Runtime::FunctionForId(Runtime::kHiddenCreateJSGeneratorObject),
arguments, pos);
VariableProxy* init_proxy = factory()->NewVariableProxy(
@@ -3687,10 +3695,10 @@
if (is_generator) {
VariableProxy* get_proxy = factory()->NewVariableProxy(
function_state_->generator_object_variable());
- Expression *undefined = factory()->NewLiteral(
- isolate()->factory()->undefined_value(), RelocInfo::kNoPosition);
- Yield* yield = factory()->NewYield(
- get_proxy, undefined, Yield::FINAL, RelocInfo::kNoPosition);
+ Expression* undefined =
+ factory()->NewUndefinedLiteral(RelocInfo::kNoPosition);
+ Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::FINAL,
+ RelocInfo::kNoPosition);
body->Add(factory()->NewExpressionStatement(
yield, RelocInfo::kNoPosition), zone());
}
@@ -3734,7 +3742,7 @@
int pos = peek_position();
Expect(Token::MOD, CHECK_OK);
// Allow "eval" or "arguments" for backward compatibility.
- Handle<String> name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
+ const AstRawString* name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
if (extension_ != NULL) {
@@ -3743,7 +3751,7 @@
scope_->DeclarationScope()->ForceEagerCompilation();
}
- const Runtime::Function* function = Runtime::FunctionForName(name);
+ const Runtime::Function* function = Runtime::FunctionForName(name->string());
// Check for built-in IS_VAR macro.
if (function != NULL &&
@@ -3771,7 +3779,7 @@
}
// Check that the function is defined if it's an inline runtime call.
- if (function == NULL && name->Get(0) == '_') {
+ if (function == NULL && name->FirstCharacter() == '_') {
ParserTraits::ReportMessage("not_defined", name);
*ok = false;
return NULL;
@@ -3783,8 +3791,7 @@
Literal* Parser::GetLiteralUndefined(int position) {
- return factory()->NewLiteral(
- isolate()->factory()->undefined_value(), position);
+ return factory()->NewUndefinedLiteral(position);
}
@@ -3793,7 +3800,7 @@
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();
+ const AstRawString* name = decl->proxy()->raw_name();
int position = decl->proxy()->position();
Scanner::Location location = position == RelocInfo::kNoPosition
? Scanner::Location::invalid()
@@ -3808,7 +3815,7 @@
// Parser support
-bool Parser::TargetStackContainsLabel(Handle<String> label) {
+bool Parser::TargetStackContainsLabel(const AstRawString* label) {
for (Target* t = target_stack_; t != NULL; t = t->previous()) {
BreakableStatement* stat = t->node()->AsBreakableStatement();
if (stat != NULL && ContainsLabel(stat->labels(), label))
@@ -3818,8 +3825,9 @@
}
-BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
- bool anonymous = label.is_null();
+BreakableStatement* Parser::LookupBreakTarget(const AstRawString* label,
+ bool* ok) {
+ bool anonymous = label == NULL;
for (Target* t = target_stack_; t != NULL; t = t->previous()) {
BreakableStatement* stat = t->node()->AsBreakableStatement();
if (stat == NULL) continue;
@@ -3833,9 +3841,9 @@
}
-IterationStatement* Parser::LookupContinueTarget(Handle<String> label,
+IterationStatement* Parser::LookupContinueTarget(const AstRawString* label,
bool* ok) {
- bool anonymous = label.is_null();
+ bool anonymous = label == NULL;
for (Target* t = target_stack_; t != NULL; t = t->previous()) {
IterationStatement* stat = t->node()->AsIterationStatement();
if (stat == NULL) continue;
@@ -3862,16 +3870,18 @@
void Parser::ThrowPendingError() {
+ ASSERT(ast_value_factory_->IsInternalized());
if (has_pending_error_) {
MessageLocation location(script_,
pending_error_location_.beg_pos,
pending_error_location_.end_pos);
Factory* factory = isolate()->factory();
bool has_arg =
- !pending_error_arg_.is_null() || pending_error_char_arg_ != NULL;
+ pending_error_arg_ != NULL || pending_error_char_arg_ != NULL;
Handle<FixedArray> elements = factory->NewFixedArray(has_arg ? 1 : 0);
- if (!pending_error_arg_.is_null()) {
- elements->set(0, *(pending_error_arg_.ToHandleChecked()));
+ if (pending_error_arg_ != NULL) {
+ Handle<String> arg_string = pending_error_arg_->string();
+ elements->set(0, *arg_string);
} else if (pending_error_char_arg_ != NULL) {
Handle<String> arg_string =
factory->NewStringFromUtf8(CStrVector(pending_error_char_arg_))
@@ -4785,6 +4795,18 @@
bool Parser::Parse() {
ASSERT(info()->function() == NULL);
FunctionLiteral* result = NULL;
+ ast_value_factory_ = info()->ast_value_factory();
+ if (ast_value_factory_ == NULL) {
+ ast_value_factory_ =
+ new AstValueFactory(zone(), isolate()->heap()->HashSeed());
+ }
+ if (allow_natives_syntax() || extension_ != NULL) {
+ // If intrinsics are allowed, the Parser cannot operate independent of the
+ // V8 heap because of Rumtime. Tell the string table to internalize strings
+ // and values right after they're created.
+ ast_value_factory_->Internalize(isolate());
+ }
+
if (info()->is_lazy()) {
ASSERT(!info()->is_eval());
if (info()->shared_info()->is_function()) {
@@ -4810,6 +4832,12 @@
}
}
info()->SetFunction(result);
+ ASSERT(ast_value_factory_->IsInternalized());
+ // info takes ownership of ast_value_factory_.
+ if (info()->ast_value_factory() == NULL) {
+ info()->SetAstValueFactory(ast_value_factory_);
+ }
+ ast_value_factory_ = NULL;
return (result != NULL);
}
diff --git a/src/parser.h b/src/parser.h
index d011161..3d44d58 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -389,7 +389,7 @@
typedef v8::internal::Zone Zone;
// Return types for traversing functions.
- typedef Handle<String> Identifier;
+ typedef const AstRawString* Identifier;
typedef v8::internal::Expression* Expression;
typedef Yield* YieldExpression;
typedef v8::internal::FunctionLiteral* FunctionLiteral;
@@ -421,29 +421,29 @@
}
// Helper functions for recursive descent.
- bool IsEvalOrArguments(Handle<String> identifier) const;
+ bool IsEvalOrArguments(const AstRawString* identifier) const;
// Returns true if the expression is of type "this.foo".
static bool IsThisProperty(Expression* expression);
static bool IsIdentifier(Expression* expression);
- static Handle<String> AsIdentifier(Expression* expression) {
+ static const AstRawString* AsIdentifier(Expression* expression) {
ASSERT(IsIdentifier(expression));
- return expression->AsVariableProxy()->name();
+ return expression->AsVariableProxy()->raw_name();
}
static bool IsBoilerplateProperty(ObjectLiteral::Property* property) {
return ObjectLiteral::IsBoilerplateProperty(property);
}
- static bool IsArrayIndex(Handle<String> string, uint32_t* index) {
- return !string.is_null() && string->AsArrayIndex(index);
+ static bool IsArrayIndex(const AstRawString* string, uint32_t* index) {
+ return string->AsArrayIndex(index);
}
// Functions for encapsulating the differences between parsing and preparsing;
// operations interleaved with the recursive descent.
- static void PushLiteralName(FuncNameInferrer* fni, Handle<String> id) {
+ static void PushLiteralName(FuncNameInferrer* fni, const AstRawString* id) {
fni->PushLiteralName(id);
}
void PushPropertyName(FuncNameInferrer* fni, Expression* expression);
@@ -501,16 +501,17 @@
// type. The first argument may be null (in the handle sense) in
// which case no arguments are passed to the constructor.
Expression* NewThrowSyntaxError(
- const char* type, Handle<Object> arg, int pos);
+ const char* type, const AstRawString* arg, int pos);
// Generate AST node that throws a TypeError with the given
// type. Both arguments must be non-null (in the handle sense).
- Expression* NewThrowTypeError(const char* type, Handle<Object> arg, int pos);
+ Expression* NewThrowTypeError(const char* type, const AstRawString* arg,
+ int pos);
// Generic AST generator for throwing errors from compiled code.
Expression* NewThrowError(
- Handle<String> constructor, const char* type,
- Vector<Handle<Object> > arguments, int pos);
+ const AstRawString* constructor, const char* type,
+ const AstRawString* arg, int pos);
// Reporting errors.
void ReportMessageAt(Scanner::Location source_location,
@@ -518,16 +519,19 @@
const char* arg = NULL,
bool is_reference_error = false);
void ReportMessage(const char* message,
- MaybeHandle<String> arg,
+ const char* arg = NULL,
+ bool is_reference_error = false);
+ void ReportMessage(const char* message,
+ const AstRawString* arg,
bool is_reference_error = false);
void ReportMessageAt(Scanner::Location source_location,
const char* message,
- MaybeHandle<String> arg,
+ const AstRawString* arg,
bool is_reference_error = false);
// "null" return type creators.
- static Handle<String> EmptyIdentifier() {
- return Handle<String>();
+ static const AstRawString* EmptyIdentifier() {
+ return NULL;
}
static Expression* EmptyExpression() {
return NULL;
@@ -545,16 +549,16 @@
AstNodeFactory<AstConstructionVisitor>* factory);
// Producing data during the recursive descent.
- Handle<String> GetSymbol(Scanner* scanner = NULL);
- Handle<String> NextLiteralString(Scanner* scanner,
- PretenureFlag tenured);
+ const AstRawString* GetSymbol(Scanner* scanner);
+ const AstRawString* GetNextSymbol(Scanner* scanner);
+
Expression* ThisExpression(Scope* scope,
AstNodeFactory<AstConstructionVisitor>* factory);
Literal* ExpressionFromLiteral(
Token::Value token, int pos, Scanner* scanner,
AstNodeFactory<AstConstructionVisitor>* factory);
Expression* ExpressionFromIdentifier(
- Handle<String> name, int pos, Scope* scope,
+ const AstRawString* name, int pos, Scope* scope,
AstNodeFactory<AstConstructionVisitor>* factory);
Expression* ExpressionFromString(
int pos, Scanner* scanner,
@@ -572,7 +576,7 @@
// Temporary glue; these functions will move to ParserBase.
Expression* ParseV8Intrinsic(bool* ok);
FunctionLiteral* ParseFunctionLiteral(
- Handle<String> name,
+ const AstRawString* name,
Scanner::Location function_name_location,
bool name_is_strict_reserved,
bool is_generator,
@@ -644,7 +648,7 @@
Handle<String> source);
// Report syntax error
- void ReportInvalidCachedData(Handle<String> name, bool* ok);
+ void ReportInvalidCachedData(const AstRawString* name, bool* ok);
void SetCachedData(ScriptData** data,
CachedDataMode cached_data_mode) {
@@ -671,8 +675,10 @@
// for failure at the call sites.
void* ParseSourceElements(ZoneList<Statement*>* processor, int end_token,
bool is_eval, bool is_global, bool* ok);
- Statement* ParseModuleElement(ZoneStringList* labels, bool* ok);
- Statement* ParseModuleDeclaration(ZoneStringList* names, bool* ok);
+ Statement* ParseModuleElement(ZoneList<const AstRawString*>* labels,
+ bool* ok);
+ Statement* ParseModuleDeclaration(ZoneList<const AstRawString*>* names,
+ bool* ok);
Module* ParseModule(bool* ok);
Module* ParseModuleLiteral(bool* ok);
Module* ParseModulePath(bool* ok);
@@ -681,38 +687,45 @@
Module* ParseModuleSpecifier(bool* ok);
Block* ParseImportDeclaration(bool* ok);
Statement* ParseExportDeclaration(bool* ok);
- Statement* ParseBlockElement(ZoneStringList* labels, bool* ok);
- Statement* ParseStatement(ZoneStringList* labels, bool* ok);
- Statement* ParseFunctionDeclaration(ZoneStringList* names, bool* ok);
+ Statement* ParseBlockElement(ZoneList<const AstRawString*>* labels, bool* ok);
+ Statement* ParseStatement(ZoneList<const AstRawString*>* labels, bool* ok);
+ Statement* ParseFunctionDeclaration(ZoneList<const AstRawString*>* names,
+ bool* ok);
Statement* ParseNativeDeclaration(bool* ok);
- Block* ParseBlock(ZoneStringList* labels, bool* ok);
+ Block* ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok);
Block* ParseVariableStatement(VariableDeclarationContext var_context,
- ZoneStringList* names,
+ ZoneList<const AstRawString*>* names,
bool* ok);
Block* ParseVariableDeclarations(VariableDeclarationContext var_context,
VariableDeclarationProperties* decl_props,
- ZoneStringList* names,
- Handle<String>* out,
+ ZoneList<const AstRawString*>* names,
+ const AstRawString** out,
bool* ok);
- Statement* ParseExpressionOrLabelledStatement(ZoneStringList* labels,
- bool* ok);
- IfStatement* ParseIfStatement(ZoneStringList* labels, bool* ok);
+ Statement* ParseExpressionOrLabelledStatement(
+ ZoneList<const AstRawString*>* labels, bool* ok);
+ IfStatement* ParseIfStatement(ZoneList<const AstRawString*>* labels,
+ bool* ok);
Statement* ParseContinueStatement(bool* ok);
- Statement* ParseBreakStatement(ZoneStringList* labels, bool* ok);
+ Statement* ParseBreakStatement(ZoneList<const AstRawString*>* labels,
+ bool* ok);
Statement* ParseReturnStatement(bool* ok);
- Statement* ParseWithStatement(ZoneStringList* labels, bool* ok);
+ Statement* ParseWithStatement(ZoneList<const AstRawString*>* labels,
+ bool* ok);
CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok);
- SwitchStatement* ParseSwitchStatement(ZoneStringList* labels, bool* ok);
- DoWhileStatement* ParseDoWhileStatement(ZoneStringList* labels, bool* ok);
- WhileStatement* ParseWhileStatement(ZoneStringList* labels, bool* ok);
- Statement* ParseForStatement(ZoneStringList* labels, bool* ok);
+ SwitchStatement* ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
+ bool* ok);
+ DoWhileStatement* ParseDoWhileStatement(ZoneList<const AstRawString*>* labels,
+ bool* ok);
+ WhileStatement* ParseWhileStatement(ZoneList<const AstRawString*>* labels,
+ bool* ok);
+ Statement* ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok);
Statement* ParseThrowStatement(bool* ok);
Expression* MakeCatchContext(Handle<String> id, VariableProxy* value);
TryStatement* ParseTryStatement(bool* ok);
DebuggerStatement* ParseDebuggerStatement(bool* ok);
// Support for hamony block scoped bindings.
- Block* ParseScopedBlock(ZoneStringList* labels, bool* ok);
+ Block* ParseScopedBlock(ZoneList<const AstRawString*>* labels, bool* ok);
// Initialize the components of a for-in / for-of statement.
void InitializeForEachStatement(ForEachStatement* stmt,
@@ -720,12 +733,12 @@
Expression* subject,
Statement* body);
Statement* DesugarLetBindingsInForStatement(
- Scope* inner_scope, ZoneStringList* names, ForStatement* loop,
- Statement* init, Expression* cond, Statement* next, Statement* body,
- bool* ok);
+ Scope* inner_scope, ZoneList<const AstRawString*>* names,
+ ForStatement* loop, Statement* init, Expression* cond, Statement* next,
+ Statement* body, bool* ok);
FunctionLiteral* ParseFunctionLiteral(
- Handle<String> name,
+ const AstRawString* name,
Scanner::Location function_name_location,
bool name_is_strict_reserved,
bool is_generator,
@@ -754,14 +767,14 @@
void CheckConflictingVarDeclarations(Scope* scope, bool* ok);
// Parser support
- VariableProxy* NewUnresolved(Handle<String> name,
+ VariableProxy* NewUnresolved(const AstRawString* name,
VariableMode mode,
Interface* interface);
void Declare(Declaration* declaration, bool resolve, bool* ok);
- bool TargetStackContainsLabel(Handle<String> label);
- BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok);
- IterationStatement* LookupContinueTarget(Handle<String> label, bool* ok);
+ bool TargetStackContainsLabel(const AstRawString* label);
+ BreakableStatement* LookupBreakTarget(const AstRawString* label, bool* ok);
+ IterationStatement* LookupContinueTarget(const AstRawString* label, bool* ok);
void RegisterTargetUse(Label* target, Target* stop);
@@ -771,7 +784,7 @@
// Skip over a lazy function, either using cached data if we have it, or
// by parsing the function with PreParser. Consumes the ending }.
- void SkipLazyFunctionBody(Handle<String> function_name,
+ void SkipLazyFunctionBody(const AstRawString* function_name,
int* materialized_literal_count,
int* expected_property_count,
bool* ok);
@@ -780,12 +793,9 @@
SingletonLogger* logger);
// Consumes the ending }.
- ZoneList<Statement*>* ParseEagerFunctionBody(Handle<String> function_name,
- int pos,
- Variable* fvar,
- Token::Value fvar_init_op,
- bool is_generator,
- bool* ok);
+ ZoneList<Statement*>* ParseEagerFunctionBody(
+ const AstRawString* function_name, int pos, Variable* fvar,
+ Token::Value fvar_init_op, bool is_generator, bool* ok);
void ThrowPendingError();
@@ -798,6 +808,7 @@
Target* target_stack_; // for break, continue statements
ScriptData** cached_data_;
CachedDataMode cached_data_mode_;
+ AstValueFactory* ast_value_factory_;
CompilationInfo* info_;
@@ -805,7 +816,7 @@
bool has_pending_error_;
Scanner::Location pending_error_location_;
const char* pending_error_message_;
- MaybeHandle<String> pending_error_arg_;
+ const AstRawString* pending_error_arg_;
const char* pending_error_char_arg_;
bool pending_error_is_reference_error_;
};
diff --git a/src/preparser.h b/src/preparser.h
index f8e6203..753ff1b 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -150,7 +150,8 @@
FunctionState** function_state_stack,
typename Traits::Type::Scope** scope_stack,
typename Traits::Type::Scope* scope,
- typename Traits::Type::Zone* zone = NULL);
+ typename Traits::Type::Zone* zone = NULL,
+ AstValueFactory* ast_value_factory = NULL);
~FunctionState();
int NextMaterializedLiteralIndex() {
@@ -395,7 +396,9 @@
void ReportMessageAt(Scanner::Location location, const char* message,
bool is_reference_error = false) {
- Traits::ReportMessageAt(location, message, NULL, is_reference_error);
+ Traits::ReportMessageAt(location, message,
+ reinterpret_cast<const char*>(NULL),
+ is_reference_error);
}
void ReportUnexpectedToken(Token::Value token);
@@ -782,9 +785,9 @@
class PreParserFactory {
public:
- explicit PreParserFactory(void* extra_param) {}
- PreParserExpression NewLiteral(PreParserIdentifier identifier,
- int pos) {
+ explicit PreParserFactory(void* extra_param1, void* extra_param2) {}
+ PreParserExpression NewStringLiteral(PreParserIdentifier identifier,
+ int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewNumberLiteral(double number,
@@ -1036,8 +1039,8 @@
// Producing data during the recursive descent.
PreParserIdentifier GetSymbol(Scanner* scanner);
- static PreParserIdentifier NextLiteralString(Scanner* scanner,
- PretenureFlag tenured) {
+
+ static PreParserIdentifier GetNextSymbol(Scanner* scanner) {
return PreParserIdentifier::Default();
}
@@ -1225,7 +1228,8 @@
FunctionState** function_state_stack,
typename Traits::Type::Scope** scope_stack,
typename Traits::Type::Scope* scope,
- typename Traits::Type::Zone* extra_param)
+ typename Traits::Type::Zone* extra_param,
+ AstValueFactory* ast_value_factory)
: next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
next_handler_index_(0),
expected_property_count_(0),
@@ -1237,7 +1241,7 @@
outer_scope_(*scope_stack),
saved_ast_node_id_(0),
extra_param_(extra_param),
- factory_(extra_param) {
+ factory_(extra_param, ast_value_factory) {
*scope_stack_ = scope;
*function_state_stack = this;
Traits::SetUpFunctionState(this, extra_param);
@@ -1363,14 +1367,14 @@
int literal_index = function_state_->NextMaterializedLiteralIndex();
- IdentifierT js_pattern = this->NextLiteralString(scanner(), TENURED);
+ IdentifierT js_pattern = this->GetNextSymbol(scanner());
if (!scanner()->ScanRegExpFlags()) {
Next();
ReportMessage("invalid_regexp_flags");
*ok = false;
return Traits::EmptyExpression();
}
- IdentifierT js_flags = this->NextLiteralString(scanner(), TENURED);
+ IdentifierT js_flags = this->GetNextSymbol(scanner());
Next();
return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
}
@@ -1615,7 +1619,7 @@
}
// Failed to parse as get/set property, so it's just a normal property
// (which might be called "get" or "set" or something else).
- key = factory()->NewLiteral(id, next_pos);
+ key = factory()->NewStringLiteral(id, next_pos);
break;
}
case Token::STRING: {
@@ -1627,7 +1631,7 @@
key = factory()->NewNumberLiteral(index, next_pos);
break;
}
- key = factory()->NewLiteral(string, next_pos);
+ key = factory()->NewStringLiteral(string, next_pos);
break;
}
case Token::NUMBER: {
@@ -1640,7 +1644,7 @@
if (Token::IsKeyword(next)) {
Consume(next);
IdentifierT string = this->GetSymbol(scanner_);
- key = factory()->NewLiteral(string, next_pos);
+ key = factory()->NewStringLiteral(string, next_pos);
} else {
Token::Value next = Next();
ReportUnexpectedToken(next);
@@ -2009,7 +2013,7 @@
int pos = position();
IdentifierT name = ParseIdentifierName(CHECK_OK);
result = factory()->NewProperty(
- result, factory()->NewLiteral(name, pos), pos);
+ result, factory()->NewStringLiteral(name, pos), pos);
if (fni_ != NULL) this->PushLiteralName(fni_, name);
break;
}
@@ -2132,7 +2136,7 @@
int pos = position();
IdentifierT name = ParseIdentifierName(CHECK_OK);
expression = factory()->NewProperty(
- expression, factory()->NewLiteral(name, pos), pos);
+ expression, factory()->NewStringLiteral(name, pos), pos);
if (fni_ != NULL) {
this->PushLiteralName(fni_, name);
}
diff --git a/src/prettyprinter.cc b/src/prettyprinter.cc
index ecfb015..c0961f2 100644
--- a/src/prettyprinter.cc
+++ b/src/prettyprinter.cc
@@ -6,6 +6,7 @@
#include "src/v8.h"
+#include "src/ast-value-factory.h"
#include "src/platform.h"
#include "src/prettyprinter.h"
#include "src/scopes.h"
@@ -133,7 +134,7 @@
void PrettyPrinter::VisitContinueStatement(ContinueStatement* node) {
Print("continue");
- ZoneStringList* labels = node->target()->labels();
+ ZoneList<const AstRawString*>* labels = node->target()->labels();
if (labels != NULL) {
Print(" ");
ASSERT(labels->length() > 0); // guaranteed to have at least one entry
@@ -145,7 +146,7 @@
void PrettyPrinter::VisitBreakStatement(BreakStatement* node) {
Print("break");
- ZoneStringList* labels = node->target()->labels();
+ ZoneList<const AstRawString*>* labels = node->target()->labels();
if (labels != NULL) {
Print(" ");
ASSERT(labels->length() > 0); // guaranteed to have at least one entry
@@ -524,7 +525,7 @@
}
-void PrettyPrinter::PrintLabels(ZoneStringList* labels) {
+void PrettyPrinter::PrintLabels(ZoneList<const AstRawString*>* labels) {
if (labels != NULL) {
for (int i = 0; i < labels->length(); i++) {
PrintLiteral(labels->at(i), false);
@@ -582,6 +583,11 @@
}
+void PrettyPrinter::PrintLiteral(const AstRawString* value, bool quote) {
+ PrintLiteral(value->string(), quote);
+}
+
+
void PrettyPrinter::PrintParameters(Scope* scope) {
Print("(");
for (int i = 0; i < scope->num_parameters(); i++) {
@@ -676,7 +682,7 @@
}
-void AstPrinter::PrintLabelsIndented(ZoneStringList* labels) {
+void AstPrinter::PrintLabelsIndented(ZoneList<const AstRawString*>* labels) {
if (labels == NULL || labels->length() == 0) return;
PrintIndented("LABELS ");
PrintLabels(labels);
diff --git a/src/prettyprinter.h b/src/prettyprinter.h
index 585734e..de40aae 100644
--- a/src/prettyprinter.h
+++ b/src/prettyprinter.h
@@ -44,9 +44,10 @@
const char* Output() const { return output_; }
virtual void PrintStatements(ZoneList<Statement*>* statements);
- void PrintLabels(ZoneStringList* labels);
+ void PrintLabels(ZoneList<const AstRawString*>* labels);
virtual void PrintArguments(ZoneList<Expression*>* arguments);
void PrintLiteral(Handle<Object> value, bool quote);
+ void PrintLiteral(const AstRawString* value, bool quote);
void PrintParameters(Scope* scope);
void PrintDeclarations(ZoneList<Declaration*>* declarations);
void PrintFunctionLiteral(FunctionLiteral* function);
@@ -83,7 +84,7 @@
void PrintLiteralWithModeIndented(const char* info,
Variable* var,
Handle<Object> value);
- void PrintLabelsIndented(ZoneStringList* labels);
+ void PrintLabelsIndented(ZoneList<const AstRawString*>* labels);
void inc_indent() { indent_++; }
void dec_indent() { indent_--; }
diff --git a/src/rewriter.cc b/src/rewriter.cc
index c92ccda..8ec5c54 100644
--- a/src/rewriter.cc
+++ b/src/rewriter.cc
@@ -20,7 +20,9 @@
result_assigned_(false),
is_set_(false),
in_try_(false),
- factory_(zone) {
+ // Passing a null AstValueFactory is fine, because Processor doesn't
+ // need to create strings or literals.
+ factory_(zone, NULL) {
InitializeAstVisitor(zone);
}
@@ -234,8 +236,10 @@
ZoneList<Statement*>* body = function->body();
if (!body->is_empty()) {
- Variable* result = scope->NewTemporary(
- info->isolate()->factory()->dot_result_string());
+ Variable* result =
+ scope->NewTemporary(info->ast_value_factory()->dot_result_string());
+ // The name string must be internalized at this point.
+ ASSERT(!result->name().is_null());
Processor processor(result, info->zone());
processor.Process(body);
if (processor.HasStackOverflow()) return false;
@@ -250,7 +254,7 @@
// coincides with the end of the with scope which is the position of '1'.
int pos = function->end_position();
VariableProxy* result_proxy = processor.factory()->NewVariableProxy(
- result->name(), false, result->interface(), pos);
+ result->raw_name(), false, result->interface(), pos);
result_proxy->BindTo(result);
Statement* result_statement =
processor.factory()->NewReturnStatement(result_proxy, pos);
diff --git a/src/runtime-profiler.cc b/src/runtime-profiler.cc
index dddcad0..cba563f 100644
--- a/src/runtime-profiler.cc
+++ b/src/runtime-profiler.cc
@@ -110,7 +110,9 @@
}
-void RuntimeProfiler::AttemptOnStackReplacement(JSFunction* function) {
+void RuntimeProfiler::AttemptOnStackReplacement(JSFunction* function,
+ int loop_nesting_levels) {
+ SharedFunctionInfo* shared = function->shared();
// See AlwaysFullCompiler (in compiler.cc) comment on why we need
// Debug::has_break_points().
if (!FLAG_use_osr ||
@@ -119,7 +121,6 @@
return;
}
- SharedFunctionInfo* shared = function->shared();
// If the code is not optimizable, don't try OSR.
if (!shared->code()->optimizable()) return;
@@ -137,7 +138,9 @@
PrintF("]\n");
}
- BackEdgeTable::Patch(isolate_, shared->code());
+ for (int i = 0; i < loop_nesting_levels; i++) {
+ BackEdgeTable::Patch(isolate_, shared->code());
+ }
}
@@ -175,14 +178,8 @@
if (shared_code->kind() != Code::FUNCTION) continue;
if (function->IsInOptimizationQueue()) continue;
- if (FLAG_always_osr &&
- shared_code->allow_osr_at_loop_nesting_level() == 0) {
- // Testing mode: always try an OSR compile for every function.
- for (int i = 0; i < Code::kMaxLoopNestingMarker; i++) {
- // TODO(titzer): fix AttemptOnStackReplacement to avoid this dumb loop.
- shared_code->set_allow_osr_at_loop_nesting_level(i);
- AttemptOnStackReplacement(function);
- }
+ if (FLAG_always_osr) {
+ AttemptOnStackReplacement(function, Code::kMaxLoopNestingMarker);
// Fall through and do a normal optimized compile as well.
} else if (!frame->is_optimized() &&
(function->IsMarkedForOptimization() ||
@@ -196,12 +193,7 @@
if (shared_code->CodeSize() > allowance) {
if (ticks < 255) shared_code->set_profiler_ticks(ticks + 1);
} else {
- int nesting = shared_code->allow_osr_at_loop_nesting_level();
- if (nesting < Code::kMaxLoopNestingMarker) {
- int new_nesting = nesting + 1;
- shared_code->set_allow_osr_at_loop_nesting_level(new_nesting);
- AttemptOnStackReplacement(function);
- }
+ AttemptOnStackReplacement(function);
}
continue;
}
diff --git a/src/runtime-profiler.h b/src/runtime-profiler.h
index fa8352d..14ced76 100644
--- a/src/runtime-profiler.h
+++ b/src/runtime-profiler.h
@@ -23,7 +23,7 @@
void NotifyICChanged() { any_ic_changed_ = true; }
- void AttemptOnStackReplacement(JSFunction* function);
+ void AttemptOnStackReplacement(JSFunction* function, int nesting_levels = 1);
private:
void Optimize(JSFunction* function, const char* reason);
diff --git a/src/runtime.cc b/src/runtime.cc
index 3cb6fe2..6d7fca9 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -310,7 +310,7 @@
// computed properties have been assigned so that we can generate
// constant function properties.
if (should_transform && !has_function_literal) {
- JSObject::TransformToFastProperties(
+ JSObject::MigrateSlowToFast(
boilerplate, boilerplate->map()->unused_property_fields());
}
@@ -5055,7 +5055,7 @@
// DefineAccessor checks access rights.
JSObject::DefineAccessor(obj, name, getter, setter, attr);
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
- if (fast) JSObject::TransformToFastProperties(obj, 0);
+ if (fast) JSObject::MigrateSlowToFast(obj, 0);
return isolate->heap()->undefined_value();
}
@@ -6036,7 +6036,7 @@
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
if (object->IsJSObject() && !object->IsGlobalObject()) {
- JSObject::TransformToFastProperties(Handle<JSObject>::cast(object), 0);
+ JSObject::MigrateSlowToFast(Handle<JSObject>::cast(object), 0);
}
return *object;
}
@@ -8530,16 +8530,11 @@
if (args.length() == 2 &&
unoptimized->kind() == Code::FUNCTION) {
CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
- if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("osr"))) {
+ if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("osr")) && FLAG_use_osr) {
// Start patching from the currently patched loop nesting level.
- int current_level = unoptimized->allow_osr_at_loop_nesting_level();
- ASSERT(BackEdgeTable::Verify(isolate, unoptimized, current_level));
- if (FLAG_use_osr) {
- for (int i = current_level + 1; i <= Code::kMaxLoopNestingMarker; i++) {
- unoptimized->set_allow_osr_at_loop_nesting_level(i);
- isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
- }
- }
+ ASSERT(BackEdgeTable::Verify(isolate, unoptimized));
+ isolate->runtime_profiler()->AttemptOnStackReplacement(
+ *function, Code::kMaxLoopNestingMarker);
} else if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("concurrent")) &&
isolate->concurrent_recompilation_enabled()) {
function->MarkForConcurrentOptimization();
@@ -9138,6 +9133,23 @@
// In Win64 they are assigned to a hidden first argument.
return result;
}
+#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
+// For x32 a 128-bit struct return is done as rax and rdx from the ObjectPair
+// are used in the full codegen and Crankshaft compiler. An alternative is
+// using uint64_t and modifying full codegen and Crankshaft compiler.
+struct ObjectPair {
+ Object* x;
+ uint32_t x_upper;
+ Object* y;
+ uint32_t y_upper;
+};
+
+
+static inline ObjectPair MakePair(Object* x, Object* y) {
+ ObjectPair result = {x, 0, y, 0};
+ // Pointers x and y returned in rax and rdx, in x32-abi.
+ return result;
+}
#else
typedef uint64_t ObjectPair;
static inline ObjectPair MakePair(Object* x, Object* y) {
diff --git a/src/sampler.cc b/src/sampler.cc
index aedf75f..82fe27d 100644
--- a/src/sampler.cc
+++ b/src/sampler.cc
@@ -596,7 +596,7 @@
SafeStackFrameIterator it(isolate, regs.fp, regs.sp, js_entry_sp);
top_frame_type = it.top_frame_type();
- int i = 0;
+ unsigned i = 0;
while (!it.done() && i < TickSample::kMaxFramesCount) {
stack[i++] = it.frame()->pc();
it.Advance();
diff --git a/src/sampler.h b/src/sampler.h
index fe94a02..80fe5a9 100644
--- a/src/sampler.h
+++ b/src/sampler.h
@@ -44,10 +44,11 @@
Address tos; // Top stack value (*sp).
Address external_callback;
};
- static const int kMaxFramesCount = 64;
+ static const unsigned kMaxFramesCountLog2 = 8;
+ static const unsigned kMaxFramesCount = (1 << kMaxFramesCountLog2) - 1;
Address stack[kMaxFramesCount]; // Call stack.
TimeTicks timestamp;
- int frames_count : 8; // Number of captured frames.
+ unsigned frames_count : kMaxFramesCountLog2; // Number of captured frames.
bool has_external_callback : 1;
StackFrame::Type top_frame_type : 4;
};
diff --git a/src/scanner.cc b/src/scanner.cc
index 4e2e8fd..df19ee8 100644
--- a/src/scanner.cc
+++ b/src/scanner.cc
@@ -9,6 +9,7 @@
#include "src/v8.h"
#include "include/v8stdint.h"
+#include "src/ast-value-factory.h"
#include "src/char-predicates-inl.h"
#include "src/conversions-inl.h"
#include "src/list-inl.h"
@@ -1093,26 +1094,19 @@
}
-Handle<String> Scanner::AllocateNextLiteralString(Isolate* isolate,
- PretenureFlag tenured) {
- if (is_next_literal_one_byte()) {
- return isolate->factory()->NewStringFromOneByte(
- next_literal_one_byte_string(), tenured).ToHandleChecked();
- } else {
- return isolate->factory()->NewStringFromTwoByte(
- next_literal_two_byte_string(), tenured).ToHandleChecked();
+const AstRawString* Scanner::CurrentSymbol(AstValueFactory* ast_value_factory) {
+ if (is_literal_one_byte()) {
+ return ast_value_factory->GetOneByteString(literal_one_byte_string());
}
+ return ast_value_factory->GetTwoByteString(literal_two_byte_string());
}
-Handle<String> Scanner::AllocateInternalizedString(Isolate* isolate) {
- if (is_literal_one_byte()) {
- return isolate->factory()->InternalizeOneByteString(
- literal_one_byte_string());
- } else {
- return isolate->factory()->InternalizeTwoByteString(
- literal_two_byte_string());
+const AstRawString* Scanner::NextSymbol(AstValueFactory* ast_value_factory) {
+ if (is_next_literal_one_byte()) {
+ return ast_value_factory->GetOneByteString(next_literal_one_byte_string());
}
+ return ast_value_factory->GetTwoByteString(next_literal_two_byte_string());
}
diff --git a/src/scanner.h b/src/scanner.h
index 2979082..8fee1b1 100644
--- a/src/scanner.h
+++ b/src/scanner.h
@@ -21,6 +21,8 @@
namespace internal {
+class AstRawString;
+class AstValueFactory;
class ParserRecorder;
@@ -376,9 +378,8 @@
return next_.literal_chars->is_contextual_keyword(keyword);
}
- Handle<String> AllocateNextLiteralString(Isolate* isolate,
- PretenureFlag tenured);
- Handle<String> AllocateInternalizedString(Isolate* isolate);
+ const AstRawString* CurrentSymbol(AstValueFactory* ast_value_factory);
+ const AstRawString* NextSymbol(AstValueFactory* ast_value_factory);
double DoubleValue();
bool UnescapedLiteralMatches(const char* data, int length) {
diff --git a/src/scopeinfo.cc b/src/scopeinfo.cc
index d84c5bf..bce8244 100644
--- a/src/scopeinfo.cc
+++ b/src/scopeinfo.cc
@@ -540,7 +540,7 @@
for (Interface::Iterator it = interface->iterator();
!it.done(); it.Advance(), ++i) {
Variable* var = scope->LookupLocal(it.name());
- info->set_name(i, *it.name());
+ info->set_name(i, *(it.name()->string()));
info->set_mode(i, var->mode());
ASSERT((var->mode() == MODULE) == (it.interface()->IsModule()));
if (var->mode() == MODULE) {
diff --git a/src/scopes.cc b/src/scopes.cc
index 497f794..2b3c07a 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -24,34 +24,28 @@
// use. Because a Variable holding a handle with the same location exists
// this is ensured.
-static bool Match(void* key1, void* key2) {
- String* name1 = *reinterpret_cast<String**>(key1);
- String* name2 = *reinterpret_cast<String**>(key2);
- ASSERT(name1->IsInternalizedString());
- ASSERT(name2->IsInternalizedString());
- return name1 == name2;
-}
-
-
VariableMap::VariableMap(Zone* zone)
- : ZoneHashMap(Match, 8, ZoneAllocationPolicy(zone)),
+ : ZoneHashMap(ZoneHashMap::PointersMatch, 8, ZoneAllocationPolicy(zone)),
zone_(zone) {}
VariableMap::~VariableMap() {}
Variable* VariableMap::Declare(
Scope* scope,
- Handle<String> name,
+ const AstRawString* name,
VariableMode mode,
bool is_valid_lhs,
Variable::Kind kind,
InitializationFlag initialization_flag,
Interface* interface) {
- Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), true,
- ZoneAllocationPolicy(zone()));
+ // AstRawStrings are unambiguous, i.e., the same string is always represented
+ // by the same AstRawString*.
+ // FIXME(marja): fix the type of Lookup.
+ Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(),
+ true, ZoneAllocationPolicy(zone()));
if (p->value == NULL) {
// The variable has not been declared yet -> insert it.
- ASSERT(p->key == name.location());
+ ASSERT(p->key == name);
p->value = new(zone()) Variable(scope,
name,
mode,
@@ -64,11 +58,11 @@
}
-Variable* VariableMap::Lookup(Handle<String> name) {
- Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), false,
- ZoneAllocationPolicy(NULL));
+Variable* VariableMap::Lookup(const AstRawString* name) {
+ Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(),
+ false, ZoneAllocationPolicy(NULL));
if (p != NULL) {
- ASSERT(*reinterpret_cast<String**>(p->key) == *name);
+ ASSERT(reinterpret_cast<const AstRawString*>(p->key) == name);
ASSERT(p->value != NULL);
return reinterpret_cast<Variable*>(p->value);
}
@@ -79,7 +73,8 @@
// ----------------------------------------------------------------------------
// Implementation of Scope
-Scope::Scope(Scope* outer_scope, ScopeType scope_type, Zone* zone)
+Scope::Scope(Scope* outer_scope, ScopeType scope_type,
+ AstValueFactory* ast_value_factory, Zone* zone)
: isolate_(zone->isolate()),
inner_scopes_(4, zone),
variables_(zone),
@@ -92,6 +87,7 @@
(scope_type == MODULE_SCOPE || scope_type == GLOBAL_SCOPE)
? Interface::NewModule(zone) : NULL),
already_resolved_(false),
+ ast_value_factory_(ast_value_factory),
zone_(zone) {
SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null());
// The outermost scope must be a global scope.
@@ -103,6 +99,7 @@
Scope::Scope(Scope* inner_scope,
ScopeType scope_type,
Handle<ScopeInfo> scope_info,
+ AstValueFactory* value_factory,
Zone* zone)
: isolate_(zone->isolate()),
inner_scopes_(4, zone),
@@ -114,6 +111,7 @@
decls_(4, zone),
interface_(NULL),
already_resolved_(true),
+ ast_value_factory_(value_factory),
zone_(zone) {
SetDefaults(scope_type, NULL, scope_info);
if (!scope_info.is_null()) {
@@ -126,7 +124,8 @@
}
-Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name, Zone* zone)
+Scope::Scope(Scope* inner_scope, const AstRawString* catch_variable_name,
+ AstValueFactory* value_factory, Zone* zone)
: isolate_(zone->isolate()),
inner_scopes_(1, zone),
variables_(zone),
@@ -137,6 +136,7 @@
decls_(0, zone),
interface_(NULL),
already_resolved_(true),
+ ast_value_factory_(value_factory),
zone_(zone) {
SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null());
AddInnerScope(inner_scope);
@@ -157,7 +157,7 @@
Handle<ScopeInfo> scope_info) {
outer_scope_ = outer_scope;
scope_type_ = scope_type;
- scope_name_ = isolate_->factory()->empty_string();
+ scope_name_ = ast_value_factory_->empty_string();
dynamics_ = NULL;
receiver_ = NULL;
function_ = NULL;
@@ -199,6 +199,7 @@
Scope* with_scope = new(zone) Scope(current_scope,
WITH_SCOPE,
Handle<ScopeInfo>::null(),
+ global_scope->ast_value_factory_,
zone);
current_scope = with_scope;
// All the inner scopes are inside a with.
@@ -211,30 +212,36 @@
current_scope = new(zone) Scope(current_scope,
GLOBAL_SCOPE,
Handle<ScopeInfo>(scope_info),
+ global_scope->ast_value_factory_,
zone);
} else if (context->IsModuleContext()) {
ScopeInfo* scope_info = ScopeInfo::cast(context->module()->scope_info());
current_scope = new(zone) Scope(current_scope,
MODULE_SCOPE,
Handle<ScopeInfo>(scope_info),
+ global_scope->ast_value_factory_,
zone);
} else if (context->IsFunctionContext()) {
ScopeInfo* scope_info = context->closure()->shared()->scope_info();
current_scope = new(zone) Scope(current_scope,
FUNCTION_SCOPE,
Handle<ScopeInfo>(scope_info),
+ global_scope->ast_value_factory_,
zone);
} else if (context->IsBlockContext()) {
ScopeInfo* scope_info = ScopeInfo::cast(context->extension());
current_scope = new(zone) Scope(current_scope,
BLOCK_SCOPE,
Handle<ScopeInfo>(scope_info),
+ global_scope->ast_value_factory_,
zone);
} else {
ASSERT(context->IsCatchContext());
String* name = String::cast(context->extension());
- current_scope = new(zone) Scope(
- current_scope, Handle<String>(name), zone);
+ current_scope = new (zone) Scope(
+ current_scope,
+ global_scope->ast_value_factory_->GetString(Handle<String>(name)),
+ global_scope->ast_value_factory_, zone);
}
if (contains_with) current_scope->RecordWithStatement();
if (innermost_scope == NULL) innermost_scope = current_scope;
@@ -266,7 +273,9 @@
// Allocate the variables.
{
- AstNodeFactory<AstNullVisitor> ast_node_factory(info->zone());
+ // Passing NULL as AstValueFactory is ok, because AllocateVariables doesn't
+ // need to create new strings or values.
+ AstNodeFactory<AstNullVisitor> ast_node_factory(info->zone(), NULL);
if (!top->AllocateVariables(info, &ast_node_factory)) return false;
}
@@ -310,7 +319,7 @@
if (is_declaration_scope()) {
Variable* var =
variables_.Declare(this,
- isolate_->factory()->this_string(),
+ ast_value_factory_->this_string(),
VAR,
false,
Variable::THIS,
@@ -327,7 +336,7 @@
// Note that it might never be accessed, in which case it won't be
// allocated during variable allocation.
variables_.Declare(this,
- isolate_->factory()->arguments_string(),
+ ast_value_factory_->arguments_string(),
VAR,
true,
Variable::ARGUMENTS,
@@ -366,23 +375,28 @@
}
-Variable* Scope::LookupLocal(Handle<String> name) {
+Variable* Scope::LookupLocal(const AstRawString* name) {
Variable* result = variables_.Lookup(name);
if (result != NULL || scope_info_.is_null()) {
return result;
}
+ // The Scope is backed up by ScopeInfo. This means it cannot operate in a
+ // heap-independent mode, and all strings must be internalized immediately. So
+ // it's ok to get the Handle<String> here.
+ Handle<String> name_handle = name->string();
// If we have a serialized scope info, we might find the variable there.
// There should be no local slot with the given name.
- ASSERT(scope_info_->StackSlotIndex(*name) < 0);
+ ASSERT(scope_info_->StackSlotIndex(*name_handle) < 0);
// Check context slot lookup.
VariableMode mode;
Variable::Location location = Variable::CONTEXT;
InitializationFlag init_flag;
- int index = ScopeInfo::ContextSlotIndex(scope_info_, name, &mode, &init_flag);
+ int index =
+ ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode, &init_flag);
if (index < 0) {
// Check parameters.
- index = scope_info_->ParameterIndex(*name);
+ index = scope_info_->ParameterIndex(*name_handle);
if (index < 0) return NULL;
mode = DYNAMIC;
@@ -397,14 +411,14 @@
}
-Variable* Scope::LookupFunctionVar(Handle<String> name,
+Variable* Scope::LookupFunctionVar(const AstRawString* name,
AstNodeFactory<AstNullVisitor>* factory) {
- if (function_ != NULL && function_->proxy()->name().is_identical_to(name)) {
+ if (function_ != NULL && function_->proxy()->raw_name() == name) {
return function_->proxy()->var();
} else if (!scope_info_.is_null()) {
// If we are backed by a scope info, try to lookup the variable there.
VariableMode mode;
- int index = scope_info_->FunctionContextSlotIndex(*name, &mode);
+ int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode);
if (index < 0) return NULL;
Variable* var = new(zone()) Variable(
this, name, mode, true /* is valid LHS */,
@@ -421,7 +435,7 @@
}
-Variable* Scope::Lookup(Handle<String> name) {
+Variable* Scope::Lookup(const AstRawString* name) {
for (Scope* scope = this;
scope != NULL;
scope = scope->outer_scope()) {
@@ -432,7 +446,7 @@
}
-void Scope::DeclareParameter(Handle<String> name, VariableMode mode) {
+void Scope::DeclareParameter(const AstRawString* name, VariableMode mode) {
ASSERT(!already_resolved());
ASSERT(is_function_scope());
Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL,
@@ -441,7 +455,7 @@
}
-Variable* Scope::DeclareLocal(Handle<String> name,
+Variable* Scope::DeclareLocal(const AstRawString* name,
VariableMode mode,
InitializationFlag init_flag,
Interface* interface) {
@@ -456,7 +470,7 @@
}
-Variable* Scope::DeclareDynamicGlobal(Handle<String> name) {
+Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) {
ASSERT(is_global_scope());
return variables_.Declare(this,
name,
@@ -479,7 +493,7 @@
}
-Variable* Scope::NewInternal(Handle<String> name) {
+Variable* Scope::NewInternal(const AstRawString* name) {
ASSERT(!already_resolved());
Variable* var = new(zone()) Variable(this,
name,
@@ -492,7 +506,7 @@
}
-Variable* Scope::NewTemporary(Handle<String> name) {
+Variable* Scope::NewTemporary(const AstRawString* name) {
ASSERT(!already_resolved());
Variable* var = new(zone()) Variable(this,
name,
@@ -530,7 +544,7 @@
for (int i = 0; i < length; i++) {
Declaration* decl = decls_[i];
if (decl->mode() != VAR) continue;
- Handle<String> name = decl->proxy()->name();
+ const AstRawString* name = decl->proxy()->raw_name();
// Iterate through all scopes until and including the declaration scope.
Scope* previous = NULL;
@@ -773,9 +787,8 @@
}
-static void PrintName(Handle<String> name) {
- SmartArrayPointer<char> s = name->ToCString(DISALLOW_NULLS);
- PrintF("%s", s.get());
+static void PrintName(const AstRawString* name) {
+ PrintF("%.*s", name->length(), name->raw_data());
}
@@ -803,7 +816,7 @@
if (var->is_used() || !var->IsUnallocated()) {
Indent(indent, Variable::Mode2String(var->mode()));
PrintF(" ");
- PrintName(var->name());
+ PrintName(var->raw_name());
PrintF("; // ");
PrintLocation(var);
if (var->has_forced_context_allocation()) {
@@ -829,7 +842,7 @@
// Print header.
Indent(n0, Header(scope_type_));
- if (scope_name_->length() > 0) {
+ if (!scope_name_->IsEmpty()) {
PrintF(" ");
PrintName(scope_name_);
}
@@ -839,7 +852,7 @@
PrintF(" (");
for (int i = 0; i < params_.length(); i++) {
if (i > 0) PrintF(", ");
- PrintName(params_[i]->name());
+ PrintName(params_[i]->raw_name());
}
PrintF(")");
}
@@ -849,7 +862,7 @@
// Function name, if any (named function literals, only).
if (function_ != NULL) {
Indent(n1, "// (local) function name: ");
- PrintName(function_->proxy()->name());
+ PrintName(function_->proxy()->raw_name());
PrintF("\n");
}
@@ -917,8 +930,8 @@
#endif // DEBUG
-Variable* Scope::NonLocal(Handle<String> name, VariableMode mode) {
- if (dynamics_ == NULL) dynamics_ = new(zone()) DynamicScopePart(zone());
+Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) {
+ if (dynamics_ == NULL) dynamics_ = new (zone()) DynamicScopePart(zone());
VariableMap* map = dynamics_->GetMap(mode);
Variable* var = map->Lookup(name);
if (var == NULL) {
@@ -938,7 +951,7 @@
}
-Variable* Scope::LookupRecursive(Handle<String> name,
+Variable* Scope::LookupRecursive(const AstRawString* name,
BindingKind* binding_kind,
AstNodeFactory<AstNullVisitor>* factory) {
ASSERT(binding_kind != NULL);
@@ -1012,7 +1025,7 @@
// Otherwise, try to resolve the variable.
BindingKind binding_kind;
- Variable* var = LookupRecursive(proxy->name(), &binding_kind, factory);
+ Variable* var = LookupRecursive(proxy->raw_name(), &binding_kind, factory);
switch (binding_kind) {
case BOUND:
// We found a variable binding.
@@ -1024,29 +1037,29 @@
// scope which was not promoted to a context, this can happen if we use
// debugger to evaluate arbitrary expressions at a break point).
if (var->IsGlobalObjectProperty()) {
- var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
+ var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL);
} else if (var->is_dynamic()) {
- var = NonLocal(proxy->name(), DYNAMIC);
+ var = NonLocal(proxy->raw_name(), DYNAMIC);
} else {
Variable* invalidated = var;
- var = NonLocal(proxy->name(), DYNAMIC_LOCAL);
+ var = NonLocal(proxy->raw_name(), DYNAMIC_LOCAL);
var->set_local_if_not_shadowed(invalidated);
}
break;
case UNBOUND:
// No binding has been found. Declare a variable on the global object.
- var = info->global_scope()->DeclareDynamicGlobal(proxy->name());
+ var = info->global_scope()->DeclareDynamicGlobal(proxy->raw_name());
break;
case UNBOUND_EVAL_SHADOWED:
// No binding has been found. But some scope makes a sloppy 'eval' call.
- var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
+ var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL);
break;
case DYNAMIC_LOOKUP:
// The variable could not be resolved statically.
- var = NonLocal(proxy->name(), DYNAMIC);
+ var = NonLocal(proxy->raw_name(), DYNAMIC);
break;
}
@@ -1069,8 +1082,10 @@
if (FLAG_harmony_modules) {
bool ok;
#ifdef DEBUG
- if (FLAG_print_interface_details)
- PrintF("# Resolve %s:\n", var->name()->ToAsciiArray());
+ if (FLAG_print_interface_details) {
+ PrintF("# Resolve %.*s:\n", var->raw_name()->length(),
+ var->raw_name()->raw_data());
+ }
#endif
proxy->interface()->Unify(var->interface(), zone(), &ok);
if (!ok) {
@@ -1150,7 +1165,7 @@
// Give var a read/write use if there is a chance it might be accessed
// via an eval() call. This is only possible if the variable has a
// visible name.
- if ((var->is_this() || var->name()->length() > 0) &&
+ if ((var->is_this() || !var->raw_name()->IsEmpty()) &&
(var->has_forced_context_allocation() ||
scope_calls_eval_ ||
inner_scope_calls_eval_ ||
@@ -1211,7 +1226,7 @@
void Scope::AllocateParameterLocals() {
ASSERT(is_function_scope());
- Variable* arguments = LookupLocal(isolate_->factory()->arguments_string());
+ Variable* arguments = LookupLocal(ast_value_factory_->arguments_string());
ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly
bool uses_sloppy_arguments = false;
@@ -1352,10 +1367,9 @@
if (already_resolved()) return;
if (is_module_scope()) {
ASSERT(interface_->IsFrozen());
- Handle<String> name = isolate_->factory()->InternalizeOneByteString(
- STATIC_ASCII_VECTOR(".module"));
ASSERT(module_var_ == NULL);
- module_var_ = host_scope->NewInternal(name);
+ module_var_ =
+ host_scope->NewInternal(ast_value_factory_->dot_module_string());
++host_scope->num_modules_;
}
diff --git a/src/scopes.h b/src/scopes.h
index 4486921..c313a40 100644
--- a/src/scopes.h
+++ b/src/scopes.h
@@ -22,14 +22,14 @@
virtual ~VariableMap();
Variable* Declare(Scope* scope,
- Handle<String> name,
+ const AstRawString* name,
VariableMode mode,
bool is_valid_lhs,
Variable::Kind kind,
InitializationFlag initialization_flag,
Interface* interface = Interface::NewValue());
- Variable* Lookup(Handle<String> name);
+ Variable* Lookup(const AstRawString* name);
Zone* zone() const { return zone_; }
@@ -74,7 +74,8 @@
// ---------------------------------------------------------------------------
// Construction
- Scope(Scope* outer_scope, ScopeType scope_type, Zone* zone);
+ Scope(Scope* outer_scope, ScopeType scope_type,
+ AstValueFactory* value_factory, Zone* zone);
// Compute top scope and allocate variables. For lazy compilation the top
// scope only contains the single lazily compiled function, so this
@@ -85,7 +86,9 @@
Zone* zone);
// The scope name is only used for printing/debugging.
- void SetScopeName(Handle<String> scope_name) { scope_name_ = scope_name; }
+ void SetScopeName(const AstRawString* scope_name) {
+ scope_name_ = scope_name;
+ }
void Initialize();
@@ -100,18 +103,18 @@
// Declarations
// Lookup a variable in this scope. Returns the variable or NULL if not found.
- Variable* LookupLocal(Handle<String> name);
+ Variable* LookupLocal(const AstRawString* name);
// This lookup corresponds to a lookup in the "intermediate" scope sitting
// between this scope and the outer scope. (ECMA-262, 3rd., requires that
// the name of named function literal is kept in an intermediate scope
// in between this scope and the next outer scope.)
- Variable* LookupFunctionVar(Handle<String> name,
+ Variable* LookupFunctionVar(const AstRawString* name,
AstNodeFactory<AstNullVisitor>* factory);
// Lookup a variable in this scope or outer scopes.
// Returns the variable or NULL if not found.
- Variable* Lookup(Handle<String> name);
+ Variable* Lookup(const AstRawString* name);
// Declare the function variable for a function literal. This variable
// is in an intermediate scope between this function scope and the the
@@ -124,11 +127,11 @@
// 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, VariableMode mode);
+ void DeclareParameter(const AstRawString* name, VariableMode mode);
// Declare a local variable in this scope. If the variable has been
// declared before, the previously declared variable is returned.
- Variable* DeclareLocal(Handle<String> name,
+ Variable* DeclareLocal(const AstRawString* name,
VariableMode mode,
InitializationFlag init_flag,
Interface* interface = Interface::NewValue());
@@ -137,12 +140,12 @@
// global scope. The variable was introduced (possibly from an inner
// scope) by a reference to an unresolved variable with no intervening
// with statements or eval calls.
- Variable* DeclareDynamicGlobal(Handle<String> name);
+ Variable* DeclareDynamicGlobal(const AstRawString* name);
// Create a new unresolved variable.
template<class Visitor>
VariableProxy* NewUnresolved(AstNodeFactory<Visitor>* factory,
- Handle<String> name,
+ const AstRawString* name,
Interface* interface = Interface::NewValue(),
int position = RelocInfo::kNoPosition) {
// Note that we must not share the unresolved variables with
@@ -167,13 +170,13 @@
// for printing and cannot be used to find the variable. In particular,
// the only way to get hold of the temporary is by keeping the Variable*
// around.
- Variable* NewInternal(Handle<String> name);
+ Variable* NewInternal(const AstRawString* name);
// Creates a new temporary variable in this scope. The name is only used
// for printing and cannot be used to find the variable. In particular,
// the only way to get hold of the temporary is by keeping the Variable*
// around. The name should not clash with a legitimate variable names.
- Variable* NewTemporary(Handle<String> name);
+ Variable* NewTemporary(const AstRawString* name);
// Adds the specific declaration node to the list of declarations in
// this scope. The declarations are processed as part of entering
@@ -390,7 +393,7 @@
// ---------------------------------------------------------------------------
// Strict mode support.
- bool IsDeclared(Handle<String> name) {
+ bool IsDeclared(const AstRawString* name) {
// During formal parameter list parsing the scope only contains
// two variables inserted at initialization: "this" and "arguments".
// "this" is an invalid parameter name and "arguments" is invalid parameter
@@ -421,7 +424,7 @@
ScopeType scope_type_;
// Debugging support.
- Handle<String> scope_name_;
+ const AstRawString* scope_name_;
// The variables declared in this scope:
//
@@ -497,7 +500,7 @@
// Create a non-local variable with a given name.
// These variables are looked up dynamically at runtime.
- Variable* NonLocal(Handle<String> name, VariableMode mode);
+ Variable* NonLocal(const AstRawString* name, VariableMode mode);
// Variable resolution.
// Possible results of a recursive variable lookup telling if and how a
@@ -548,7 +551,7 @@
// Lookup a variable reference given by name recursively starting with this
// scope. If the code is executed because of a call to 'eval', the context
// parameter should be set to the calling context of 'eval'.
- Variable* LookupRecursive(Handle<String> name,
+ Variable* LookupRecursive(const AstRawString* name,
BindingKind* binding_kind,
AstNodeFactory<AstNullVisitor>* factory);
MUST_USE_RESULT
@@ -592,10 +595,12 @@
private:
// Construct a scope based on the scope info.
Scope(Scope* inner_scope, ScopeType type, Handle<ScopeInfo> scope_info,
- Zone* zone);
+ AstValueFactory* value_factory, Zone* zone);
// Construct a catch scope with a binding for the name.
- Scope(Scope* inner_scope, Handle<String> catch_variable_name, Zone* zone);
+ Scope(Scope* inner_scope,
+ const AstRawString* catch_variable_name,
+ AstValueFactory* value_factory, Zone* zone);
void AddInnerScope(Scope* inner_scope) {
if (inner_scope != NULL) {
@@ -608,6 +613,7 @@
Scope* outer_scope,
Handle<ScopeInfo> scope_info);
+ AstValueFactory* ast_value_factory_;
Zone* zone_;
};
diff --git a/src/utils.cc b/src/utils.cc
index 52b0d48..df1f280 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -394,4 +394,24 @@
}
+bool DoubleToBoolean(double d) {
+ // NaN, +0, and -0 should return the false object
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ union IeeeDoubleLittleEndianArchType u;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ union IeeeDoubleBigEndianArchType u;
+#endif
+ u.d = d;
+ if (u.bits.exp == 2047) {
+ // Detect NaN for IEEE double precision floating point.
+ if ((u.bits.man_low | u.bits.man_high) != 0) return false;
+ }
+ if (u.bits.exp == 0) {
+ // Detect +0, and -0 for IEEE double precision floating point.
+ if ((u.bits.man_low | u.bits.man_high) == 0) return false;
+ }
+ return true;
+}
+
+
} } // namespace v8::internal
diff --git a/src/utils.h b/src/utils.h
index 5422985..da5d0fc 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -1318,8 +1318,12 @@
#if V8_HOST_ARCH_IA32
#define STOS "stosl"
#elif V8_HOST_ARCH_X64
+#if V8_HOST_ARCH_32_BIT
+#define STOS "addr32 stosl"
+#else
#define STOS "stosq"
#endif
+#endif
#if defined(__native_client__)
// This STOS sequence does not validate for x86_64 Native Client.
// Here we #undef STOS to force use of the slower C version.
@@ -1578,6 +1582,36 @@
};
+bool DoubleToBoolean(double d);
+
+template <typename Stream>
+bool StringToArrayIndex(Stream* stream, uint32_t* index) {
+ uint16_t ch = stream->GetNext();
+
+ // If the string begins with a '0' character, it must only consist
+ // of it to be a legal array index.
+ if (ch == '0') {
+ *index = 0;
+ return !stream->HasMore();
+ }
+
+ // Convert string to uint32 array index; character by character.
+ int d = ch - '0';
+ if (d < 0 || d > 9) return false;
+ uint32_t result = d;
+ while (stream->HasMore()) {
+ d = stream->GetNext() - '0';
+ if (d < 0 || d > 9) return false;
+ // Check that the new result is below the 32 bit limit.
+ if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
+ result = (result * 10) + d;
+ }
+
+ *index = result;
+ return true;
+}
+
+
} } // namespace v8::internal
#endif // V8_UTILS_H_
diff --git a/src/variables.cc b/src/variables.cc
index 906b6ab..3013938 100644
--- a/src/variables.cc
+++ b/src/variables.cc
@@ -33,7 +33,7 @@
Variable::Variable(Scope* scope,
- Handle<String> name,
+ const AstRawString* name,
VariableMode mode,
bool is_valid_ref,
Kind kind,
@@ -52,8 +52,6 @@
is_used_(false),
initialization_flag_(initialization_flag),
interface_(interface) {
- // Names must be canonicalized for fast equality checks.
- ASSERT(name->IsInternalizedString());
// Var declared variables never need initialization.
ASSERT(!(mode == VAR && initialization_flag == kNeedsInitialization));
}
diff --git a/src/variables.h b/src/variables.h
index acec910..fdea0ee 100644
--- a/src/variables.h
+++ b/src/variables.h
@@ -5,6 +5,7 @@
#ifndef V8_VARIABLES_H_
#define V8_VARIABLES_H_
+#include "src/ast-value-factory.h"
#include "src/interface.h"
#include "src/zone.h"
@@ -52,7 +53,7 @@
};
Variable(Scope* scope,
- Handle<String> name,
+ const AstRawString* name,
VariableMode mode,
bool is_valid_ref,
Kind kind,
@@ -70,7 +71,8 @@
// scope is only used to follow the context chain length.
Scope* scope() const { return scope_; }
- Handle<String> name() const { return name_; }
+ Handle<String> name() const { return name_->string(); }
+ const AstRawString* raw_name() const { return name_; }
VariableMode mode() const { return mode_; }
bool has_forced_context_allocation() const {
return force_context_allocation_;
@@ -136,7 +138,7 @@
private:
Scope* scope_;
- Handle<String> name_;
+ const AstRawString* name_;
VariableMode mode_;
Kind kind_;
Location location_;
diff --git a/src/version.cc b/src/version.cc
index 6a4f90b..b0004fe 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,8 +34,8 @@
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION 3
#define MINOR_VERSION 28
-#define BUILD_NUMBER 1
-#define PATCH_LEVEL 2
+#define BUILD_NUMBER 2
+#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/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index 0bc5739..b6aadc7 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -2375,10 +2375,10 @@
__ SmiToInteger32(rdx, rdx);
__ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rcx);
- __ cmpq(rdi, rcx);
+ __ cmpp(rdi, rcx);
__ j(not_equal, &miss);
- __ movq(rax, Immediate(arg_count()));
+ __ movp(rax, Immediate(arg_count()));
__ movp(rbx, FieldOperand(rbx, rdx, times_pointer_size,
FixedArray::kHeaderSize));
@@ -2417,7 +2417,7 @@
// The checks. First, does rdi match the recorded monomorphic target?
__ SmiToInteger32(rdx, rdx);
- __ cmpq(rdi, FieldOperand(rbx, rdx, times_pointer_size,
+ __ cmpp(rdi, FieldOperand(rbx, rdx, times_pointer_size,
FixedArray::kHeaderSize));
__ j(not_equal, &extra_checks_or_miss);
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index 3190e5a..46d91a0 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -2939,7 +2939,8 @@
// rcx: valid entries in the descriptor array.
// Calculate the end of the descriptor array.
__ imulp(rcx, rcx, Immediate(DescriptorArray::kDescriptorSize));
- __ leap(rcx, Operand(r8, rcx, times_8, DescriptorArray::kFirstOffset));
+ __ leap(rcx,
+ Operand(r8, rcx, times_pointer_size, DescriptorArray::kFirstOffset));
// Calculate location of the first key name.
__ addp(r8, Immediate(DescriptorArray::kFirstOffset));
// Loop through all the keys in the descriptor array. If one of these is the
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index b9b1b8e..a2ff91b 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -167,7 +167,7 @@
#endif
__ Push(rax);
__ Set(rax, slots);
- __ movq(kScratchRegister, kSlotsZapValue);
+ __ Set(kScratchRegister, kSlotsZapValue);
Label loop;
__ bind(&loop);
__ movp(MemOperand(rsp, rax, times_pointer_size, 0),
@@ -744,7 +744,7 @@
ExternalReference count = ExternalReference::stress_deopt_count(isolate());
Label no_deopt;
__ pushfq();
- __ Push(rax);
+ __ pushq(rax);
Operand count_operand = masm()->ExternalOperand(count, kScratchRegister);
__ movl(rax, count_operand);
__ subl(rax, Immediate(1));
@@ -752,13 +752,13 @@
if (FLAG_trap_on_deopt) __ int3();
__ movl(rax, Immediate(FLAG_deopt_every_n_times));
__ movl(count_operand, rax);
- __ Pop(rax);
+ __ popq(rax);
__ popfq();
ASSERT(frame_is_built_);
__ call(entry, RelocInfo::RUNTIME_ENTRY);
__ bind(&no_deopt);
__ movl(count_operand, rax);
- __ Pop(rax);
+ __ popq(rax);
__ popfq();
}
@@ -2746,7 +2746,7 @@
__ Push(ToRegister(instr->value()));
__ Push(instr->function());
- static const int kAdditionalDelta = 10;
+ static const int kAdditionalDelta = kPointerSize == kInt64Size ? 10 : 16;
int delta =
masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
ASSERT(delta >= 0);
@@ -4715,7 +4715,7 @@
if (FLAG_inline_new) {
__ AllocateHeapNumber(reg, tmp, &slow);
- __ jmp(&done, Label::kNear);
+ __ jmp(&done, kPointerSize == kInt64Size ? Label::kNear : Label::kFar);
}
// Slow case: Call the runtime system to do the number allocation.
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index 919df87..6d772c0 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -331,6 +331,16 @@
int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) {
+ if (kind == DOUBLE_REGISTERS && kDoubleSize == 2 * kPointerSize) {
+ // Skip a slot if for a double-width slot for x32 port.
+ spill_slot_count_++;
+ // The spill slot's address is at rbp - (index + 1) * kPointerSize -
+ // StandardFrameConstants::kFixedFrameSizeFromFp. kFixedFrameSizeFromFp is
+ // 2 * kPointerSize, if rbp is aligned at 8-byte boundary, the below "|= 1"
+ // will make sure the spilled doubles are aligned at 8-byte boundary.
+ // TODO(haitao): make sure rbp is aligned at 8-byte boundary for x32 port.
+ spill_slot_count_ |= 1;
+ }
return spill_slot_count_++;
}
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index d42756a..e0fa23c 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -1100,7 +1100,7 @@
if (emit_debug_code()) {
Move(dst, Smi::FromInt(kSmiConstantRegisterValue),
Assembler::RelocInfoNone());
- cmpq(dst, kSmiConstantRegister);
+ cmpp(dst, kSmiConstantRegister);
Assert(equal, kUninitializedKSmiConstantRegister);
}
int value = source->value();
diff --git a/test/cctest/test-ast.cc b/test/cctest/test-ast.cc
index 2285d0c..a25ae69 100644
--- a/test/cctest/test-ast.cc
+++ b/test/cctest/test-ast.cc
@@ -41,7 +41,7 @@
Isolate* isolate = CcTest::i_isolate();
Zone zone(isolate);
- AstNodeFactory<AstNullVisitor> factory(&zone);
+ AstNodeFactory<AstNullVisitor> factory(&zone, NULL);
AstNode* node = factory.NewEmptyStatement(RelocInfo::kNoPosition);
list->Add(node);
CHECK_EQ(1, list->length());
diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc
index 77b5bd8..6e5e23b 100644
--- a/test/cctest/test-cpu-profiler.cc
+++ b/test/cctest/test-cpu-profiler.cc
@@ -283,7 +283,7 @@
sample->pc = code->address();
sample->tos = 0;
sample->frames_count = i::TickSample::kMaxFramesCount;
- for (int i = 0; i < sample->frames_count; ++i) {
+ for (unsigned i = 0; i < sample->frames_count; ++i) {
sample->stack[i] = code->address();
}
processor->FinishTickSample();
@@ -1248,6 +1248,72 @@
}
+static const char* cpu_profiler_deep_stack_test_source =
+"function foo(n) {\n"
+" if (n)\n"
+" foo(n - 1);\n"
+" else\n"
+" startProfiling('my_profile');\n"
+"}\n"
+"function start() {\n"
+" foo(250);\n"
+"}\n";
+
+
+// Check a deep stack
+//
+// [Top down]:
+// 0 (root) 0 #1
+// 2 (program) 0 #2
+// 0 start 21 #3 no reason
+// 0 foo 21 #4 no reason
+// 0 foo 21 #5 no reason
+// ....
+// 0 foo 21 #253 no reason
+// 1 startProfiling 0 #254
+TEST(CpuProfileDeepStack) {
+ v8::HandleScope scope(CcTest::isolate());
+ v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
+ v8::Context::Scope context_scope(env);
+
+ v8::Script::Compile(v8::String::NewFromUtf8(
+ env->GetIsolate(), cpu_profiler_deep_stack_test_source))->Run();
+ v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "start")));
+
+ v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
+ v8::Local<v8::String> profile_name =
+ v8::String::NewFromUtf8(env->GetIsolate(), "my_profile");
+ function->Call(env->Global(), 0, NULL);
+ v8::CpuProfile* profile = cpu_profiler->StopProfiling(profile_name);
+ CHECK_NE(NULL, profile);
+ // Dump collected profile to have a better diagnostic in case of failure.
+ reinterpret_cast<i::CpuProfile*>(profile)->Print();
+
+ const v8::CpuProfileNode* root = profile->GetTopDownRoot();
+ {
+ ScopedVector<v8::Handle<v8::String> > names(3);
+ names[0] = v8::String::NewFromUtf8(
+ env->GetIsolate(), ProfileGenerator::kGarbageCollectorEntryName);
+ names[1] = v8::String::NewFromUtf8(env->GetIsolate(),
+ ProfileGenerator::kProgramEntryName);
+ names[2] = v8::String::NewFromUtf8(env->GetIsolate(), "start");
+ CheckChildrenNames(root, names);
+ }
+
+ const v8::CpuProfileNode* node =
+ GetChild(env->GetIsolate(), root, "start");
+ for (int i = 0; i < 250; ++i) {
+ node = GetChild(env->GetIsolate(), node, "foo");
+ }
+ // TODO(alph):
+ // In theory there must be one more 'foo' and a 'startProfiling' nodes,
+ // but due to unstable top frame extraction these might be missing.
+
+ profile->Delete();
+}
+
+
static const char* js_native_js_test_source =
"var is_profiling = false;\n"
"function foo(iterations) {\n"
diff --git a/test/cctest/test-lockers.cc b/test/cctest/test-lockers.cc
index f92a81e..0e6f14a 100644
--- a/test/cctest/test-lockers.cc
+++ b/test/cctest/test-lockers.cc
@@ -247,6 +247,8 @@
TEST(MultithreadedParallelIsolates) {
#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
const int kNThreads = 10;
+#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
+ const int kNThreads = 4;
#else
const int kNThreads = 50;
#endif
@@ -713,6 +715,8 @@
TEST(ExtensionsRegistration) {
#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
const int kNThreads = 10;
+#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
+ const int kNThreads = 4;
#else
const int kNThreads = 40;
#endif
diff --git a/test/cctest/test-log-stack-tracer.cc b/test/cctest/test-log-stack-tracer.cc
index 3f9d0b3..334a201 100644
--- a/test/cctest/test-log-stack-tracer.cc
+++ b/test/cctest/test-log-stack-tracer.cc
@@ -172,7 +172,7 @@
CHECK_EQ(FUNCTION_ADDR(i::TraceExtension::Trace), sample.external_callback);
// Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace"
- int base = 0;
+ unsigned base = 0;
CHECK_GT(sample.frames_count, base + 1);
CHECK(IsAddressWithinFuncCode(
@@ -225,7 +225,7 @@
CHECK_EQ(FUNCTION_ADDR(i::TraceExtension::JSTrace), sample.external_callback);
// Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace"
- int base = 0;
+ unsigned base = 0;
CHECK_GT(sample.frames_count, base + 1);
CHECK(IsAddressWithinFuncCode(context, "JSTrace", sample.stack[base + 0]));
CHECK(IsAddressWithinFuncCode(
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index c484663..858354d 100644
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -31,6 +31,7 @@
#include "src/v8.h"
+#include "src/ast-value-factory.h"
#include "src/compiler.h"
#include "src/execution.h"
#include "src/isolate.h"
@@ -796,8 +797,12 @@
CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV);
CHECK(scanner.ScanRegExpPattern(start == i::Token::ASSIGN_DIV));
scanner.Next(); // Current token is now the regexp literal.
+ i::Zone zone(CcTest::i_isolate());
+ i::AstValueFactory ast_value_factory(&zone,
+ CcTest::i_isolate()->heap()->HashSeed());
+ ast_value_factory.Internalize(CcTest::i_isolate());
i::Handle<i::String> val =
- scanner.AllocateInternalizedString(CcTest::i_isolate());
+ scanner.CurrentSymbol(&ast_value_factory)->string();
i::DisallowHeapAllocation no_alloc;
i::String::FlatContent content = val->GetFlatContent();
CHECK(content.IsAscii());
@@ -2587,3 +2592,20 @@
i::DeleteArray(two_byte_source);
i::DeleteArray(two_byte_name);
}
+
+
+TEST(RegressionLazyFunctionWithErrorWithArg) {
+ // The bug occurred when a lazy function had an error which requires a
+ // parameter (such as "unknown label" here). The error message was processed
+ // before the AstValueFactory containing the error message string was
+ // internalized.
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
+ LocalContext env;
+ i::FLAG_lazy = true;
+ i::FLAG_min_preparse_length = 0;
+ CompileRun("function this_is_lazy() {\n"
+ " break p;\n"
+ "}\n"
+ "this_is_lazy();\n");
+}
diff --git a/test/mjsunit/harmony/collections.js b/test/mjsunit/harmony/collections.js
index edbdd41..1dd7f0d 100644
--- a/test/mjsunit/harmony/collections.js
+++ b/test/mjsunit/harmony/collections.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.
-// Flags: --harmony-collections
+// Flags: --harmony-collections --harmony-iteration
// Flags: --expose-gc --allow-natives-syntax
@@ -987,3 +987,261 @@
assertArrayEquals([0, 1, 2, 3, 4], buffer);
})();
+
+
+(function TestSetConstructor() {
+ var s = new Set(null);
+ assertEquals(s.size, 0);
+
+ s = new Set(undefined);
+ assertEquals(s.size, 0);
+
+ // No @@iterator
+ assertThrows(function() {
+ new Set({});
+ }, TypeError);
+
+ // @@iterator not callable
+ assertThrows(function() {
+ var object = {};
+ object[Symbol.iterator] = 42;
+ new Set(object);
+ }, TypeError);
+
+ // @@iterator result not object
+ assertThrows(function() {
+ var object = {};
+ object[Symbol.iterator] = function() {
+ return 42;
+ };
+ new Set(object);
+ }, TypeError);
+
+ var s2 = new Set();
+ s2.add('a');
+ s2.add('b');
+ s2.add('c');
+ s = new Set(s2.values());
+ assertEquals(s.size, 3);
+ assertTrue(s.has('a'));
+ assertTrue(s.has('b'));
+ assertTrue(s.has('c'));
+})();
+
+
+(function TestSetConstructorAddNotCallable() {
+ var originalSetPrototypeAdd = Set.prototype.add;
+ assertThrows(function() {
+ Set.prototype.add = 42;
+ new Set([1, 2].values());
+ }, TypeError);
+ Set.prototype.add = originalSetPrototypeAdd;
+})();
+
+
+(function TestSetConstructorGetAddOnce() {
+ var originalSetPrototypeAdd = Set.prototype.add;
+ var getAddCount = 0;
+ Object.defineProperty(Set.prototype, 'add', {
+ get: function() {
+ getAddCount++;
+ return function() {};
+ }
+ });
+ var s = new Set([1, 2].values());
+ assertEquals(getAddCount, 1);
+ assertEquals(s.size, 0);
+ Object.defineProperty(Set.prototype, 'add', {
+ value: originalSetPrototypeAdd,
+ writable: true
+ });
+})();
+
+
+(function TestSetConstructorAddReplaced() {
+ var originalSetPrototypeAdd = Set.prototype.add;
+ var addCount = 0;
+ Set.prototype.add = function(value) {
+ addCount++;
+ originalSetPrototypeAdd.call(this, value);
+ Set.prototype.add = null;
+ };
+ var s = new Set([1, 2].values());
+ assertEquals(addCount, 2);
+ assertEquals(s.size, 2);
+ Set.prototype.add = originalSetPrototypeAdd;
+})();
+
+
+(function TestSetConstructorOrderOfDoneValue() {
+ var valueCount = 0, doneCount = 0;
+ var iterator = {
+ next: function() {
+ return {
+ get value() {
+ valueCount++;
+ },
+ get done() {
+ doneCount++;
+ throw new Error();
+ }
+ };
+ }
+ };
+ iterator[Symbol.iterator] = function() {
+ return this;
+ };
+ assertThrows(function() {
+ new Set(iterator);
+ });
+ assertEquals(doneCount, 1);
+ assertEquals(valueCount, 0);
+})();
+
+
+(function TestSetConstructorNextNotAnObject() {
+ var iterator = {
+ next: function() {
+ return 'abc';
+ }
+ };
+ iterator[Symbol.iterator] = function() {
+ return this;
+ };
+ assertThrows(function() {
+ new Set(iterator);
+ }, TypeError);
+})();
+
+
+(function TestMapConstructor() {
+ var m = new Map(null);
+ assertEquals(m.size, 0);
+
+ m = new Map(undefined);
+ assertEquals(m.size, 0);
+
+ // No @@iterator
+ assertThrows(function() {
+ new Map({});
+ }, TypeError);
+
+ // @@iterator not callable
+ assertThrows(function() {
+ var object = {};
+ object[Symbol.iterator] = 42;
+ new Map(object);
+ }, TypeError);
+
+ // @@iterator result not object
+ assertThrows(function() {
+ var object = {};
+ object[Symbol.iterator] = function() {
+ return 42;
+ };
+ new Map(object);
+ }, TypeError);
+
+ var m2 = new Map();
+ m2.set(0, 'a');
+ m2.set(1, 'b');
+ m2.set(2, 'c');
+ m = new Map(m2.entries());
+ assertEquals(m.size, 3);
+ assertEquals(m.get(0), 'a');
+ assertEquals(m.get(1), 'b');
+ assertEquals(m.get(2), 'c');
+})();
+
+
+(function TestMapConstructorSetNotCallable() {
+ var originalMapPrototypeSet = Map.prototype.set;
+ assertThrows(function() {
+ Map.prototype.set = 42;
+ new Map([1, 2].entries());
+ }, TypeError);
+ Map.prototype.set = originalMapPrototypeSet;
+})();
+
+
+(function TestMapConstructorGetAddOnce() {
+ var originalMapPrototypeSet = Map.prototype.set;
+ var getSetCount = 0;
+ Object.defineProperty(Map.prototype, 'set', {
+ get: function() {
+ getSetCount++;
+ return function() {};
+ }
+ });
+ var m = new Map([1, 2].entries());
+ assertEquals(getSetCount, 1);
+ assertEquals(m.size, 0);
+ Object.defineProperty(Map.prototype, 'set', {
+ value: originalMapPrototypeSet,
+ writable: true
+ });
+})();
+
+
+(function TestMapConstructorSetReplaced() {
+ var originalMapPrototypeSet = Map.prototype.set;
+ var setCount = 0;
+ Map.prototype.set = function(key, value) {
+ setCount++;
+ originalMapPrototypeSet.call(this, key, value);
+ Map.prototype.set = null;
+ };
+ var m = new Map([1, 2].entries());
+ assertEquals(setCount, 2);
+ assertEquals(m.size, 2);
+ Map.prototype.set = originalMapPrototypeSet;
+})();
+
+
+(function TestMapConstructorOrderOfDoneValue() {
+ var valueCount = 0, doneCount = 0;
+ function FakeError() {}
+ var iterator = {
+ next: function() {
+ return {
+ get value() {
+ valueCount++;
+ },
+ get done() {
+ doneCount++;
+ throw new FakeError();
+ }
+ };
+ }
+ };
+ iterator[Symbol.iterator] = function() {
+ return this;
+ };
+ assertThrows(function() {
+ new Map(iterator);
+ }, FakeError);
+ assertEquals(doneCount, 1);
+ assertEquals(valueCount, 0);
+})();
+
+
+(function TestMapConstructorNextNotAnObject() {
+ var iterator = {
+ next: function() {
+ return 'abc';
+ }
+ };
+ iterator[Symbol.iterator] = function() {
+ return this;
+ };
+ assertThrows(function() {
+ new Map(iterator);
+ }, TypeError);
+})();
+
+
+(function TestMapConstructorIteratorNotObjectValues() {
+ assertThrows(function() {
+ new Map([1, 2].values());
+ }, TypeError);
+})();
diff --git a/test/mjsunit/regress/regress-crbug-387599.js b/test/mjsunit/regress/regress-crbug-387599.js
new file mode 100644
index 0000000..98750aa
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-387599.js
@@ -0,0 +1,19 @@
+// Copyright 2014 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.
+
+// Flags: --allow-natives-syntax --expose-debug-as debug
+
+Debug = debug.Debug;
+Debug.setListener(function() {});
+
+function f() {
+ for (var i = 0; i < 100; i++) {
+ %OptimizeFunctionOnNextCall(f, "osr");
+ }
+}
+
+Debug.setBreakPoint(f, 0, 0);
+f();
+f();
+Debug.setListener(null);
diff --git a/test/mjsunit/regress/regress-crbug-387636.js b/test/mjsunit/regress/regress-crbug-387636.js
new file mode 100644
index 0000000..1e50ace
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-387636.js
@@ -0,0 +1,14 @@
+// Copyright 2014 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.
+
+// Flags: --allow-natives-syntax
+
+function f() {
+ [].indexOf(0x40000000);
+}
+
+f();
+f();
+%OptimizeFunctionOnNextCall(f);
+f();
diff --git a/tools/disasm.py b/tools/disasm.py
index 6fa81ca..cc7ef06 100644
--- a/tools/disasm.py
+++ b/tools/disasm.py
@@ -49,7 +49,8 @@
"ia32": "-m i386",
"x64": "-m i386 -M x86-64",
"arm": "-m arm", # Not supported by our objdump build.
- "mips": "-m mips" # Not supported by our objdump build.
+ "mips": "-m mips", # Not supported by our objdump build.
+ "arm64": "-m aarch64"
}
diff --git a/tools/generate-runtime-tests.py b/tools/generate-runtime-tests.py
index a604cd3..e8d4c64 100755
--- a/tools/generate-runtime-tests.py
+++ b/tools/generate-runtime-tests.py
@@ -51,7 +51,7 @@
EXPECTED_FUZZABLE_COUNT = 326
EXPECTED_CCTEST_COUNT = 6
EXPECTED_UNKNOWN_COUNT = 4
-EXPECTED_BUILTINS_COUNT = 798
+EXPECTED_BUILTINS_COUNT = 800
# Don't call these at all.
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index c6dcf69..c7d04c6 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -343,6 +343,8 @@
'../../src/assembler.h',
'../../src/assert-scope.h',
'../../src/assert-scope.cc',
+ '../../src/ast-value-factory.cc',
+ '../../src/ast-value-factory.h',
'../../src/ast.cc',
'../../src/ast.h',
'../../src/bignum-dtoa.cc',
@@ -870,7 +872,7 @@
'../../src/mips/stub-cache-mips.cc',
],
}],
- ['v8_target_arch=="x64"', {
+ ['v8_target_arch=="x64" or v8_target_arch=="x32"', {
'sources': [ ### gcmole(arch:x64) ###
'../../src/x64/assembler-x64-inl.h',
'../../src/x64/assembler-x64.cc',
diff --git a/tools/ll_prof.py b/tools/ll_prof.py
index 216929d..409b396 100755
--- a/tools/ll_prof.py
+++ b/tools/ll_prof.py
@@ -351,7 +351,8 @@
"ia32": ctypes.c_uint32,
"arm": ctypes.c_uint32,
"mips": ctypes.c_uint32,
- "x64": ctypes.c_uint64
+ "x64": ctypes.c_uint64,
+ "arm64": ctypes.c_uint64
}
_CODE_CREATE_TAG = "C"
diff --git a/tools/parser-shell.cc b/tools/parser-shell.cc
index c229185..f14c000 100644
--- a/tools/parser-shell.cc
+++ b/tools/parser-shell.cc
@@ -44,6 +44,18 @@
using namespace v8::internal;
+class StringResource8 : public v8::String::ExternalAsciiStringResource {
+ public:
+ StringResource8(const char* data, int length)
+ : data_(data), length_(length) { }
+ virtual size_t length() const { return length_; }
+ virtual const char* data() const { return data_; }
+
+ private:
+ const char* data_;
+ int length_;
+};
+
std::pair<TimeDelta, TimeDelta> RunBaselineParser(
const char* fname, Encoding encoding, int repeat, v8::Isolate* isolate,
v8::Handle<v8::Context> context) {
@@ -63,7 +75,9 @@
break;
}
case LATIN1: {
- source_handle = v8::String::NewFromOneByte(isolate, source);
+ StringResource8* string_resource =
+ new StringResource8(reinterpret_cast<const char*>(source), length);
+ source_handle = v8::String::NewExternal(isolate, string_resource);
break;
}
}
diff --git a/tools/run-tests.py b/tools/run-tests.py
index 794c864..fbbe416 100755
--- a/tools/run-tests.py
+++ b/tools/run-tests.py
@@ -86,6 +86,7 @@
"nacl_ia32",
"nacl_x64",
"x64",
+ "x32",
"arm64"]
# Double the timeout for these:
SLOW_ARCHS = ["android_arm",
diff --git a/tools/whitespace.txt b/tools/whitespace.txt
index 4517663..69793d0 100644
--- a/tools/whitespace.txt
+++ b/tools/whitespace.txt
@@ -3,3 +3,4 @@
+