summaryrefslogtreecommitdiff
path: root/deps
diff options
context:
space:
mode:
Diffstat (limited to 'deps')
-rw-r--r--deps/v8/ChangeLog62
-rw-r--r--deps/v8/SConstruct214
-rw-r--r--deps/v8/include/v8-debug.h168
-rw-r--r--deps/v8/include/v8.h73
-rw-r--r--deps/v8/samples/shell.cc22
-rwxr-xr-x[-rw-r--r--]deps/v8/src/SConscript38
-rw-r--r--deps/v8/src/accessors.cc37
-rw-r--r--deps/v8/src/accessors.h4
-rw-r--r--deps/v8/src/api.cc185
-rw-r--r--deps/v8/src/arm/assembler-arm-inl.h (renamed from deps/v8/src/assembler-arm-inl.h)8
-rw-r--r--deps/v8/src/arm/assembler-arm.cc (renamed from deps/v8/src/assembler-arm.cc)2
-rw-r--r--deps/v8/src/arm/assembler-arm.h (renamed from deps/v8/src/assembler-arm.h)40
-rw-r--r--deps/v8/src/arm/builtins-arm.cc (renamed from deps/v8/src/builtins-arm.cc)63
-rw-r--r--deps/v8/src/arm/codegen-arm.cc (renamed from deps/v8/src/codegen-arm.cc)538
-rw-r--r--deps/v8/src/arm/codegen-arm.h (renamed from deps/v8/src/codegen-arm.h)28
-rw-r--r--deps/v8/src/arm/constants-arm.h (renamed from deps/v8/src/constants-arm.h)13
-rw-r--r--deps/v8/src/arm/cpu-arm.cc (renamed from deps/v8/src/cpu-arm.cc)0
-rw-r--r--deps/v8/src/arm/debug-arm.cc (renamed from deps/v8/src/debug-arm.cc)5
-rw-r--r--deps/v8/src/arm/disasm-arm.cc (renamed from deps/v8/src/disasm-arm.cc)9
-rw-r--r--deps/v8/src/arm/frames-arm.cc (renamed from deps/v8/src/frames-arm.cc)2
-rw-r--r--deps/v8/src/arm/frames-arm.h (renamed from deps/v8/src/frames-arm.h)6
-rw-r--r--deps/v8/src/arm/ic-arm.cc (renamed from deps/v8/src/ic-arm.cc)57
-rw-r--r--deps/v8/src/arm/jump-target-arm.cc (renamed from deps/v8/src/jump-target-arm.cc)2
-rw-r--r--deps/v8/src/arm/macro-assembler-arm.cc (renamed from deps/v8/src/macro-assembler-arm.cc)27
-rw-r--r--deps/v8/src/arm/macro-assembler-arm.h (renamed from deps/v8/src/macro-assembler-arm.h)20
-rw-r--r--deps/v8/src/arm/regexp-macro-assembler-arm.cc (renamed from deps/v8/src/regexp-macro-assembler-arm.cc)2
-rw-r--r--deps/v8/src/arm/regexp-macro-assembler-arm.h (renamed from deps/v8/src/regexp-macro-assembler-arm.h)6
-rw-r--r--deps/v8/src/arm/register-allocator-arm.cc (renamed from deps/v8/src/register-allocator-arm.cc)8
-rw-r--r--deps/v8/src/arm/simulator-arm.cc (renamed from deps/v8/src/simulator-arm.cc)95
-rw-r--r--deps/v8/src/arm/simulator-arm.h (renamed from deps/v8/src/simulator-arm.h)14
-rw-r--r--deps/v8/src/arm/stub-cache-arm.cc (renamed from deps/v8/src/stub-cache-arm.cc)15
-rw-r--r--deps/v8/src/arm/virtual-frame-arm.cc (renamed from deps/v8/src/virtual-frame-arm.cc)13
-rw-r--r--deps/v8/src/arm/virtual-frame-arm.h (renamed from deps/v8/src/virtual-frame-arm.h)6
-rw-r--r--deps/v8/src/array.js167
-rw-r--r--deps/v8/src/assembler.cc56
-rw-r--r--deps/v8/src/assembler.h37
-rw-r--r--deps/v8/src/ast.cc21
-rw-r--r--deps/v8/src/ast.h7
-rw-r--r--deps/v8/src/bootstrapper.cc64
-rw-r--r--deps/v8/src/builtins.cc3
-rw-r--r--deps/v8/src/builtins.h5
-rw-r--r--deps/v8/src/checks.h2
-rw-r--r--deps/v8/src/code-stubs.h2
-rw-r--r--deps/v8/src/codegen.cc90
-rw-r--r--deps/v8/src/codegen.h20
-rw-r--r--deps/v8/src/compiler.cc43
-rw-r--r--deps/v8/src/compiler.h3
-rw-r--r--deps/v8/src/contexts.h6
-rw-r--r--deps/v8/src/d8.cc27
-rw-r--r--deps/v8/src/d8.h3
-rw-r--r--deps/v8/src/d8.js37
-rw-r--r--deps/v8/src/date-delay.js25
-rw-r--r--deps/v8/src/dateparser-inl.h5
-rw-r--r--deps/v8/src/debug-agent.cc21
-rw-r--r--deps/v8/src/debug-agent.h28
-rw-r--r--deps/v8/src/debug-delay.js75
-rw-r--r--deps/v8/src/debug.cc541
-rw-r--r--deps/v8/src/debug.h188
-rw-r--r--deps/v8/src/execution.cc26
-rw-r--r--deps/v8/src/execution.h11
-rw-r--r--deps/v8/src/factory.cc13
-rw-r--r--deps/v8/src/factory.h5
-rw-r--r--deps/v8/src/frames-inl.h12
-rw-r--r--deps/v8/src/frames.cc8
-rw-r--r--deps/v8/src/func-name-inferrer.cc9
-rw-r--r--deps/v8/src/func-name-inferrer.h23
-rw-r--r--deps/v8/src/global-handles.cc2
-rw-r--r--deps/v8/src/global-handles.h5
-rw-r--r--deps/v8/src/globals.h110
-rw-r--r--deps/v8/src/handles.cc72
-rw-r--r--deps/v8/src/handles.h9
-rw-r--r--deps/v8/src/heap-inl.h4
-rw-r--r--deps/v8/src/heap.cc161
-rw-r--r--deps/v8/src/ia32/assembler-ia32-inl.h (renamed from deps/v8/src/assembler-ia32-inl.h)6
-rw-r--r--deps/v8/src/ia32/assembler-ia32.cc (renamed from deps/v8/src/assembler-ia32.cc)43
-rw-r--r--deps/v8/src/ia32/assembler-ia32.h (renamed from deps/v8/src/assembler-ia32.h)6
-rw-r--r--deps/v8/src/ia32/builtins-ia32.cc (renamed from deps/v8/src/builtins-ia32.cc)28
-rw-r--r--deps/v8/src/ia32/codegen-ia32.cc (renamed from deps/v8/src/codegen-ia32.cc)262
-rw-r--r--deps/v8/src/ia32/codegen-ia32.h633
-rw-r--r--deps/v8/src/ia32/cpu-ia32.cc (renamed from deps/v8/src/cpu-ia32.cc)0
-rw-r--r--deps/v8/src/ia32/debug-ia32.cc (renamed from deps/v8/src/debug-ia32.cc)4
-rw-r--r--deps/v8/src/ia32/disasm-ia32.cc (renamed from deps/v8/src/disasm-ia32.cc)0
-rw-r--r--deps/v8/src/ia32/frames-ia32.cc (renamed from deps/v8/src/frames-ia32.cc)0
-rw-r--r--deps/v8/src/ia32/frames-ia32.h (renamed from deps/v8/src/frames-ia32.h)6
-rw-r--r--deps/v8/src/ia32/ic-ia32.cc (renamed from deps/v8/src/ic-ia32.cc)116
-rw-r--r--deps/v8/src/ia32/jump-target-ia32.cc (renamed from deps/v8/src/jump-target-ia32.cc)12
-rw-r--r--deps/v8/src/ia32/macro-assembler-ia32.cc (renamed from deps/v8/src/macro-assembler-ia32.cc)13
-rw-r--r--deps/v8/src/ia32/macro-assembler-ia32.h371
-rw-r--r--deps/v8/src/ia32/regexp-macro-assembler-ia32.cc (renamed from deps/v8/src/regexp-macro-assembler-ia32.cc)16
-rw-r--r--deps/v8/src/ia32/regexp-macro-assembler-ia32.h (renamed from deps/v8/src/regexp-macro-assembler-ia32.h)6
-rw-r--r--deps/v8/src/ia32/register-allocator-ia32.cc (renamed from deps/v8/src/register-allocator-ia32.cc)6
-rw-r--r--deps/v8/src/ia32/simulator-ia32.cc (renamed from deps/v8/src/simulator-ia32.cc)0
-rw-r--r--deps/v8/src/ia32/simulator-ia32.h (renamed from deps/v8/src/simulator-ia32.h)6
-rw-r--r--deps/v8/src/ia32/stub-cache-ia32.cc (renamed from deps/v8/src/stub-cache-ia32.cc)16
-rw-r--r--deps/v8/src/ia32/virtual-frame-ia32.cc (renamed from deps/v8/src/virtual-frame-ia32.cc)160
-rw-r--r--deps/v8/src/ia32/virtual-frame-ia32.h (renamed from deps/v8/src/virtual-frame-ia32.h)6
-rw-r--r--deps/v8/src/ic-inl.h4
-rw-r--r--deps/v8/src/ic.cc37
-rw-r--r--deps/v8/src/ic.h18
-rw-r--r--deps/v8/src/interpreter-irregexp.cc6
-rw-r--r--deps/v8/src/json-delay.js254
-rw-r--r--deps/v8/src/jsregexp.cc33
-rw-r--r--deps/v8/src/jsregexp.h12
-rw-r--r--deps/v8/src/jump-target.cc80
-rw-r--r--deps/v8/src/list-inl.h39
-rw-r--r--deps/v8/src/list.h15
-rw-r--r--deps/v8/src/log.cc386
-rw-r--r--deps/v8/src/log.h35
-rw-r--r--deps/v8/src/macro-assembler.h28
-rw-r--r--deps/v8/src/macros.py2
-rw-r--r--deps/v8/src/mark-compact.cc86
-rw-r--r--deps/v8/src/mark-compact.h11
-rw-r--r--deps/v8/src/math.js2
-rw-r--r--deps/v8/src/messages.js4
-rw-r--r--deps/v8/src/mirror-delay.js98
-rw-r--r--deps/v8/src/objects-debug.cc7
-rw-r--r--deps/v8/src/objects-inl.h88
-rw-r--r--deps/v8/src/objects.cc504
-rw-r--r--deps/v8/src/objects.h109
-rw-r--r--deps/v8/src/platform-freebsd.cc30
-rw-r--r--deps/v8/src/platform-linux.cc51
-rw-r--r--deps/v8/src/platform-macos.cc3
-rw-r--r--deps/v8/src/platform-nullos.cc2
-rw-r--r--deps/v8/src/platform-win32.cc12
-rw-r--r--deps/v8/src/platform.h17
-rw-r--r--deps/v8/src/property.h19
-rw-r--r--deps/v8/src/regexp-macro-assembler-irregexp-inl.h4
-rw-r--r--deps/v8/src/regexp-macro-assembler-tracer.h6
-rw-r--r--deps/v8/src/regexp-stack.h6
-rw-r--r--deps/v8/src/register-allocator.h5
-rw-r--r--deps/v8/src/rewriter.cc7
-rw-r--r--deps/v8/src/runtime.cc273
-rw-r--r--deps/v8/src/runtime.h95
-rw-r--r--deps/v8/src/serialize.cc83
-rw-r--r--deps/v8/src/serialize.h8
-rw-r--r--deps/v8/src/shell.h5
-rw-r--r--deps/v8/src/spaces-inl.h9
-rw-r--r--deps/v8/src/spaces.cc31
-rw-r--r--deps/v8/src/spaces.h82
-rw-r--r--deps/v8/src/string-stream.cc32
-rw-r--r--deps/v8/src/string-stream.h39
-rw-r--r--deps/v8/src/string.js10
-rw-r--r--deps/v8/src/stub-cache.cc4
-rw-r--r--deps/v8/src/stub-cache.h15
-rw-r--r--deps/v8/src/top.cc8
-rw-r--r--deps/v8/src/unicode-inl.h6
-rw-r--r--deps/v8/src/unicode.h6
-rw-r--r--deps/v8/src/usage-analyzer.h6
-rw-r--r--deps/v8/src/utils.h12
-rw-r--r--deps/v8/src/v8-counters.h4
-rw-r--r--deps/v8/src/v8.cc4
-rw-r--r--deps/v8/src/v8.h5
-rw-r--r--deps/v8/src/v8natives.js39
-rw-r--r--deps/v8/src/v8threads.cc12
-rw-r--r--deps/v8/src/version.cc87
-rw-r--r--deps/v8/src/version.h63
-rw-r--r--deps/v8/src/virtual-frame.cc46
-rw-r--r--deps/v8/src/virtual-frame.h15
-rw-r--r--deps/v8/src/x64/assembler-x64-inl.h68
-rw-r--r--deps/v8/src/x64/assembler-x64.cc36
-rw-r--r--deps/v8/src/x64/assembler-x64.h925
-rw-r--r--deps/v8/src/x64/builtins-x64.cc27
-rw-r--r--deps/v8/src/x64/codegen-x64.cc27
-rw-r--r--deps/v8/src/x64/codegen-x64.h (renamed from deps/v8/src/codegen-ia32.h)15
-rw-r--r--deps/v8/src/x64/cpu-x64.cc27
-rw-r--r--deps/v8/src/x64/debug-x64.cc27
-rw-r--r--deps/v8/src/x64/disasm-x64.cc27
-rw-r--r--deps/v8/src/x64/frames-x64.cc27
-rw-r--r--deps/v8/src/x64/frames-x64.h121
-rw-r--r--deps/v8/src/x64/ic-x64.cc27
-rw-r--r--deps/v8/src/x64/jump-target-x64.cc27
-rw-r--r--deps/v8/src/x64/macro-assembler-x64.cc27
-rw-r--r--deps/v8/src/x64/macro-assembler-x64.h (renamed from deps/v8/src/macro-assembler-ia32.h)33
-rw-r--r--deps/v8/src/x64/regexp-macro-assembler-x64.cc27
-rw-r--r--deps/v8/src/x64/regexp-macro-assembler-x64.h27
-rw-r--r--deps/v8/src/x64/register-allocator-x64.cc27
-rw-r--r--deps/v8/src/x64/simulator-x64.cc27
-rw-r--r--deps/v8/src/x64/simulator-x64.h47
-rw-r--r--deps/v8/src/x64/stub-cache-x64.cc27
-rw-r--r--deps/v8/src/x64/virtual-frame-x64.cc27
-rw-r--r--deps/v8/src/x64/virtual-frame-x64.h493
-rw-r--r--deps/v8/test/cctest/SConscript4
-rw-r--r--deps/v8/test/cctest/cctest.cc3
-rw-r--r--deps/v8/test/cctest/cctest.status9
-rw-r--r--deps/v8/test/cctest/test-api.cc534
-rw-r--r--deps/v8/test/cctest/test-assembler-arm.cc4
-rw-r--r--deps/v8/test/cctest/test-debug.cc563
-rw-r--r--deps/v8/test/cctest/test-decls.cc4
-rw-r--r--deps/v8/test/cctest/test-func-name-inference.cc27
-rw-r--r--deps/v8/test/cctest/test-hashmap.cc2
-rw-r--r--deps/v8/test/cctest/test-list.cc2
-rw-r--r--deps/v8/test/cctest/test-log-ia32.cc125
-rw-r--r--deps/v8/test/cctest/test-log.cc117
-rw-r--r--deps/v8/test/cctest/test-regexp.cc60
-rw-r--r--deps/v8/test/cctest/test-serialize.cc40
-rw-r--r--deps/v8/test/cctest/test-strings.cc154
-rw-r--r--deps/v8/test/cctest/test-version.cc88
-rw-r--r--deps/v8/test/mjsunit/array-reduce.js514
-rw-r--r--deps/v8/test/mjsunit/array-sort.js188
-rw-r--r--deps/v8/test/mjsunit/bugs/bug-334.js90
-rw-r--r--deps/v8/test/mjsunit/codegen_coverage.js91
-rw-r--r--deps/v8/test/mjsunit/constant-folding.js61
-rw-r--r--deps/v8/test/mjsunit/debug-backtrace.js36
-rw-r--r--deps/v8/test/mjsunit/debug-handle.js92
-rw-r--r--deps/v8/test/mjsunit/debug-setbreakpoint.js20
-rw-r--r--deps/v8/test/mjsunit/enumeration-order.js60
-rw-r--r--deps/v8/test/mjsunit/eval-enclosing-function-name.js76
-rw-r--r--deps/v8/test/mjsunit/json.js197
-rw-r--r--deps/v8/test/mjsunit/keyed-ic.js29
-rw-r--r--deps/v8/test/mjsunit/mirror-unresolved-function.js2
-rw-r--r--deps/v8/test/mjsunit/mjsunit.js51
-rw-r--r--deps/v8/test/mjsunit/mjsunit.status18
-rw-r--r--deps/v8/test/mjsunit/negate.js6
-rw-r--r--deps/v8/test/mjsunit/number-limits.js12
-rw-r--r--deps/v8/test/mjsunit/receiver-in-with-calls.js47
-rw-r--r--deps/v8/test/mjsunit/regexp-multiline-stack-trace.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-318.js4
-rw-r--r--deps/v8/test/mjsunit/regress/regress-326.js40
-rw-r--r--deps/v8/test/mjsunit/smi-ops.js487
-rw-r--r--deps/v8/test/mjsunit/tools/codemap.js158
-rw-r--r--deps/v8/test/mjsunit/tools/consarray.js60
-rw-r--r--deps/v8/test/mjsunit/tools/csvparser.js79
-rw-r--r--deps/v8/test/mjsunit/tools/profile.js348
-rw-r--r--deps/v8/test/mjsunit/tools/profile_view.js95
-rw-r--r--deps/v8/test/mjsunit/undeletable-functions.js181
-rw-r--r--deps/v8/tools/codemap.js230
-rw-r--r--deps/v8/tools/consarray.js93
-rw-r--r--deps/v8/tools/csvparser.js98
-rw-r--r--deps/v8/tools/gyp/v8.gyp726
-rw-r--r--deps/v8/tools/linux-tick-processor16
-rw-r--r--deps/v8/tools/profile.js605
-rw-r--r--deps/v8/tools/profile_view.js323
-rw-r--r--deps/v8/tools/splaytree.js4
-rw-r--r--deps/v8/tools/tickprocessor.js646
-rw-r--r--deps/v8/tools/tickprocessor.py2
-rwxr-xr-x[-rw-r--r--]deps/v8/tools/v8.xcodeproj/project.pbxproj128
-rw-r--r--deps/v8/tools/visual_studio/arm.vsprops2
-rw-r--r--deps/v8/tools/visual_studio/d8.vcproj4
-rw-r--r--deps/v8/tools/visual_studio/ia32.vsprops11
-rw-r--r--deps/v8/tools/visual_studio/js2c.cmd2
-rw-r--r--deps/v8/tools/visual_studio/v8.vcproj12
-rw-r--r--deps/v8/tools/visual_studio/v8_base.vcproj54
-rw-r--r--deps/v8/tools/visual_studio/v8_base_arm.vcproj72
-rw-r--r--deps/v8/tools/visual_studio/v8_cctest.vcproj12
-rw-r--r--deps/v8/tools/visual_studio/v8_cctest_arm.vcproj8
-rw-r--r--deps/v8/tools/visual_studio/v8_mksnapshot.vcproj4
-rw-r--r--deps/v8/tools/visual_studio/v8_process_sample.vcproj4
-rw-r--r--deps/v8/tools/visual_studio/v8_shell_sample.vcproj4
-rw-r--r--deps/v8/tools/visual_studio/v8_snapshot.vcproj4
-rw-r--r--deps/v8/tools/visual_studio/v8_snapshot_cc.vcproj4
-rw-r--r--deps/v8/tools/windows-tick-processor.bat5
251 files changed, 15652 insertions, 2807 deletions
diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog
index d5c30c7f5..2ff993659 100644
--- a/deps/v8/ChangeLog
+++ b/deps/v8/ChangeLog
@@ -1,3 +1,61 @@
+2009-05-11: Version 1.2.3
+
+ Fixed bug in reporting of out-of-memory situations.
+
+ Introduced hidden prototypes on certain builtin prototype objects
+ such as String.prototype to emulate JSC's behavior of restoring
+ the original function when deleting functions from those prototype
+ objects.
+
+ Fixed crash bug in the register allocator.
+
+
+2009-05-04: Version 1.2.2
+
+ Fixed bug in array sorting for sparse arrays (issue 326).
+
+ Added support for adding a soname when building a shared library
+ on Linux (issue 151).
+
+ Fixed bug caused by morphing internal ASCII strings to external
+ two-byte strings. Slices over ASCII strings have to forward ASCII
+ checks to the underlying buffer string.
+
+ Allowed API call-as-function handlers to be called as
+ constructors.
+
+ Fixed a crash bug where an external string was disposed but a
+ slice of the external string survived as a symbol.
+
+
+2009-04-27: Version 1.2.1
+
+ Added EcmaScript 5 JSON object.
+
+ Fix bug in preemption support on ARM.
+
+
+2009-04-23: Version 1.2.0
+
+ Optimized floating-point operations on ARM.
+
+ Added a number of extensions to the debugger API.
+
+ Changed the enumeration order for unsigned integer keys to always
+ be numerical order.
+
+ Added a "read" extension to the shell sample.
+
+ Added support for Array.prototype.reduce and
+ Array.prototype.reduceRight.
+
+ Added an option to the SCons build to control Microsoft Visual C++
+ link-time code generation.
+
+ Fixed a number of bugs (in particular issue 315, issue 316,
+ issue 317 and issue 318).
+
+
2009-04-15: Version 1.1.10
Fixed crash bug that occurred when loading a const variable in the
@@ -27,13 +85,13 @@
Changed test-debug/ThreadedDebugging to be non-flaky (issue 96).
- Fixed step-in handling for Function.prototype.apply and call in
+ Fixed step-in handling for Function.prototype.apply and call in
the debugger (issue 269).
Fixed v8::Object::DeleteHiddenValue to not bail out when there
are no hidden properties.
- Added workaround for crash bug, where external symbol table
+ Added workaround for crash bug, where external symbol table
entries with deleted resources would lead to NPEs when looking
up in the symbol table.
diff --git a/deps/v8/SConstruct b/deps/v8/SConstruct
index 01083cc5d..0c506790e 100644
--- a/deps/v8/SConstruct
+++ b/deps/v8/SConstruct
@@ -35,6 +35,7 @@ root_dir = dirname(File('SConstruct').rfile().abspath)
sys.path.append(join(root_dir, 'tools'))
import js2c, utils
+
# ANDROID_TOP is the top of the Android checkout, fetched from the environment
# variable 'TOP'. You will also need to set the CXX, CC, AR and RANLIB
# environment variables to the cross-compiling tools.
@@ -83,7 +84,8 @@ ANDROID_LINKFLAGS = ['-nostdlib',
LIBRARY_FLAGS = {
'all': {
- 'CPPDEFINES': ['ENABLE_LOGGING_AND_PROFILING']
+ 'CPPDEFINES': ['ENABLE_LOGGING_AND_PROFILING'],
+ 'CPPPATH': [join(root_dir, 'src')]
},
'gcc': {
'all': {
@@ -94,6 +96,7 @@ LIBRARY_FLAGS = {
'CCFLAGS': ['-g', '-O0'],
'CPPDEFINES': ['ENABLE_DISASSEMBLER', 'DEBUG'],
'os:android': {
+ 'CPPDEFINES': ['ENABLE_DEBUGGER_SUPPORT'],
'CCFLAGS': ['-mthumb']
}
},
@@ -102,13 +105,13 @@ LIBRARY_FLAGS = {
'-ffunction-sections'],
'os:android': {
'CCFLAGS': ['-mthumb', '-Os'],
- 'CPPDEFINES': ['SK_RELEASE', 'NDEBUG']
+ 'CPPDEFINES': ['SK_RELEASE', 'NDEBUG', 'ENABLE_DEBUGGER_SUPPORT']
}
},
'os:linux': {
'CCFLAGS': ['-ansi'],
'library:shared': {
- 'LIBS': ['pthread', 'rt']
+ 'LIBS': ['pthread']
}
},
'os:macos': {
@@ -129,9 +132,30 @@ LIBRARY_FLAGS = {
'-Wstrict-aliasing=2'],
'CPPPATH': ANDROID_INCLUDES,
},
+ 'wordsize:32': {
+ 'arch:x64': {
+ 'CCFLAGS': ['-m64'],
+ 'LINKFLAGS': ['-m64']
+ }
+ },
'wordsize:64': {
- 'CCFLAGS': ['-m32'],
- 'LINKFLAGS': ['-m32']
+ 'arch:ia32': {
+ 'CCFLAGS': ['-m32'],
+ 'LINKFLAGS': ['-m32']
+ },
+ 'arch:arm': {
+ 'CCFLAGS': ['-m32'],
+ 'LINKFLAGS': ['-m32']
+ }
+ },
+ 'arch:ia32': {
+ 'CPPDEFINES': ['V8_TARGET_ARCH_IA32']
+ },
+ 'arch:arm': {
+ 'CPPDEFINES': ['V8_TARGET_ARCH_ARM']
+ },
+ 'arch:x64': {
+ 'CPPDEFINES': ['V8_TARGET_ARCH_X64']
},
'prof:oprofile': {
'CPPDEFINES': ['ENABLE_OPROFILE_AGENT']
@@ -148,6 +172,9 @@ LIBRARY_FLAGS = {
'ARFLAGS': ['/NOLOGO'],
'CCPDBFLAGS': ['/Zi']
},
+ 'arch:ia32': {
+ 'CPPDEFINES': ['V8_TARGET_ARCH_IA32']
+ },
'mode:debug': {
'CCFLAGS': ['/Od', '/Gm'],
'CPPDEFINES': ['_DEBUG', 'ENABLE_DISASSEMBLER', 'DEBUG'],
@@ -160,16 +187,20 @@ LIBRARY_FLAGS = {
}
},
'mode:release': {
- 'CCFLAGS': ['/O2', '/GL'],
- 'LINKFLAGS': ['/OPT:REF', '/OPT:ICF', '/LTCG'],
- 'ARFLAGS': ['/LTCG'],
+ 'CCFLAGS': ['/O2'],
+ 'LINKFLAGS': ['/OPT:REF', '/OPT:ICF'],
'msvcrt:static': {
'CCFLAGS': ['/MT']
},
'msvcrt:shared': {
'CCFLAGS': ['/MD']
+ },
+ 'msvcltcg:on': {
+ 'CCFLAGS': ['/GL'],
+ 'LINKFLAGS': ['/LTCG'],
+ 'ARFLAGS': ['/LTCG'],
}
- },
+ }
}
}
@@ -181,17 +212,16 @@ V8_EXTRA_FLAGS = {
'WARNINGFLAGS': ['-Wall', '-Werror', '-W',
'-Wno-unused-parameter']
},
- 'arch:arm': {
- 'CPPDEFINES': ['ARM']
- },
- 'arch:android': {
- 'CPPDEFINES': ['ARM']
- },
'os:win32': {
'WARNINGFLAGS': ['-pedantic', '-Wno-long-long']
},
'os:linux': {
- 'WARNINGFLAGS': ['-pedantic']
+ 'WARNINGFLAGS': ['-pedantic'],
+ 'library:shared': {
+ 'soname:on': {
+ 'LINKFLAGS': ['-Wl,-soname,${SONAME}']
+ }
+ }
},
'os:macos': {
'WARNINGFLAGS': ['-pedantic']
@@ -209,7 +239,7 @@ V8_EXTRA_FLAGS = {
'LIBS': ['winmm', 'ws2_32']
},
'arch:arm': {
- 'CPPDEFINES': ['ARM'],
+ 'CPPDEFINES': ['V8_TARGET_ARCH_ARM'],
# /wd4996 is to silence the warning about sscanf
# used by the arm simulator.
'WARNINGFLAGS': ['/wd4996']
@@ -224,7 +254,7 @@ V8_EXTRA_FLAGS = {
MKSNAPSHOT_EXTRA_FLAGS = {
'gcc': {
'os:linux': {
- 'LIBS': ['pthread', 'rt'],
+ 'LIBS': ['pthread'],
},
'os:macos': {
'LIBS': ['pthread'],
@@ -238,6 +268,7 @@ MKSNAPSHOT_EXTRA_FLAGS = {
},
'msvc': {
'all': {
+ 'CPPDEFINES': ['_HAS_EXCEPTIONS=0'],
'LIBS': ['winmm', 'ws2_32']
}
}
@@ -268,7 +299,7 @@ CCTEST_EXTRA_FLAGS = {
'LIBPATH': [abspath('.')]
},
'os:linux': {
- 'LIBS': ['pthread', 'rt'],
+ 'LIBS': ['pthread'],
},
'os:macos': {
'LIBS': ['pthread'],
@@ -279,10 +310,34 @@ CCTEST_EXTRA_FLAGS = {
'os:win32': {
'LIBS': ['winmm', 'ws2_32']
},
- 'wordsize:64': {
- 'CCFLAGS': ['-m32'],
- 'LINKFLAGS': ['-m32']
+ 'os:android': {
+ 'CPPDEFINES': ['ANDROID', '__ARM_ARCH_5__', '__ARM_ARCH_5T__',
+ '__ARM_ARCH_5E__', '__ARM_ARCH_5TE__'],
+ 'CCFLAGS': ANDROID_FLAGS,
+ 'CPPPATH': ANDROID_INCLUDES,
+ 'LIBPATH': [ANDROID_TOP + '/out/target/product/generic/obj/lib'],
+ 'LINKFLAGS': ANDROID_LINKFLAGS,
+ 'LIBS': ['c', 'stdc++', 'm'],
+ 'mode:release': {
+ 'CPPDEFINES': ['SK_RELEASE', 'NDEBUG']
+ }
},
+ 'wordsize:32': {
+ 'arch:x64': {
+ 'CCFLAGS': ['-m64'],
+ 'LINKFLAGS': ['-m64']
+ }
+ },
+ 'wordsize:64': {
+ 'arch:ia32': {
+ 'CCFLAGS': ['-m32'],
+ 'LINKFLAGS': ['-m32']
+ },
+ 'arch:arm': {
+ 'CCFLAGS': ['-m32'],
+ 'LINKFLAGS': ['-m32']
+ }
+ }
},
'msvc': {
'all': {
@@ -291,6 +346,9 @@ CCTEST_EXTRA_FLAGS = {
},
'library:shared': {
'CPPDEFINES': ['USING_V8_SHARED']
+ },
+ 'arch:ia32': {
+ 'CPPDEFINES': ['V8_TARGET_ARCH_IA32']
}
}
}
@@ -307,7 +365,7 @@ SAMPLE_FLAGS = {
'CCFLAGS': ['-fno-rtti', '-fno-exceptions']
},
'os:linux': {
- 'LIBS': ['pthread', 'rt'],
+ 'LIBS': ['pthread'],
},
'os:macos': {
'LIBS': ['pthread'],
@@ -330,9 +388,21 @@ SAMPLE_FLAGS = {
'CPPDEFINES': ['SK_RELEASE', 'NDEBUG']
}
},
+ 'wordsize:32': {
+ 'arch:x64': {
+ 'CCFLAGS': ['-m64'],
+ 'LINKFLAGS': ['-m64']
+ }
+ },
'wordsize:64': {
- 'CCFLAGS': ['-m32'],
- 'LINKFLAGS': ['-m32']
+ 'arch:ia32': {
+ 'CCFLAGS': ['-m32'],
+ 'LINKFLAGS': ['-m32']
+ },
+ 'arch:arm': {
+ 'CCFLAGS': ['-m32'],
+ 'LINKFLAGS': ['-m32']
+ }
},
'mode:release': {
'CCFLAGS': ['-O2']
@@ -359,14 +429,21 @@ SAMPLE_FLAGS = {
},
'mode:release': {
'CCFLAGS': ['/O2'],
- 'LINKFLAGS': ['/OPT:REF', '/OPT:ICF', '/LTCG'],
+ 'LINKFLAGS': ['/OPT:REF', '/OPT:ICF'],
'msvcrt:static': {
'CCFLAGS': ['/MT']
},
'msvcrt:shared': {
'CCFLAGS': ['/MD']
+ },
+ 'msvcltcg:on': {
+ 'CCFLAGS': ['/GL'],
+ 'LINKFLAGS': ['/LTCG'],
}
},
+ 'arch:ia32': {
+ 'CPPDEFINES': ['V8_TARGET_ARCH_IA32']
+ },
'mode:debug': {
'CCFLAGS': ['/Od'],
'LINKFLAGS': ['/DEBUG'],
@@ -387,7 +464,7 @@ D8_FLAGS = {
'LIBS': ['readline']
},
'os:linux': {
- 'LIBS': ['pthread', 'rt'],
+ 'LIBS': ['pthread'],
},
'os:macos': {
'LIBS': ['pthread'],
@@ -443,17 +520,17 @@ SIMPLE_OPTIONS = {
'toolchain': {
'values': ['gcc', 'msvc'],
'default': TOOLCHAIN_GUESS,
- 'help': 'the toolchain to use'
+ 'help': 'the toolchain to use (' + TOOLCHAIN_GUESS + ')'
},
'os': {
'values': ['freebsd', 'linux', 'macos', 'win32', 'android'],
'default': OS_GUESS,
- 'help': 'the os to build for'
+ 'help': 'the os to build for (' + OS_GUESS + ')'
},
'arch': {
- 'values':['arm', 'ia32'],
+ 'values':['arm', 'ia32', 'x64'],
'default': ARCH_GUESS,
- 'help': 'the architecture to build for'
+ 'help': 'the architecture to build for (' + ARCH_GUESS + ')'
},
'snapshot': {
'values': ['on', 'off', 'nobuild'],
@@ -470,10 +547,20 @@ SIMPLE_OPTIONS = {
'default': 'static',
'help': 'the type of library to produce'
},
+ 'soname': {
+ 'values': ['on', 'off'],
+ 'default': 'off',
+ 'help': 'turn on setting soname for Linux shared library'
+ },
'msvcrt': {
'values': ['static', 'shared'],
'default': 'static',
- 'help': 'the type of MSVCRT library to use'
+ 'help': 'the type of Microsoft Visual C++ runtime library to use'
+ },
+ 'msvcltcg': {
+ 'values': ['on', 'off'],
+ 'default': 'on',
+ 'help': 'use Microsoft Visual C++ link-time code generation'
},
'wordsize': {
'values': ['64', '32'],
@@ -515,6 +602,49 @@ def GetOptions():
return result
+def GetVersionComponents():
+ MAJOR_VERSION_PATTERN = re.compile(r"#define\s+MAJOR_VERSION\s+(.*)")
+ MINOR_VERSION_PATTERN = re.compile(r"#define\s+MINOR_VERSION\s+(.*)")
+ BUILD_NUMBER_PATTERN = re.compile(r"#define\s+BUILD_NUMBER\s+(.*)")
+ PATCH_LEVEL_PATTERN = re.compile(r"#define\s+PATCH_LEVEL\s+(.*)")
+
+ patterns = [MAJOR_VERSION_PATTERN,
+ MINOR_VERSION_PATTERN,
+ BUILD_NUMBER_PATTERN,
+ PATCH_LEVEL_PATTERN]
+
+ source = open(join(root_dir, 'src', 'version.cc')).read()
+ version_components = []
+ for pattern in patterns:
+ match = pattern.search(source)
+ if match:
+ version_components.append(match.group(1).strip())
+ else:
+ version_components.append('0')
+
+ return version_components
+
+
+def GetVersion():
+ version_components = GetVersionComponents()
+
+ if version_components[len(version_components) - 1] == '0':
+ version_components.pop()
+ return '.'.join(version_components)
+
+
+def GetSpecificSONAME():
+ SONAME_PATTERN = re.compile(r"#define\s+SONAME\s+\"(.*)\"")
+
+ source = open(join(root_dir, 'src', 'version.cc')).read()
+ match = SONAME_PATTERN.search(source)
+
+ if match:
+ return match.group(1).strip()
+ else:
+ return ''
+
+
def SplitList(str):
return [ s for s in str.split(",") if len(s) > 0 ]
@@ -537,6 +667,12 @@ def VerifyOptions(env):
Abort("Profiling on windows only supported for static library.")
if env['prof'] == 'oprofile' and env['os'] != 'linux':
Abort("OProfile is only supported on Linux.")
+ if env['os'] == 'win32' and env['soname'] == 'on':
+ Abort("Shared Object soname not applicable for Windows.")
+ if env['soname'] == 'on' and env['library'] == 'static':
+ Abort("Shared Object soname not applicable for static library.")
+ if env['arch'] == 'x64' and env['os'] != 'linux':
+ Abort("X64 compilation only allowed on Linux OS.")
for (name, option) in SIMPLE_OPTIONS.iteritems():
if (not option.get('default')) and (name not in ARGUMENTS):
message = ("A value for option %s must be specified (%s)." %
@@ -565,13 +701,13 @@ class BuildContext(object):
def AddRelevantFlags(self, initial, flags):
result = initial.copy()
- self.AppendFlags(result, flags.get('all'))
toolchain = self.options['toolchain']
if toolchain in flags:
self.AppendFlags(result, flags[toolchain].get('all'))
for option in sorted(self.options.keys()):
value = self.options[option]
self.AppendFlags(result, flags[toolchain].get(option + ':' + value))
+ self.AppendFlags(result, flags.get('all'))
return result
def AddRelevantSubFlags(self, options, flags):
@@ -667,11 +803,23 @@ def BuildSpecific(env, mode, env_overrides):
'd8': d8_flags
}
+ # Generate library base name.
target_id = mode
suffix = SUFFIXES[target_id]
library_name = 'v8' + suffix
+ version = GetVersion()
+ if context.options['soname'] == 'on':
+ # When building shared object with SONAME version the library name.
+ library_name += '-' + version
env['LIBRARY'] = library_name
+ # Generate library SONAME if required by the build.
+ if context.options['soname'] == 'on':
+ soname = GetSpecificSONAME()
+ if soname == '':
+ soname = 'lib' + library_name + '.so'
+ env['SONAME'] = soname
+
# Build the object files by invoking SCons recursively.
(object_files, shell_files, mksnapshot) = env.SConscript(
join('src', 'SConscript'),
diff --git a/deps/v8/include/v8-debug.h b/deps/v8/include/v8-debug.h
index 4c639c183..3adc0a0d5 100644
--- a/deps/v8/include/v8-debug.h
+++ b/deps/v8/include/v8-debug.h
@@ -25,8 +25,8 @@
// (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_DEBUG_H_
-#define V8_DEBUG_H_
+#ifndef V8_V8_DEBUG_H_
+#define V8_V8_DEBUG_H_
#include "v8.h"
@@ -79,48 +79,116 @@ enum DebugEvent {
};
-/**
- * Debug event callback function.
- *
- * \param event the type of the debug event that triggered the callback
- * (enum DebugEvent)
- * \param exec_state execution state (JavaScript object)
- * \param event_data event specific data (JavaScript object)
- * \param data value passed by the user to SetDebugEventListener
- */
-typedef void (*DebugEventCallback)(DebugEvent event,
- Handle<Object> exec_state,
- Handle<Object> event_data,
- Handle<Value> data);
-
-
-/**
- * Debug message callback function.
- *
- * \param message the debug message
- * \param length length of the message
- * \param data the data value passed when registering the message handler
- * A DebugMessageHandler does not take posession of the message string,
- * and must not rely on the data persisting after the handler returns.
- */
-typedef void (*DebugMessageHandler)(const uint16_t* message, int length,
- void* data);
-
-/**
- * Debug host dispatch callback function.
- *
- * \param dispatch the dispatch value
- * \param data the data value passed when registering the dispatch handler
- */
-typedef void (*DebugHostDispatchHandler)(void* dispatch,
- void* data);
-
-
-
class EXPORT Debug {
public:
+ /**
+ * A client object passed to the v8 debugger whose ownership will be taken by
+ * it. v8 is always responsible for deleting the object.
+ */
+ class ClientData {
+ public:
+ virtual ~ClientData() {}
+ };
+
+
+ /**
+ * A message object passed to the debug message handler.
+ */
+ class Message {
+ public:
+ /**
+ * Check type of message.
+ */
+ virtual bool IsEvent() const = 0;
+ virtual bool IsResponse() const = 0;
+ virtual DebugEvent GetEvent() const = 0;
+
+ /**
+ * Indicate whether this is a response to a continue command which will
+ * start the VM running after this is processed.
+ */
+ virtual bool WillStartRunning() const = 0;
+
+ /**
+ * Access to execution state and event data. Don't store these cross
+ * callbacks as their content becomes invalid. These objects are from the
+ * debugger event that started the debug message loop.
+ */
+ virtual Handle<Object> GetExecutionState() const = 0;
+ virtual Handle<Object> GetEventData() const = 0;
+
+ /**
+ * Get the debugger protocol JSON.
+ */
+ virtual Handle<String> GetJSON() const = 0;
+
+ /**
+ * Get the context active when the debug event happened. Note this is not
+ * the current active context as the JavaScript part of the debugger is
+ * running in it's own context which is entered at this point.
+ */
+ virtual Handle<Context> GetEventContext() const = 0;
+
+ /**
+ * Client data passed with the corresponding request if any. This is the
+ * client_data data value passed into Debug::SendCommand along with the
+ * request that led to the message or NULL if the message is an event. The
+ * debugger takes ownership of the data and will delete it even if there is
+ * no message handler.
+ */
+ virtual ClientData* GetClientData() const = 0;
+
+ virtual ~Message() {}
+ };
+
+
+ /**
+ * Debug event callback function.
+ *
+ * \param event the type of the debug event that triggered the callback
+ * (enum DebugEvent)
+ * \param exec_state execution state (JavaScript object)
+ * \param event_data event specific data (JavaScript object)
+ * \param data value passed by the user to SetDebugEventListener
+ */
+ typedef void (*EventCallback)(DebugEvent event,
+ Handle<Object> exec_state,
+ Handle<Object> event_data,
+ Handle<Value> data);
+
+
+ /**
+ * Debug message callback function.
+ *
+ * \param message the debug message handler message object
+ * \param length length of the message
+ * \param client_data the data value passed when registering the message handler
+
+ * A MessageHandler does not take posession of the message string,
+ * and must not rely on the data persisting after the handler returns.
+ *
+ * This message handler is deprecated. Use MessageHandler2 instead.
+ */
+ typedef void (*MessageHandler)(const uint16_t* message, int length,
+ ClientData* client_data);
+
+ /**
+ * Debug message callback function.
+ *
+ * \param message the debug message handler message object
+
+ * A MessageHandler does not take posession of the message data,
+ * and must not rely on the data persisting after the handler returns.
+ */
+ typedef void (*MessageHandler2)(const Message& message);
+
+ /**
+ * Debug host dispatch callback function.
+ */
+ typedef void (*HostDispatchHandler)();
+
// Set a C debug event listener.
- static bool SetDebugEventListener(DebugEventCallback that,
+ static bool SetDebugEventListener(EventCallback that,
Handle<Value> data = Handle<Value>());
// Set a JavaScript debug event listener.
@@ -130,15 +198,17 @@ class EXPORT Debug {
// Break execution of JavaScript.
static void DebugBreak();
- // Message based interface. The message protocol is JSON.
- static void SetMessageHandler(DebugMessageHandler handler, void* data = NULL,
- bool message_handler_thread = true);
- static void SendCommand(const uint16_t* command, int length);
+ // Message based interface. The message protocol is JSON. NOTE the message
+ // handler thread is not supported any more parameter must be false.
+ static void SetMessageHandler(MessageHandler handler,
+ bool message_handler_thread = false);
+ static void SetMessageHandler2(MessageHandler2 handler);
+ static void SendCommand(const uint16_t* command, int length,
+ ClientData* client_data = NULL);
// Dispatch interface.
- static void SetHostDispatchHandler(DebugHostDispatchHandler handler,
- void* data = NULL);
- static void SendHostDispatch(void* dispatch);
+ static void SetHostDispatchHandler(HostDispatchHandler handler,
+ int period = 100);
/**
* Run a JavaScript function in the debugger.
@@ -176,4 +246,4 @@ class EXPORT Debug {
#undef EXPORT
-#endif // V8_DEBUG_H_
+#endif // V8_V8_DEBUG_H_
diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h
index 1ddaee02c..9f59e4e6b 100644
--- a/deps/v8/include/v8.h
+++ b/deps/v8/include/v8.h
@@ -41,10 +41,15 @@
#include <stdio.h>
#ifdef _WIN32
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef short int16_t; // NOLINT
+typedef unsigned short uint16_t; // NOLINT
typedef int int32_t;
typedef unsigned int uint32_t;
-typedef unsigned short uint16_t; // NOLINT
-typedef long long int64_t; // NOLINT
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+// intptr_t is defined in crtdefs.h through stdio.h.
// Setup for Windows DLL export/import. When building the V8 DLL the
// BUILDING_V8_SHARED needs to be defined. When building a program which uses
@@ -529,6 +534,13 @@ class V8EXPORT Script {
* Returns the script id value.
*/
Local<Value> Id();
+
+ /**
+ * Associate an additional data object with the script. This is mainly used
+ * with the debugger as this data object is only available through the
+ * debugger API.
+ */
+ void SetData(Handle<Value> data);
};
@@ -540,9 +552,19 @@ class V8EXPORT Message {
Local<String> Get() const;
Local<String> GetSourceLine() const;
+ /**
+ * Returns the resource name for the script from where the function causing
+ * the error originates.
+ */
Handle<Value> GetScriptResourceName() const;
/**
+ * Returns the resource data for the script from where the function causing
+ * the error originates.
+ */
+ Handle<Value> GetScriptData() const;
+
+ /**
* Returns the number, 1-based, of the line where the error occurred.
*/
int GetLineNumber() const;
@@ -805,14 +827,14 @@ class V8EXPORT String : public Primitive {
};
/**
- * Get the ExternalStringResource for an external string. Only
- * valid if IsExternal() returns true.
+ * Get the ExternalStringResource for an external string. Returns
+ * NULL if IsExternal() doesn't return true.
*/
ExternalStringResource* GetExternalStringResource() const;
/**
* Get the ExternalAsciiStringResource for an external ascii string.
- * Only valid if IsExternalAscii() returns true.
+ * Returns NULL if IsExternalAscii() doesn't return true.
*/
ExternalAsciiStringResource* GetExternalAsciiStringResource() const;
@@ -1028,6 +1050,18 @@ class V8EXPORT Object : public Value {
bool Set(Handle<Value> key,
Handle<Value> value,
PropertyAttribute attribs = None);
+
+ // Sets a local property on this object, bypassing interceptors and
+ // overriding accessors or read-only properties.
+ //
+ // Note that if the object has an interceptor the property will be set
+ // locally, but since the interceptor takes precedence the local property
+ // will only be returned if the interceptor doesn't return a value.
+ //
+ // Note also that this only works for named properties.
+ bool ForceSet(Handle<Value> key,
+ Handle<Value> value,
+ PropertyAttribute attribs = None);
Local<Value> Get(Handle<Value> key);
// TODO(1245389): Replace the type-specific versions of these
@@ -1093,6 +1127,9 @@ class V8EXPORT Object : public Value {
/**
* Returns the identity hash for this object. The current implemenation uses
* a hidden property on the object to store the identity hash.
+ *
+ * The return value will never be 0. Also, it is not guaranteed to be
+ * unique.
*/
int GetIdentityHash();
@@ -2043,6 +2080,24 @@ class V8EXPORT V8 {
static void ResumeProfiler();
/**
+ * If logging is performed into a memory buffer (via --logfile=*), allows to
+ * retrieve previously written messages. This can be used for retrieving
+ * profiler log data in the application. This function is thread-safe.
+ *
+ * Caller provides a destination buffer that must exist during GetLogLines
+ * call. Only whole log lines are copied into the buffer.
+ *
+ * \param from_pos specified a point in a buffer to read from, 0 is the
+ * beginning of a buffer. It is assumed that caller updates its current
+ * position using returned size value from the previous call.
+ * \param dest_buf destination buffer for log data.
+ * \param max_size size of the destination buffer.
+ * \returns actual size of log data copied into buffer.
+ */
+ static int GetLogLines(int from_pos, char* dest_buf, int max_size);
+
+
+ /**
* Releases any resources used by v8 and stops any utility threads
* that may be running. Note that disposing v8 is permanent, it
* cannot be reinitialized.
@@ -2223,6 +2278,14 @@ class V8EXPORT Context {
static bool InContext();
/**
+ * Associate an additional data object with the context. This is mainly used
+ * with the debugger to provide additional information on the context through
+ * the debugger API.
+ */
+ void SetData(Handle<Value> data);
+ Local<Value> GetData();
+
+ /**
* Stack-allocated class which sets the execution context for all
* operations executed within a local scope.
*/
diff --git a/deps/v8/samples/shell.cc b/deps/v8/samples/shell.cc
index 087d4fd46..27ed293e7 100644
--- a/deps/v8/samples/shell.cc
+++ b/deps/v8/samples/shell.cc
@@ -38,6 +38,7 @@ bool ExecuteString(v8::Handle<v8::String> source,
bool print_result,
bool report_exceptions);
v8::Handle<v8::Value> Print(const v8::Arguments& args);
+v8::Handle<v8::Value> Read(const v8::Arguments& args);
v8::Handle<v8::Value> Load(const v8::Arguments& args);
v8::Handle<v8::Value> Quit(const v8::Arguments& args);
v8::Handle<v8::Value> Version(const v8::Arguments& args);
@@ -52,6 +53,8 @@ int RunMain(int argc, char* argv[]) {
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
// Bind the global 'print' function to the C++ Print callback.
global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print));
+ // Bind the global 'read' function to the C++ Read callback.
+ global->Set(v8::String::New("read"), v8::FunctionTemplate::New(Read));
// Bind the global 'load' function to the C++ Load callback.
global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load));
// Bind the 'quit' function
@@ -135,6 +138,25 @@ v8::Handle<v8::Value> Print(const v8::Arguments& args) {
}
+// The callback that is invoked by v8 whenever the JavaScript 'read'
+// function is called. This function loads the content of the file named in
+// the argument into a JavaScript string.
+v8::Handle<v8::Value> Read(const v8::Arguments& args) {
+ if (args.Length() != 1) {
+ return v8::ThrowException(v8::String::New("Bad parameters"));
+ }
+ v8::String::Utf8Value file(args[0]);
+ if (*file == NULL) {
+ return v8::ThrowException(v8::String::New("Error loading file"));
+ }
+ v8::Handle<v8::String> source = ReadFile(*file);
+ if (source.IsEmpty()) {
+ return v8::ThrowException(v8::String::New("Error loading file"));
+ }
+ return source;
+}
+
+
// The callback that is invoked by v8 whenever the JavaScript 'load'
// function is called. Loads, compiles and executes its argument
// JavaScript file.
diff --git a/deps/v8/src/SConscript b/deps/v8/src/SConscript
index 97fb7d6ca..59c452b7c 100644..100755
--- a/deps/v8/src/SConscript
+++ b/deps/v8/src/SConscript
@@ -50,23 +50,36 @@ SOURCES = {
'scopeinfo.cc', 'scopes.cc', 'serialize.cc', 'snapshot-common.cc',
'spaces.cc', 'string-stream.cc', 'stub-cache.cc', 'token.cc', 'top.cc',
'unicode.cc', 'usage-analyzer.cc', 'utils.cc', 'v8-counters.cc',
- 'v8.cc', 'v8threads.cc', 'variables.cc', 'virtual-frame.cc', 'zone.cc'
+ 'v8.cc', 'v8threads.cc', 'variables.cc', 'version.cc',
+ 'virtual-frame.cc', 'zone.cc'
],
'arch:arm': [
- 'assembler-arm.cc', 'builtins-arm.cc', 'codegen-arm.cc', 'cpu-arm.cc',
- 'disasm-arm.cc', 'debug-arm.cc', 'frames-arm.cc', 'ic-arm.cc',
- 'jump-target-arm.cc', 'macro-assembler-arm.cc',
- 'regexp-macro-assembler-arm.cc', 'register-allocator-arm.cc',
- 'stub-cache-arm.cc', 'virtual-frame-arm.cc'
+ 'arm/assembler-arm.cc', 'arm/builtins-arm.cc',
+ 'arm/codegen-arm.cc', 'arm/cpu-arm.cc', 'arm/disasm-arm.cc',
+ 'arm/debug-arm.cc', 'arm/frames-arm.cc', 'arm/ic-arm.cc',
+ 'arm/jump-target-arm.cc', 'arm/macro-assembler-arm.cc',
+ 'arm/regexp-macro-assembler-arm.cc',
+ 'arm/register-allocator-arm.cc', 'arm/stub-cache-arm.cc',
+ 'arm/virtual-frame-arm.cc'
],
'arch:ia32': [
- 'assembler-ia32.cc', 'builtins-ia32.cc', 'codegen-ia32.cc',
- 'cpu-ia32.cc', 'disasm-ia32.cc', 'debug-ia32.cc', 'frames-ia32.cc',
- 'ic-ia32.cc', 'jump-target-ia32.cc', 'macro-assembler-ia32.cc',
- 'regexp-macro-assembler-ia32.cc', 'register-allocator-ia32.cc',
- 'stub-cache-ia32.cc', 'virtual-frame-ia32.cc'
+ 'ia32/assembler-ia32.cc', 'ia32/builtins-ia32.cc',
+ 'ia32/codegen-ia32.cc', 'ia32/cpu-ia32.cc', 'ia32/disasm-ia32.cc',
+ 'ia32/debug-ia32.cc', 'ia32/frames-ia32.cc', 'ia32/ic-ia32.cc',
+ 'ia32/jump-target-ia32.cc', 'ia32/macro-assembler-ia32.cc',
+ 'ia32/regexp-macro-assembler-ia32.cc',
+ 'ia32/register-allocator-ia32.cc', 'ia32/stub-cache-ia32.cc',
+ 'ia32/virtual-frame-ia32.cc'
],
- 'simulator:arm': ['simulator-arm.cc'],
+ 'arch:x64': [
+ 'x64/assembler-x64.cc', 'x64/builtins-x64.cc',
+ 'x64/codegen-x64.cc', 'x64/cpu-x64.cc', 'x64/disasm-x64.cc',
+ 'x64/debug-x64.cc', 'x64/frames-x64.cc', 'x64/ic-x64.cc',
+ 'x64/jump-target-x64.cc', 'x64/macro-assembler-x64.cc',
+ # 'x64/regexp-macro-assembler-x64.cc',
+ 'x64/stub-cache-x64.cc'
+ ],
+ 'simulator:arm': ['arm/simulator-arm.cc'],
'os:freebsd': ['platform-freebsd.cc', 'platform-posix.cc'],
'os:linux': ['platform-linux.cc', 'platform-posix.cc'],
'os:android': ['platform-linux.cc', 'platform-posix.cc'],
@@ -121,6 +134,7 @@ debug-delay.js
mirror-delay.js
date-delay.js
regexp-delay.js
+json-delay.js
'''.split()
diff --git a/deps/v8/src/accessors.cc b/deps/v8/src/accessors.cc
index d779eb26a..4cd93be87 100644
--- a/deps/v8/src/accessors.cc
+++ b/deps/v8/src/accessors.cc
@@ -252,6 +252,24 @@ const AccessorDescriptor Accessors::ScriptColumnOffset = {
//
+// Accessors::ScriptData
+//
+
+
+Object* Accessors::ScriptGetData(Object* object, void*) {
+ Object* script = JSValue::cast(object)->value();
+ return Script::cast(script)->data();
+}
+
+
+const AccessorDescriptor Accessors::ScriptData = {
+ ScriptGetData,
+ IllegalSetter,
+ 0
+};
+
+
+//
// Accessors::ScriptType
//
@@ -290,6 +308,25 @@ const AccessorDescriptor Accessors::ScriptLineEnds = {
//
+// Accessors::ScriptGetContextData
+//
+
+
+Object* Accessors::ScriptGetContextData(Object* object, void*) {
+ HandleScope scope;
+ Handle<Script> script(Script::cast(JSValue::cast(object)->value()));
+ return script->context_data();
+}
+
+
+const AccessorDescriptor Accessors::ScriptContextData = {
+ ScriptGetContextData,
+ IllegalSetter,
+ 0
+};
+
+
+//
// Accessors::FunctionPrototype
//
diff --git a/deps/v8/src/accessors.h b/deps/v8/src/accessors.h
index 938b0142a..1dd8fdd2f 100644
--- a/deps/v8/src/accessors.h
+++ b/deps/v8/src/accessors.h
@@ -45,8 +45,10 @@ namespace v8 { namespace internal {
V(ScriptId) \
V(ScriptLineOffset) \
V(ScriptColumnOffset) \
+ V(ScriptData) \
V(ScriptType) \
V(ScriptLineEnds) \
+ V(ScriptContextData) \
V(ObjectPrototype)
// Accessors contains all predefined proxy accessors.
@@ -84,8 +86,10 @@ class Accessors : public AllStatic {
static Object* ScriptGetSource(Object* object, void*);
static Object* ScriptGetLineOffset(Object* object, void*);
static Object* ScriptGetColumnOffset(Object* object, void*);
+ static Object* ScriptGetData(Object* object, void*);
static Object* ScriptGetType(Object* object, void*);
static Object* ScriptGetLineEnds(Object* object, void*);
+ static Object* ScriptGetContextData(Object* object, void*);
static Object* ObjectGetPrototype(Object* receiver, void*);
static Object* ObjectSetPrototype(JSObject* receiver, Object* value, void*);
diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc
index a190b9cfb..c250412e4 100644
--- a/deps/v8/src/api.cc
+++ b/deps/v8/src/api.cc
@@ -37,6 +37,7 @@
#include "serialize.h"
#include "snapshot.h"
#include "v8threads.h"
+#include "version.h"
#define LOG_API(expr) LOG(ApiEntryCall(expr))
@@ -444,6 +445,40 @@ void Context::Exit() {
}
+void Context::SetData(v8::Handle<Value> data) {
+ if (IsDeadCheck("v8::Context::SetData()")) return;
+ ENTER_V8;
+ {
+ HandleScope scope;
+ i::Handle<i::Context> env = Utils::OpenHandle(this);
+ i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
+ ASSERT(env->IsGlobalContext());
+ if (env->IsGlobalContext()) {
+ env->set_data(*raw_data);
+ }
+ }
+}
+
+
+v8::Local<v8::Value> Context::GetData() {
+ if (IsDeadCheck("v8::Context::GetData()")) return v8::Local<Value>();
+ ENTER_V8;
+ i::Object* raw_result = NULL;
+ {
+ HandleScope scope;
+ i::Handle<i::Context> env = Utils::OpenHandle(this);
+ ASSERT(env->IsGlobalContext());
+ if (env->IsGlobalContext()) {
+ raw_result = env->data();
+ } else {
+ return Local<Value>();
+ }
+ }
+ i::Handle<i::Object> result(raw_result);
+ return Utils::ToLocal(result);
+}
+
+
void** v8::HandleScope::RawClose(void** value) {
if (!ApiCheck(!is_closed_,
"v8::HandleScope::Close()",
@@ -1108,6 +1143,19 @@ Local<Value> Script::Id() {
}
+void Script::SetData(v8::Handle<Value> data) {
+ ON_BAILOUT("v8::Script::SetData()", return);
+ LOG_API("Script::SetData");
+ {
+ HandleScope scope;
+ i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
+ i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
+ i::Handle<i::Script> script(i::Script::cast(fun->shared()->script()));
+ script->set_data(*raw_data);
+ }
+}
+
+
// --- E x c e p t i o n s ---
@@ -1199,6 +1247,22 @@ v8::Handle<Value> Message::GetScriptResourceName() const {
}
+v8::Handle<Value> Message::GetScriptData() const {
+ if (IsDeadCheck("v8::Message::GetScriptResourceData()")) {
+ return Local<Value>();
+ }
+ ENTER_V8;
+ HandleScope scope;
+ i::Handle<i::JSObject> obj =
+ i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
+ // Return this.script.data.
+ i::Handle<i::JSValue> script =
+ i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
+ i::Handle<i::Object> data(i::Script::cast(script->value())->data());
+ return scope.Close(Utils::ToLocal(data));
+}
+
+
static i::Handle<i::Object> CallV8HeapFunction(const char* name,
i::Handle<i::Object> recv,
int argc,
@@ -1806,6 +1870,26 @@ bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
}
+bool v8::Object::ForceSet(v8::Handle<Value> key,
+ v8::Handle<Value> value,
+ v8::PropertyAttribute attribs) {
+ ON_BAILOUT("v8::Object::ForceSet()", return false);
+ ENTER_V8;
+ i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+ i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
+ i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
+ EXCEPTION_PREAMBLE();
+ i::Handle<i::Object> obj = i::ForceSetProperty(
+ self,
+ key_obj,
+ value_obj,
+ static_cast<PropertyAttributes>(attribs));
+ has_pending_exception = obj.is_null();
+ EXCEPTION_BAILOUT_CHECK(false);
+ return true;
+}
+
+
Local<Value> v8::Object::Get(v8::Handle<Value> key) {
ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
ENTER_V8;
@@ -2023,7 +2107,12 @@ int v8::Object::GetIdentityHash() {
if (hash->IsSmi()) {
hash_value = i::Smi::cast(*hash)->value();
} else {
- hash_value = random() & i::Smi::kMaxValue; // Limit range to fit a smi.
+ int attempts = 0;
+ do {
+ hash_value = random() & i::Smi::kMaxValue; // Limit range to fit a smi.
+ attempts++;
+ } while (hash_value == 0 && attempts < 30);
+ hash_value = hash_value != 0 ? hash_value : 1; // never return 0
i::SetProperty(hidden_props,
hash_symbol,
i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
@@ -2266,9 +2355,12 @@ v8::String::ExternalStringResource*
v8::String::GetExternalStringResource() const {
EnsureInitialized("v8::String::GetExternalStringResource()");
i::Handle<i::String> str = Utils::OpenHandle(this);
- ASSERT(str->IsExternalTwoByteString());
- void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
- return reinterpret_cast<ExternalStringResource*>(resource);
+ if (i::StringShape(*str).IsExternalTwoByte()) {
+ void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
+ return reinterpret_cast<ExternalStringResource*>(resource);
+ } else {
+ return NULL;
+ }
}
@@ -2276,9 +2368,12 @@ v8::String::ExternalAsciiStringResource*
v8::String::GetExternalAsciiStringResource() const {
EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
i::Handle<i::String> str = Utils::OpenHandle(this);
- ASSERT(str->IsExternalAsciiString());
- void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
- return reinterpret_cast<ExternalAsciiStringResource*>(resource);
+ if (i::StringShape(*str).IsExternalAscii()) {
+ void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
+ return reinterpret_cast<ExternalAsciiStringResource*>(resource);
+ } else {
+ return NULL;
+ }
}
@@ -2373,7 +2468,9 @@ bool v8::V8::Dispose() {
const char* v8::V8::GetVersion() {
- return "1.1.10.4";
+ static v8::internal::EmbeddedVector<char, 128> buffer;
+ v8::internal::Version::GetString(buffer);
+ return buffer.start();
}
@@ -2589,10 +2686,13 @@ Local<Value> v8::External::Wrap(void* data) {
ENTER_V8;
if ((reinterpret_cast<intptr_t>(data) & kAlignedPointerMask) == 0) {
uintptr_t data_ptr = reinterpret_cast<uintptr_t>(data);
- int data_value = static_cast<int>(data_ptr >> kAlignedPointerShift);
+ intptr_t data_value =
+ static_cast<intptr_t>(data_ptr >> kAlignedPointerShift);
STATIC_ASSERT(sizeof(data_ptr) == sizeof(data_value));
- i::Handle<i::Object> obj(i::Smi::FromInt(data_value));
- return Utils::ToLocal(obj);
+ if (i::Smi::IsIntptrValid(data_value)) {
+ i::Handle<i::Object> obj(i::Smi::FromIntptr(data_value));
+ return Utils::ToLocal(obj);
+ }
}
return ExternalNewImpl(data);
}
@@ -2603,7 +2703,8 @@ void* v8::External::Unwrap(v8::Handle<v8::Value> value) {
i::Handle<i::Object> obj = Utils::OpenHandle(*value);
if (obj->IsSmi()) {
// The external value was an aligned pointer.
- uintptr_t result = i::Smi::cast(*obj)->value() << kAlignedPointerShift;
+ uintptr_t result = static_cast<uintptr_t>(
+ i::Smi::cast(*obj)->value()) << kAlignedPointerShift;
return reinterpret_cast<void*>(result);
}
return ExternalValueImpl(obj);
@@ -3021,6 +3122,11 @@ void V8::ResumeProfiler() {
#endif
}
+int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+ return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
+#endif
+}
String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
@@ -3180,8 +3286,8 @@ Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
// --- D e b u g S u p p o r t ---
-
-bool Debug::SetDebugEventListener(DebugEventCallback that, Handle<Value> data) {
+#ifdef ENABLE_DEBUGGER_SUPPORT
+bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
EnsureInitialized("v8::Debug::SetDebugEventListener()");
ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
ENTER_V8;
@@ -3211,31 +3317,54 @@ void Debug::DebugBreak() {
}
-void Debug::SetMessageHandler(v8::DebugMessageHandler handler, void* data,
+static v8::Debug::MessageHandler message_handler = NULL;
+
+static void MessageHandlerWrapper(const v8::Debug::Message& message) {
+ if (message_handler) {
+ v8::String::Value json(message.GetJSON());
+ message_handler(*json, json.length(), message.GetClientData());
+ }
+}
+
+
+void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
bool message_handler_thread) {
EnsureInitialized("v8::Debug::SetMessageHandler");
ENTER_V8;
- i::Debugger::SetMessageHandler(handler, data, message_handler_thread);
-}
+ // Message handler thread not supported any more. Parameter temporally left in
+ // the API for client compatability reasons.
+ CHECK(!message_handler_thread);
-
-void Debug::SendCommand(const uint16_t* command, int length) {
- if (!i::V8::HasBeenSetup()) return;
- i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length));
+ // TODO(sgjesse) support the old message handler API through a simple wrapper.
+ message_handler = handler;
+ if (message_handler != NULL) {
+ i::Debugger::SetMessageHandler(MessageHandlerWrapper);
+ } else {
+ i::Debugger::SetMessageHandler(NULL);
+ }
}
-void Debug::SetHostDispatchHandler(v8::DebugHostDispatchHandler handler,
- void* data) {
- EnsureInitialized("v8::Debug::SetHostDispatchHandler");
+void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
+ EnsureInitialized("v8::Debug::SetMessageHandler");
ENTER_V8;
- i::Debugger::SetHostDispatchHandler(handler, data);
+ i::Debugger::SetMessageHandler(handler);
}
-void Debug::SendHostDispatch(void* dispatch) {
+void Debug::SendCommand(const uint16_t* command, int length,
+ ClientData* client_data) {
if (!i::V8::HasBeenSetup()) return;
- i::Debugger::ProcessHostDispatch(dispatch);
+ i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
+ client_data);
+}
+
+
+void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
+ int period) {
+ EnsureInitialized("v8::Debug::SetHostDispatchHandler");
+ ENTER_V8;
+ i::Debugger::SetHostDispatchHandler(handler, period);
}
@@ -3263,7 +3392,7 @@ Handle<Value> Debug::Call(v8::Handle<v8::Function> fun,
bool Debug::EnableAgent(const char* name, int port) {
return i::Debugger::StartAgent(name, port);
}
-
+#endif // ENABLE_DEBUGGER_SUPPORT
namespace internal {
diff --git a/deps/v8/src/assembler-arm-inl.h b/deps/v8/src/arm/assembler-arm-inl.h
index 315605e78..fe64761e3 100644
--- a/deps/v8/src/assembler-arm-inl.h
+++ b/deps/v8/src/arm/assembler-arm-inl.h
@@ -34,10 +34,10 @@
// significantly by Google Inc.
// Copyright 2006-2008 the V8 project authors. All rights reserved.
-#ifndef V8_ASSEMBLER_ARM_INL_H_
-#define V8_ASSEMBLER_ARM_INL_H_
+#ifndef V8_ARM_ASSEMBLER_ARM_INL_H_
+#define V8_ARM_ASSEMBLER_ARM_INL_H_
-#include "assembler-arm.h"
+#include "arm/assembler-arm.h"
#include "cpu.h"
@@ -246,4 +246,4 @@ void Assembler::set_target_address_at(Address pc, Address target) {
} } // namespace v8::internal
-#endif // V8_ASSEMBLER_ARM_INL_H_
+#endif // V8_ARM_ASSEMBLER_ARM_INL_H_
diff --git a/deps/v8/src/assembler-arm.cc b/deps/v8/src/arm/assembler-arm.cc
index ba7638ec1..191c865a8 100644
--- a/deps/v8/src/assembler-arm.cc
+++ b/deps/v8/src/arm/assembler-arm.cc
@@ -36,7 +36,7 @@
#include "v8.h"
-#include "assembler-arm-inl.h"
+#include "arm/assembler-arm-inl.h"
#include "serialize.h"
namespace v8 { namespace internal {
diff --git a/deps/v8/src/assembler-arm.h b/deps/v8/src/arm/assembler-arm.h
index f965ebd8a..d7535e0da 100644
--- a/deps/v8/src/assembler-arm.h
+++ b/deps/v8/src/arm/assembler-arm.h
@@ -37,8 +37,8 @@
// A light-weight ARM Assembler
// Generates user mode instructions for the ARM architecture up to version 5
-#ifndef V8_ASSEMBLER_ARM_H_
-#define V8_ASSEMBLER_ARM_H_
+#ifndef V8_ARM_ASSEMBLER_ARM_H_
+#define V8_ARM_ASSEMBLER_ARM_H_
#include "assembler.h"
@@ -164,23 +164,23 @@ enum Coprocessor {
// Condition field in instructions
enum Condition {
- eq = 0 << 28,
- ne = 1 << 28,
- cs = 2 << 28,
- hs = 2 << 28,
- cc = 3 << 28,
- lo = 3 << 28,
- mi = 4 << 28,
- pl = 5 << 28,
- vs = 6 << 28,
- vc = 7 << 28,
- hi = 8 << 28,
- ls = 9 << 28,
- ge = 10 << 28,
- lt = 11 << 28,
- gt = 12 << 28,
- le = 13 << 28,
- al = 14 << 28
+ eq = 0 << 28, // Z set equal.
+ ne = 1 << 28, // Z clear not equal.
+ cs = 2 << 28, // C set unsigned higher or same.
+ hs = 2 << 28, // C set unsigned higher or same.
+ cc = 3 << 28, // C clear unsigned lower.
+ lo = 3 << 28, // C clear unsigned lower.
+ mi = 4 << 28, // N set negative.
+ pl = 5 << 28, // N clear positive or zero.
+ vs = 6 << 28, // V set overflow.
+ vc = 7 << 28, // V clear no overflow.
+ hi = 8 << 28, // C set, Z clear unsigned higher.
+ ls = 9 << 28, // C clear or Z set unsigned lower or same.
+ ge = 10 << 28, // N == V greater or equal.
+ lt = 11 << 28, // N != V less than.
+ gt = 12 << 28, // Z clear, N == V greater than.
+ le = 13 << 28, // Z set or N != V less then or equal
+ al = 14 << 28 // always.
};
@@ -786,4 +786,4 @@ class Assembler : public Malloced {
} } // namespace v8::internal
-#endif // V8_ASSEMBLER_ARM_H_
+#endif // V8_ARM_ASSEMBLER_ARM_H_
diff --git a/deps/v8/src/builtins-arm.cc b/deps/v8/src/arm/builtins-arm.cc
index 2e6f25518..9c7a42ab1 100644
--- a/deps/v8/src/builtins-arm.cc
+++ b/deps/v8/src/arm/builtins-arm.cc
@@ -34,7 +34,7 @@
namespace v8 { namespace internal {
-#define __ masm->
+#define __ ACCESS_MASM(masm)
void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
@@ -58,6 +58,16 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
// -- sp[...]: constructor arguments
// -----------------------------------
+ Label non_function_call;
+ // Check that the function is not a smi.
+ __ tst(r1, Operand(kSmiTagMask));
+ __ b(eq, &non_function_call);
+ // Check that the function is a JSFunction.
+ __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+ __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+ __ cmp(r2, Operand(JS_FUNCTION_TYPE));
+ __ b(ne, &non_function_call);
+
// Enter a construct frame.
__ EnterConstructFrame();
@@ -169,7 +179,17 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
__ LeaveConstructFrame();
__ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
__ add(sp, sp, Operand(kPointerSize));
- __ mov(pc, Operand(lr));
+ __ Jump(lr);
+
+ // r0: number of arguments
+ // r1: called object
+ __ bind(&non_function_call);
+
+ // Set expected number of arguments to zero (not changing r0).
+ __ mov(r2, Operand(0));
+ __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
+ __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
+ RelocInfo::CODE_TARGET);
}
@@ -218,8 +238,9 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
__ mov(r5, Operand(r4));
__ mov(r6, Operand(r4));
__ mov(r7, Operand(r4));
- if (kR9Available == 1)
+ if (kR9Available == 1) {
__ mov(r9, Operand(r4));
+ }
// Invoke the code and pass argc as r0.
__ mov(r0, Operand(r3));
@@ -234,7 +255,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
// Exit the JS frame and remove the parameters (except function), and return.
// Respect ABI stack constraint.
__ LeaveInternalFrame();
- __ mov(pc, lr);
+ __ Jump(lr);
// r0: result
}
@@ -416,15 +437,35 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
__ push(r0);
__ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_JS);
- // Eagerly check for stack-overflow before starting to push the arguments.
- // r0: number of arguments
- Label okay;
+ Label no_preemption, retry_preemption;
+ __ bind(&retry_preemption);
ExternalReference stack_guard_limit_address =
ExternalReference::address_of_stack_guard_limit();
__ mov(r2, Operand(stack_guard_limit_address));
__ ldr(r2, MemOperand(r2));
+ __ cmp(sp, r2);
+ __ b(hi, &no_preemption);
+
+ // We have encountered a preemption or stack overflow already before we push
+ // the array contents. Save r0 which is the Smi-tagged length of the array.
+ __ push(r0);
+
+ // Runtime routines expect at least one argument, so give it a Smi.
+ __ mov(r0, Operand(Smi::FromInt(0)));
+ __ push(r0);
+ __ CallRuntime(Runtime::kStackGuard, 1);
+
+ // Since we returned, it wasn't a stack overflow. Restore r0 and try again.
+ __ pop(r0);
+ __ b(&retry_preemption);
+
+ __ bind(&no_preemption);
+
+ // Eagerly check for stack-overflow before starting to push the arguments.
+ // r0: number of arguments.
+ // r2: stack limit.
+ Label okay;
__ sub(r2, sp, r2);
- __ sub(r2, r2, Operand(3 * kPointerSize)); // limit, index, receiver
__ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
__ b(hi, &okay);
@@ -523,7 +564,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
// Tear down the internal frame and remove function, receiver and args.
__ LeaveInternalFrame();
__ add(sp, sp, Operand(3 * kPointerSize));
- __ mov(pc, lr);
+ __ Jump(lr);
}
@@ -642,14 +683,14 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
// Exit frame and return.
LeaveArgumentsAdaptorFrame(masm);
- __ mov(pc, lr);
+ __ Jump(lr);
// -------------------------------------------
// Dont adapt arguments.
// -------------------------------------------
__ bind(&dont_adapt_arguments);
- __ mov(pc, r3);
+ __ Jump(r3);
}
diff --git a/deps/v8/src/codegen-arm.cc b/deps/v8/src/arm/codegen-arm.cc
index 6fdabc3c5..1930a7c2f 100644
--- a/deps/v8/src/codegen-arm.cc
+++ b/deps/v8/src/arm/codegen-arm.cc
@@ -38,7 +38,8 @@
namespace v8 { namespace internal {
-#define __ masm_->
+#define __ ACCESS_MASM(masm_)
+
// -------------------------------------------------------------------------
// CodeGenState implementation.
@@ -146,13 +147,13 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
frame_->EmitPush(r0);
frame_->CallRuntime(Runtime::kNewContext, 1); // r0 holds the result
- if (kDebug) {
- JumpTarget verified_true(this);
- __ cmp(r0, Operand(cp));
- verified_true.Branch(eq);
- __ stop("NewContext: r0 is expected to be the same as cp");
- verified_true.Bind();
- }
+#ifdef DEBUG
+ JumpTarget verified_true(this);
+ __ cmp(r0, Operand(cp));
+ verified_true.Branch(eq);
+ __ stop("NewContext: r0 is expected to be the same as cp");
+ verified_true.Bind();
+#endif
// Update context local.
__ str(cp, frame_->Context());
}
@@ -276,7 +277,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
frame_->Exit();
__ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize));
- __ mov(pc, lr);
+ __ Jump(lr);
}
// Code generation state must be reset.
@@ -653,37 +654,27 @@ void CodeGenerator::ToBoolean(JumpTarget* true_target,
}
-class GetPropertyStub : public CodeStub {
- public:
- GetPropertyStub() { }
-
- private:
- Major MajorKey() { return GetProperty; }
- int MinorKey() { return 0; }
- void Generate(MacroAssembler* masm);
-};
-
-
-class SetPropertyStub : public CodeStub {
- public:
- SetPropertyStub() { }
-
- private:
- Major MajorKey() { return SetProperty; }
- int MinorKey() { return 0; }
- void Generate(MacroAssembler* masm);
-};
-
-
class GenericBinaryOpStub : public CodeStub {
public:
- explicit GenericBinaryOpStub(Token::Value op) : op_(op) { }
+ GenericBinaryOpStub(Token::Value op,
+ OverwriteMode mode)
+ : op_(op), mode_(mode) { }
private:
Token::Value op_;
+ OverwriteMode mode_;
+
+ // Minor key encoding in 16 bits.
+ class ModeBits: public BitField<OverwriteMode, 0, 2> {};
+ class OpBits: public BitField<Token::Value, 2, 14> {};
Major MajorKey() { return GenericBinaryOp; }
- int MinorKey() { return static_cast<int>(op_); }
+ int MinorKey() {
+ // Encode the parameters in a unique 16 bit value.
+ return OpBits::encode(op_)
+ | ModeBits::encode(mode_);
+ }
+
void Generate(MacroAssembler* masm);
const char* GetName() {
@@ -708,7 +699,8 @@ class GenericBinaryOpStub : public CodeStub {
};
-void CodeGenerator::GenericBinaryOperation(Token::Value op) {
+void CodeGenerator::GenericBinaryOperation(Token::Value op,
+ OverwriteMode overwrite_mode) {
VirtualFrame::SpilledScope spilled_scope(this);
// sp[0] : y
// sp[1] : x
@@ -727,7 +719,7 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op) {
case Token::SAR: {
frame_->EmitPop(r0); // r0 : y
frame_->EmitPop(r1); // r1 : x
- GenericBinaryOpStub stub(op);
+ GenericBinaryOpStub stub(op, overwrite_mode);
frame_->CallStub(&stub, 0);
break;
}
@@ -767,11 +759,13 @@ class DeferredInlineSmiOperation: public DeferredCode {
DeferredInlineSmiOperation(CodeGenerator* generator,
Token::Value op,
int value,
- bool reversed)
+ bool reversed,
+ OverwriteMode overwrite_mode)
: DeferredCode(generator),
op_(op),
value_(value),
- reversed_(reversed) {
+ reversed_(reversed),
+ overwrite_mode_(overwrite_mode) {
set_comment("[ DeferredInlinedSmiOperation");
}
@@ -781,6 +775,7 @@ class DeferredInlineSmiOperation: public DeferredCode {
Token::Value op_;
int value_;
bool reversed_;
+ OverwriteMode overwrite_mode_;
};
@@ -844,7 +839,7 @@ void DeferredInlineSmiOperation::Generate() {
break;
}
- GenericBinaryOpStub igostub(op_);
+ GenericBinaryOpStub igostub(op_, overwrite_mode_);
Result arg0 = generator()->allocator()->Allocate(r1);
ASSERT(arg0.is_valid());
Result arg1 = generator()->allocator()->Allocate(r0);
@@ -856,7 +851,8 @@ void DeferredInlineSmiOperation::Generate() {
void CodeGenerator::SmiOperation(Token::Value op,
Handle<Object> value,
- bool reversed) {
+ bool reversed,
+ OverwriteMode mode) {
VirtualFrame::SpilledScope spilled_scope(this);
// NOTE: This is an attempt to inline (a bit) more of the code for
// some possible smi operations (like + and -) when (at least) one
@@ -875,7 +871,7 @@ void CodeGenerator::SmiOperation(Token::Value op,
switch (op) {
case Token::ADD: {
DeferredCode* deferred =
- new DeferredInlineSmiOperation(this, op, int_value, reversed);
+ new DeferredInlineSmiOperation(this, op, int_value, reversed, mode);
__ add(r0, r0, Operand(value), SetCC);
deferred->enter()->Branch(vs);
@@ -887,7 +883,7 @@ void CodeGenerator::SmiOperation(Token::Value op,
case Token::SUB: {
DeferredCode* deferred =
- new DeferredInlineSmiOperation(this, op, int_value, reversed);
+ new DeferredInlineSmiOperation(this, op, int_value, reversed, mode);
if (!reversed) {
__ sub(r0, r0, Operand(value), SetCC);
@@ -905,7 +901,7 @@ void CodeGenerator::SmiOperation(Token::Value op,
case Token::BIT_XOR:
case Token::BIT_AND: {
DeferredCode* deferred =
- new DeferredInlineSmiOperation(this, op, int_value, reversed);
+ new DeferredInlineSmiOperation(this, op, int_value, reversed, mode);
__ tst(r0, Operand(kSmiTagMask));
deferred->enter()->Branch(ne);
switch (op) {
@@ -925,12 +921,12 @@ void CodeGenerator::SmiOperation(Token::Value op,
__ mov(ip, Operand(value));
frame_->EmitPush(ip);
frame_->EmitPush(r0);
- GenericBinaryOperation(op);
+ GenericBinaryOperation(op, mode);
} else {
int shift_value = int_value & 0x1f; // least significant 5 bits
DeferredCode* deferred =
- new DeferredInlineSmiOperation(this, op, shift_value, false);
+ new DeferredInlineSmiOperation(this, op, shift_value, false, mode);
__ tst(r0, Operand(kSmiTagMask));
deferred->enter()->Branch(ne);
__ mov(r2, Operand(r0, ASR, kSmiTagSize)); // remove tags
@@ -982,7 +978,7 @@ void CodeGenerator::SmiOperation(Token::Value op,
frame_->EmitPush(ip);
frame_->EmitPush(r0);
}
- GenericBinaryOperation(op);
+ GenericBinaryOperation(op, mode);
break;
}
@@ -1427,13 +1423,13 @@ void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
} else {
frame_->CallRuntime(Runtime::kPushContext, 1);
}
- if (kDebug) {
- JumpTarget verified_true(this);
- __ cmp(r0, Operand(cp));
- verified_true.Branch(eq);
- __ stop("PushContext: r0 is expected to be the same as cp");
- verified_true.Bind();
- }
+#ifdef DEBUG
+ JumpTarget verified_true(this);
+ __ cmp(r0, Operand(cp));
+ verified_true.Branch(eq);
+ __ stop("PushContext: r0 is expected to be the same as cp");
+ verified_true.Bind();
+#endif
// Update context local.
__ str(cp, frame_->Context());
ASSERT(frame_->height() == original_height);
@@ -1487,8 +1483,8 @@ void CodeGenerator::GenerateFastCaseSwitchJumpTable(
// Test for a Smi value in a HeapNumber.
__ tst(r0, Operand(kSmiTagMask));
is_smi.Branch(eq);
- __ ldr(r1, MemOperand(r0, HeapObject::kMapOffset - kHeapObjectTag));
- __ ldrb(r1, MemOperand(r1, Map::kInstanceTypeOffset - kHeapObjectTag));
+ __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
+ __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
__ cmp(r1, Operand(HEAP_NUMBER_TYPE));
default_target->Branch(ne);
frame_->EmitPush(r0);
@@ -2339,7 +2335,9 @@ void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ DebuggerStatament");
CodeForStatementPosition(node);
+#ifdef ENABLE_DEBUGGER_SUPPORT
frame_->CallRuntime(Runtime::kDebugBreak, 0);
+#endif
// Ignore the return value.
ASSERT(frame_->height() == original_height);
}
@@ -2523,7 +2521,9 @@ void CodeGenerator::LoadFromGlobalSlotCheckExtensions(Slot* slot,
if (s->is_eval_scope()) {
Label next, fast;
- if (!context.is(tmp)) __ mov(tmp, Operand(context));
+ if (!context.is(tmp)) {
+ __ mov(tmp, Operand(context));
+ }
__ bind(&next);
// Terminate at global context.
__ ldr(tmp2, FieldMemOperand(tmp, HeapObject::kMapOffset));
@@ -2934,15 +2934,24 @@ void CodeGenerator::VisitAssignment(Assignment* node) {
LoadAndSpill(node->value());
} else {
+ // +=, *= and similar binary assignments.
+ // Get the old value of the lhs.
target.GetValueAndSpill(NOT_INSIDE_TYPEOF);
Literal* literal = node->value()->AsLiteral();
+ bool overwrite =
+ (node->value()->AsBinaryOperation() != NULL &&
+ node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
if (literal != NULL && literal->handle()->IsSmi()) {
- SmiOperation(node->binary_op(), literal->handle(), false);
+ SmiOperation(node->binary_op(),
+ literal->handle(),
+ false,
+ overwrite ? OVERWRITE_RIGHT : NO_OVERWRITE);
frame_->EmitPush(r0);
} else {
LoadAndSpill(node->value());
- GenericBinaryOperation(node->binary_op());
+ GenericBinaryOperation(node->binary_op(),
+ overwrite ? OVERWRITE_RIGHT : NO_OVERWRITE);
frame_->EmitPush(r0);
}
}
@@ -3822,19 +3831,39 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
// is a literal small integer.
Literal* lliteral = node->left()->AsLiteral();
Literal* rliteral = node->right()->AsLiteral();
+ // NOTE: The code below assumes that the slow cases (calls to runtime)
+ // never return a constant/immutable object.
+ bool overwrite_left =
+ (node->left()->AsBinaryOperation() != NULL &&
+ node->left()->AsBinaryOperation()->ResultOverwriteAllowed());
+ bool overwrite_right =
+ (node->right()->AsBinaryOperation() != NULL &&
+ node->right()->AsBinaryOperation()->ResultOverwriteAllowed());
if (rliteral != NULL && rliteral->handle()->IsSmi()) {
LoadAndSpill(node->left());
- SmiOperation(node->op(), rliteral->handle(), false);
+ SmiOperation(node->op(),
+ rliteral->handle(),
+ false,
+ overwrite_right ? OVERWRITE_RIGHT : NO_OVERWRITE);
} else if (lliteral != NULL && lliteral->handle()->IsSmi()) {
LoadAndSpill(node->right());
- SmiOperation(node->op(), lliteral->handle(), true);
+ SmiOperation(node->op(),
+ lliteral->handle(),
+ true,
+ overwrite_left ? OVERWRITE_LEFT : NO_OVERWRITE);
} else {
+ OverwriteMode overwrite_mode = NO_OVERWRITE;
+ if (overwrite_left) {
+ overwrite_mode = OVERWRITE_LEFT;
+ } else if (overwrite_right) {
+ overwrite_mode = OVERWRITE_RIGHT;
+ }
LoadAndSpill(node->left());
LoadAndSpill(node->right());
- GenericBinaryOperation(node->op());
+ GenericBinaryOperation(node->op(), overwrite_mode);
}
frame_->EmitPush(r0);
}
@@ -4067,7 +4096,8 @@ bool CodeGenerator::HasValidEntryRegisters() { return true; }
#undef __
-#define __ masm->
+#define __ ACCESS_MASM(masm)
+
Handle<String> Reference::GetName() {
ASSERT(type_ == NAMED);
@@ -4305,167 +4335,80 @@ void Reference::SetValue(InitState init_state) {
}
-void GetPropertyStub::Generate(MacroAssembler* masm) {
- // sp[0]: key
- // sp[1]: receiver
- Label slow, fast;
- // Get the key and receiver object from the stack.
- __ ldm(ia, sp, r0.bit() | r1.bit());
- // Check that the key is a smi.
- __ tst(r0, Operand(kSmiTagMask));
- __ b(ne, &slow);
- __ mov(r0, Operand(r0, ASR, kSmiTagSize));
- // Check that the object isn't a smi.
- __ tst(r1, Operand(kSmiTagMask));
- __ b(eq, &slow);
-
- // Check that the object is some kind of JS object EXCEPT JS Value type.
- // In the case that the object is a value-wrapper object,
- // we enter the runtime system to make sure that indexing into string
- // objects work as intended.
- ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
- __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
- __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
- __ cmp(r2, Operand(JS_OBJECT_TYPE));
- __ b(lt, &slow);
-
- // Get the elements array of the object.
- __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset));
- // Check that the object is in fast mode (not dictionary).
- __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
- __ cmp(r3, Operand(Factory::hash_table_map()));
- __ b(eq, &slow);
- // Check that the key (index) is within bounds.
- __ ldr(r3, FieldMemOperand(r1, Array::kLengthOffset));
- __ cmp(r0, Operand(r3));
- __ b(lo, &fast);
-
- // Slow case: Push extra copies of the arguments (2).
- __ bind(&slow);
- __ ldm(ia, sp, r0.bit() | r1.bit());
- __ stm(db_w, sp, r0.bit() | r1.bit());
- // Do tail-call to runtime routine.
- __ TailCallRuntime(ExternalReference(Runtime::kGetProperty), 2);
-
- // Fast case: Do the load.
- __ bind(&fast);
- __ add(r3, r1, Operand(Array::kHeaderSize - kHeapObjectTag));
- __ ldr(r0, MemOperand(r3, r0, LSL, kPointerSizeLog2));
- __ cmp(r0, Operand(Factory::the_hole_value()));
- // In case the loaded value is the_hole we have to consult GetProperty
- // to ensure the prototype chain is searched.
- __ b(eq, &slow);
-
- __ StubReturn(1);
-}
-
-
-void SetPropertyStub::Generate(MacroAssembler* masm) {
- // r0 : value
- // sp[0] : key
- // sp[1] : receiver
-
- Label slow, fast, array, extra, exit;
- // Get the key and the object from the stack.
- __ ldm(ia, sp, r1.bit() | r3.bit()); // r1 = key, r3 = receiver
- // Check that the key is a smi.
- __ tst(r1, Operand(kSmiTagMask));
- __ b(ne, &slow);
- // Check that the object isn't a smi.
- __ tst(r3, Operand(kSmiTagMask));
- __ b(eq, &slow);
- // Get the type of the object from its map.
- __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
- __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
- // Check if the object is a JS array or not.
- __ cmp(r2, Operand(JS_ARRAY_TYPE));
- __ b(eq, &array);
- // Check that the object is some kind of JS object.
- __ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE));
- __ b(lt, &slow);
-
-
- // Object case: Check key against length in the elements array.
- __ ldr(r3, FieldMemOperand(r3, JSObject::kElementsOffset));
- // Check that the object is in fast mode (not dictionary).
- __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
- __ cmp(r2, Operand(Factory::hash_table_map()));
- __ b(eq, &slow);
- // Untag the key (for checking against untagged length in the fixed array).
- __ mov(r1, Operand(r1, ASR, kSmiTagSize));
- // Compute address to store into and check array bounds.
- __ add(r2, r3, Operand(Array::kHeaderSize - kHeapObjectTag));
- __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2));
- __ ldr(ip, FieldMemOperand(r3, Array::kLengthOffset));
- __ cmp(r1, Operand(ip));
- __ b(lo, &fast);
-
-
- // Slow case: Push extra copies of the arguments (3).
+static void HandleBinaryOpSlowCases(MacroAssembler* masm,
+ Label* not_smi,
+ const Builtins::JavaScript& builtin,
+ Token::Value operation,
+ int swi_number,
+ OverwriteMode mode) {
+ Label slow;
+ if (mode == NO_OVERWRITE) {
+ __ bind(not_smi);
+ }
__ bind(&slow);
- __ ldm(ia, sp, r1.bit() | r3.bit()); // r0 == value, r1 == key, r3 == object
- __ stm(db_w, sp, r0.bit() | r1.bit() | r3.bit());
- // Do tail-call to runtime routine.
- __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3);
-
-
- // Extra capacity case: Check if there is extra capacity to
- // perform the store and update the length. Used for adding one
- // element to the array by writing to array[array.length].
- // r0 == value, r1 == key, r2 == elements, r3 == object
- __ bind(&extra);
- __ b(ne, &slow); // do not leave holes in the array
- __ mov(r1, Operand(r1, ASR, kSmiTagSize)); // untag
- __ ldr(ip, FieldMemOperand(r2, Array::kLengthOffset));
- __ cmp(r1, Operand(ip));
- __ b(hs, &slow);
- __ mov(r1, Operand(r1, LSL, kSmiTagSize)); // restore tag
- __ add(r1, r1, Operand(1 << kSmiTagSize)); // and increment
- __ str(r1, FieldMemOperand(r3, JSArray::kLengthOffset));
- __ mov(r3, Operand(r2));
- // NOTE: Computing the address to store into must take the fact
- // that the key has been incremented into account.
- int displacement = Array::kHeaderSize - kHeapObjectTag -
- ((1 << kSmiTagSize) * 2);
- __ add(r2, r2, Operand(displacement));
- __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));
- __ b(&fast);
-
-
- // Array case: Get the length and the elements array from the JS
- // array. Check that the array is in fast mode; if it is the
- // length is always a smi.
- // r0 == value, r3 == object
- __ bind(&array);
- __ ldr(r2, FieldMemOperand(r3, JSObject::kElementsOffset));
- __ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset));
- __ cmp(r1, Operand(Factory::hash_table_map()));
- __ b(eq, &slow);
+ __ push(r1);
+ __ push(r0);
+ __ mov(r0, Operand(1)); // Set number of arguments.
+ __ InvokeBuiltin(builtin, JUMP_JS); // Tail call.
- // Check the key against the length in the array, compute the
- // address to store into and fall through to fast case.
- __ ldr(r1, MemOperand(sp));
- // r0 == value, r1 == key, r2 == elements, r3 == object.
- __ ldr(ip, FieldMemOperand(r3, JSArray::kLengthOffset));
- __ cmp(r1, Operand(ip));
- __ b(hs, &extra);
- __ mov(r3, Operand(r2));
- __ add(r2, r2, Operand(Array::kHeaderSize - kHeapObjectTag));
- __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));
-
-
- // Fast case: Do the store.
- // r0 == value, r2 == address to store into, r3 == elements
- __ bind(&fast);
- __ str(r0, MemOperand(r2));
- // Skip write barrier if the written value is a smi.
- __ tst(r0, Operand(kSmiTagMask));
- __ b(eq, &exit);
- // Update write barrier for the elements array address.
- __ sub(r1, r2, Operand(r3));
- __ RecordWrite(r3, r1, r2);
- __ bind(&exit);
- __ StubReturn(1);
+ // Could it be a double-double op? If we already have a place to put
+ // the answer then we can do the op and skip the builtin and runtime call.
+ if (mode != NO_OVERWRITE) {
+ __ bind(not_smi);
+ __ tst(r0, Operand(kSmiTagMask));
+ __ b(eq, &slow); // We can't handle a Smi-double combination yet.
+ __ tst(r1, Operand(kSmiTagMask));
+ __ b(eq, &slow); // We can't handle a Smi-double combination yet.
+ // Get map of r0 into r2.
+ __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
+ // Get type of r0 into r3.
+ __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+ __ cmp(r3, Operand(HEAP_NUMBER_TYPE));
+ __ b(ne, &slow);
+ // Get type of r1 into r3.
+ __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
+ // Check they are both the same map (heap number map).
+ __ cmp(r2, r3);
+ __ b(ne, &slow);
+ // Both are doubles.
+ // Calling convention says that second double is in r2 and r3.
+ __ ldr(r2, FieldMemOperand(r0, HeapNumber::kValueOffset));
+ __ ldr(r3, FieldMemOperand(r0, HeapNumber::kValueOffset + kPointerSize));
+ __ push(lr);
+ if (mode == OVERWRITE_LEFT) {
+ __ push(r1);
+ } else {
+ __ push(r0);
+ }
+ // Calling convention says that first double is in r0 and r1.
+ __ ldr(r0, FieldMemOperand(r1, HeapNumber::kValueOffset));
+ __ ldr(r1, FieldMemOperand(r1, HeapNumber::kValueOffset + kPointerSize));
+ // Call C routine that may not cause GC or other trouble.
+ __ mov(r5, Operand(ExternalReference::double_fp_operation(operation)));
+#if !defined(__arm__)
+ // Notify the simulator that we are calling an add routine in C.
+ __ swi(swi_number);
+#else
+ // Actually call the add routine written in C.
+ __ Call(r5);
+#endif
+ // Store answer in the overwritable heap number.
+ __ pop(r4);
+#if !defined(__ARM_EABI__) && defined(__arm__)
+ // Double returned in fp coprocessor register 0 and 1, encoded as register
+ // cr8. Offsets must be divisible by 4 for coprocessor so we need to
+ // substract the tag from r4.
+ __ sub(r5, r4, Operand(kHeapObjectTag));
+ __ stc(p1, cr8, MemOperand(r5, HeapNumber::kValueOffset));
+#else
+ // Double returned in fp coprocessor register 0 and 1.
+ __ str(r0, FieldMemOperand(r4, HeapNumber::kValueOffset));
+ __ str(r1, FieldMemOperand(r4, HeapNumber::kValueOffset + kPointerSize));
+#endif
+ __ mov(r0, Operand(r4));
+ // And we are done.
+ __ pop(pc);
+ }
}
@@ -4474,89 +4417,84 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
// r0 : y
// result : r0
+ // All ops need to know whether we are dealing with two Smis. Set up r2 to
+ // tell us that.
+ __ orr(r2, r1, Operand(r0)); // r2 = x | y;
+
switch (op_) {
case Token::ADD: {
- Label slow, exit;
- // fast path
- __ orr(r2, r1, Operand(r0)); // r2 = x | y;
- __ add(r0, r1, Operand(r0), SetCC); // add y optimistically
- // go slow-path in case of overflow
- __ b(vs, &slow);
- // go slow-path in case of non-smi operands
- ASSERT(kSmiTag == 0); // adjust code below
+ Label not_smi;
+ // Fast path.
+ ASSERT(kSmiTag == 0); // Adjust code below.
__ tst(r2, Operand(kSmiTagMask));
- __ b(eq, &exit);
- // slow path
- __ bind(&slow);
- __ sub(r0, r0, Operand(r1)); // revert optimistic add
- __ push(r1);
- __ push(r0);
- __ mov(r0, Operand(1)); // set number of arguments
- __ InvokeBuiltin(Builtins::ADD, JUMP_JS);
- // done
- __ bind(&exit);
+ __ b(ne, &not_smi);
+ __ add(r0, r1, Operand(r0), SetCC); // Add y optimistically.
+ // Return if no overflow.
+ __ Ret(vc);
+ __ sub(r0, r0, Operand(r1)); // Revert optimistic add.
+
+ HandleBinaryOpSlowCases(masm,
+ &not_smi,
+ Builtins::ADD,
+ Token::ADD,
+ assembler::arm::simulator_fp_add,
+ mode_);
break;
}
case Token::SUB: {
- Label slow, exit;
- // fast path
- __ orr(r2, r1, Operand(r0)); // r2 = x | y;
- __ sub(r3, r1, Operand(r0), SetCC); // subtract y optimistically
- // go slow-path in case of overflow
- __ b(vs, &slow);
- // go slow-path in case of non-smi operands
- ASSERT(kSmiTag == 0); // adjust code below
+ Label not_smi;
+ // Fast path.
+ ASSERT(kSmiTag == 0); // Adjust code below.
__ tst(r2, Operand(kSmiTagMask));
- __ mov(r0, Operand(r3), LeaveCC, eq); // conditionally set r0 to result
- __ b(eq, &exit);
- // slow path
- __ bind(&slow);
- __ push(r1);
- __ push(r0);
- __ mov(r0, Operand(1)); // set number of arguments
- __ InvokeBuiltin(Builtins::SUB, JUMP_JS);
- // done
- __ bind(&exit);
+ __ b(ne, &not_smi);
+ __ sub(r0, r1, Operand(r0), SetCC); // Subtract y optimistically.
+ // Return if no overflow.
+ __ Ret(vc);
+ __ sub(r0, r1, Operand(r0)); // Revert optimistic subtract.
+
+ HandleBinaryOpSlowCases(masm,
+ &not_smi,
+ Builtins::SUB,
+ Token::SUB,
+ assembler::arm::simulator_fp_sub,
+ mode_);
break;
}
case Token::MUL: {
- Label slow, exit;
- // tag check
- __ orr(r2, r1, Operand(r0)); // r2 = x | y;
+ Label not_smi, slow;
ASSERT(kSmiTag == 0); // adjust code below
__ tst(r2, Operand(kSmiTagMask));
- __ b(ne, &slow);
- // remove tag from one operand (but keep sign), so that result is smi
+ __ b(ne, &not_smi);
+ // Remove tag from one operand (but keep sign), so that result is Smi.
__ mov(ip, Operand(r0, ASR, kSmiTagSize));
- // do multiplication
- __ smull(r3, r2, r1, ip); // r3 = lower 32 bits of ip*r1
- // go slow on overflows (overflow bit is not set)
+ // Do multiplication
+ __ smull(r3, r2, r1, ip); // r3 = lower 32 bits of ip*r1.
+ // Go slow on overflows (overflow bit is not set).
__ mov(ip, Operand(r3, ASR, 31));
__ cmp(ip, Operand(r2)); // no overflow if higher 33 bits are identical
__ b(ne, &slow);
- // go slow on zero result to handle -0
+ // Go slow on zero result to handle -0.
__ tst(r3, Operand(r3));
__ mov(r0, Operand(r3), LeaveCC, ne);
- __ b(ne, &exit);
- // slow case
+ __ Ret(ne);
+ // Slow case.
__ bind(&slow);
- __ push(r1);
- __ push(r0);
- __ mov(r0, Operand(1)); // set number of arguments
- __ InvokeBuiltin(Builtins::MUL, JUMP_JS);
- // done
- __ bind(&exit);
+
+ HandleBinaryOpSlowCases(masm,
+ &not_smi,
+ Builtins::MUL,
+ Token::MUL,
+ assembler::arm::simulator_fp_mul,
+ mode_);
break;
}
case Token::BIT_OR:
case Token::BIT_AND:
case Token::BIT_XOR: {
- Label slow, exit;
- // tag check
- __ orr(r2, r1, Operand(r0)); // r2 = x | y;
+ Label slow;
ASSERT(kSmiTag == 0); // adjust code below
__ tst(r2, Operand(kSmiTagMask));
__ b(ne, &slow);
@@ -4566,7 +4504,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
case Token::BIT_XOR: __ eor(r0, r0, Operand(r1)); break;
default: UNREACHABLE();
}
- __ b(&exit);
+ __ Ret();
__ bind(&slow);
__ push(r1); // restore stack
__ push(r0);
@@ -4584,16 +4522,13 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
default:
UNREACHABLE();
}
- __ bind(&exit);
break;
}
case Token::SHL:
case Token::SHR:
case Token::SAR: {
- Label slow, exit;
- // tag check
- __ orr(r2, r1, Operand(r0)); // r2 = x | y;
+ Label slow;
ASSERT(kSmiTag == 0); // adjust code below
__ tst(r2, Operand(kSmiTagMask));
__ b(ne, &slow);
@@ -4633,7 +4568,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
// tag result and store it in r0
ASSERT(kSmiTag == 0); // adjust code below
__ mov(r0, Operand(r3, LSL, kSmiTagSize));
- __ b(&exit);
+ __ Ret();
// slow case
__ bind(&slow);
__ push(r1); // restore stack
@@ -4645,13 +4580,13 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
case Token::SHL: __ InvokeBuiltin(Builtins::SHL, JUMP_JS); break;
default: UNREACHABLE();
}
- __ bind(&exit);
break;
}
default: UNREACHABLE();
}
- __ Ret();
+ // This code should be unreachable.
+ __ stop("Unreachable");
}
@@ -4661,7 +4596,9 @@ void StackCheckStub::Generate(MacroAssembler* masm) {
__ ldr(ip, MemOperand(ip));
__ cmp(sp, Operand(ip));
__ b(hs, &within_limit);
- // Do tail-call to runtime routine.
+ // Do tail-call to runtime routine. Runtime routines expect at least one
+ // argument, so give it a Smi.
+ __ mov(r0, Operand(Smi::FromInt(0)));
__ push(r0);
__ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1);
__ bind(&within_limit);
@@ -4721,7 +4658,11 @@ void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
__ mov(cp, Operand(0), LeaveCC, eq);
// Restore cp otherwise.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
- if (kDebug && FLAG_debug_code) __ mov(lr, Operand(pc));
+#ifdef DEBUG
+ if (FLAG_debug_code) {
+ __ mov(lr, Operand(pc));
+ }
+#endif
__ pop(pc);
}
@@ -4784,7 +4725,11 @@ void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {
__ mov(cp, Operand(0), LeaveCC, eq);
// Restore cp otherwise.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
- if (kDebug && FLAG_debug_code) __ mov(lr, Operand(pc));
+#ifdef DEBUG
+ if (FLAG_debug_code) {
+ __ mov(lr, Operand(pc));
+ }
+#endif
__ pop(pc);
}
@@ -5043,9 +4988,11 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
}
__ ldr(ip, MemOperand(ip)); // deref address
- // Branch and link to JSEntryTrampoline
+ // Branch and link to JSEntryTrampoline. We don't use the double underscore
+ // macro for the add instruction because we don't want the coverage tool
+ // inserting instructions here after we read the pc.
__ mov(lr, Operand(pc));
- __ add(pc, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
+ masm->add(pc, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
// Unlink this frame from the handler chain. When reading the
// address of the next handler, there is no need to use the address
@@ -5057,6 +5004,7 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
// No need to restore registers
__ add(sp, sp, Operand(StackHandlerConstants::kSize));
+
__ bind(&exit); // r0 holds result
// Restore the top frame descriptors from the stack.
__ pop(r3);
@@ -5068,7 +5016,9 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
// Restore callee-saved registers and return.
#ifdef DEBUG
- if (FLAG_debug_code) __ mov(lr, Operand(pc));
+ if (FLAG_debug_code) {
+ __ mov(lr, Operand(pc));
+ }
#endif
__ ldm(ia_w, sp, kCalleeSaved | pc.bit());
}
@@ -5084,13 +5034,13 @@ void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) {
// Nothing to do: The formal number of parameters has already been
// passed in register r0 by calling function. Just return it.
- __ mov(pc, lr);
+ __ Jump(lr);
// Arguments adaptor case: Read the arguments length from the
// adaptor frame and return it.
__ bind(&adaptor);
__ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
- __ mov(pc, lr);
+ __ Jump(lr);
}
@@ -5122,7 +5072,7 @@ void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
__ sub(r3, r0, r1);
__ add(r3, fp, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize));
__ ldr(r0, MemOperand(r3, kDisplacement));
- __ mov(pc, lr);
+ __ Jump(lr);
// Arguments adaptor case: Check index against actual arguments
// limit found in the arguments adaptor frame. Use unsigned
@@ -5136,7 +5086,7 @@ void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
__ sub(r3, r0, r1);
__ add(r3, r2, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize));
__ ldr(r0, MemOperand(r3, kDisplacement));
- __ mov(pc, lr);
+ __ Jump(lr);
// Slow-case: Handle non-smi or out-of-bounds access to arguments
// by calling the runtime system.
diff --git a/deps/v8/src/codegen-arm.h b/deps/v8/src/arm/codegen-arm.h
index b072f75ed..c098acdd7 100644
--- a/deps/v8/src/codegen-arm.h
+++ b/deps/v8/src/arm/codegen-arm.h
@@ -25,8 +25,8 @@
// (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_CODEGEN_ARM_H_
-#define V8_CODEGEN_ARM_H_
+#ifndef V8_ARM_CODEGEN_ARM_H_
+#define V8_ARM_CODEGEN_ARM_H_
namespace v8 { namespace internal {
@@ -35,9 +35,6 @@ class DeferredCode;
class RegisterAllocator;
class RegisterFile;
-// Mode to overwrite BinaryExpression values.
-enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
-
enum InitState { CONST_INIT, NOT_CONST_INIT };
enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
@@ -292,10 +289,13 @@ class CodeGenerator: public AstVisitor {
void ToBoolean(JumpTarget* true_target, JumpTarget* false_target);
- void GenericBinaryOperation(Token::Value op);
+ void GenericBinaryOperation(Token::Value op, OverwriteMode overwrite_mode);
void Comparison(Condition cc, bool strict = false);
- void SmiOperation(Token::Value op, Handle<Object> value, bool reversed);
+ void SmiOperation(Token::Value op,
+ Handle<Object> value,
+ bool reversed,
+ OverwriteMode mode);
void CallWithArguments(ZoneList<Expression*>* arguments, int position);
@@ -303,7 +303,17 @@ class CodeGenerator: public AstVisitor {
void Branch(bool if_true, JumpTarget* target);
void CheckStack();
+ struct InlineRuntimeLUT {
+ void (CodeGenerator::*method)(ZoneList<Expression*>*);
+ const char* name;
+ };
+
+ static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
bool CheckForInlineRuntimeCall(CallRuntime* node);
+ static bool PatchInlineRuntimeEntry(Handle<String> name,
+ const InlineRuntimeLUT& new_entry,
+ InlineRuntimeLUT* old_entry);
+
Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node);
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
@@ -433,6 +443,8 @@ class CodeGenerator: public AstVisitor {
// in a spilled state.
bool in_spilled_code_;
+ static InlineRuntimeLUT kInlineRuntimeLUT[];
+
friend class VirtualFrame;
friend class JumpTarget;
friend class Reference;
@@ -443,4 +455,4 @@ class CodeGenerator: public AstVisitor {
} } // namespace v8::internal
-#endif // V8_CODEGEN_ARM_H_
+#endif // V8_ARM_CODEGEN_ARM_H_
diff --git a/deps/v8/src/constants-arm.h b/deps/v8/src/arm/constants-arm.h
index f55396380..66c6a8d86 100644
--- a/deps/v8/src/constants-arm.h
+++ b/deps/v8/src/arm/constants-arm.h
@@ -25,8 +25,8 @@
// (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_CONSTANTS_ARM_H_
-#define V8_CONSTANTS_ARM_H_
+#ifndef V8_ARM_CONSTANTS_ARM_H_
+#define V8_ARM_CONSTANTS_ARM_H_
namespace assembler { namespace arm {
@@ -106,7 +106,12 @@ enum SoftwareInterruptCodes {
call_rt_r5 = 0x10,
call_rt_r2 = 0x11,
// break point
- break_point = 0x20
+ break_point = 0x20,
+ // FP operations. These simulate calling into C for a moment to do fp ops.
+ // They should trash all caller-save registers.
+ simulator_fp_add = 0x21,
+ simulator_fp_sub = 0x22,
+ simulator_fp_mul = 0x23
};
@@ -232,4 +237,4 @@ class Instr {
} } // namespace assembler::arm
-#endif // V8_CONSTANTS_ARM_H_
+#endif // V8_ARM_CONSTANTS_ARM_H_
diff --git a/deps/v8/src/cpu-arm.cc b/deps/v8/src/arm/cpu-arm.cc
index 736966129..736966129 100644
--- a/deps/v8/src/cpu-arm.cc
+++ b/deps/v8/src/arm/cpu-arm.cc
diff --git a/deps/v8/src/debug-arm.cc b/deps/v8/src/arm/debug-arm.cc
index 9fb77b775..f86f981cb 100644
--- a/deps/v8/src/debug-arm.cc
+++ b/deps/v8/src/arm/debug-arm.cc
@@ -32,7 +32,7 @@
namespace v8 { namespace internal {
-
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Currently debug break is not supported in frame exit code on ARM.
bool BreakLocationIterator::IsDebugBreakAtReturn() {
return false;
@@ -58,7 +58,7 @@ bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
}
-#define __ masm->
+#define __ ACCESS_MASM(masm)
static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
@@ -191,5 +191,6 @@ void Debug::GenerateStubNoRegistersDebugBreak(MacroAssembler* masm) {
#undef __
+#endif // ENABLE_DEBUGGER_SUPPORT
} } // namespace v8::internal
diff --git a/deps/v8/src/disasm-arm.cc b/deps/v8/src/arm/disasm-arm.cc
index d19e042df..3b7474dba 100644
--- a/deps/v8/src/disasm-arm.cc
+++ b/deps/v8/src/arm/disasm-arm.cc
@@ -261,6 +261,15 @@ void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes swi) {
case break_point:
Print("break_point");
return;
+ case simulator_fp_add:
+ Print("simulator_fp_add");
+ return;
+ case simulator_fp_mul:
+ Print("simulator_fp_mul");
+ return;
+ case simulator_fp_sub:
+ Print("simulator_fp_sub");
+ return;
default:
out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
"%d",
diff --git a/deps/v8/src/frames-arm.cc b/deps/v8/src/arm/frames-arm.cc
index 121fb75be..d26198ae1 100644
--- a/deps/v8/src/frames-arm.cc
+++ b/deps/v8/src/arm/frames-arm.cc
@@ -28,7 +28,7 @@
#include "v8.h"
#include "frames-inl.h"
-#include "assembler-arm-inl.h"
+#include "arm/assembler-arm-inl.h"
namespace v8 { namespace internal {
diff --git a/deps/v8/src/frames-arm.h b/deps/v8/src/arm/frames-arm.h
index 930f6e0e0..9a18f3d93 100644
--- a/deps/v8/src/frames-arm.h
+++ b/deps/v8/src/arm/frames-arm.h
@@ -25,8 +25,8 @@
// (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_FRAMES_ARM_H_
-#define V8_FRAMES_ARM_H_
+#ifndef V8_ARM_FRAMES_ARM_H_
+#define V8_ARM_FRAMES_ARM_H_
namespace v8 { namespace internal {
@@ -376,4 +376,4 @@ inline Object* JavaScriptFrame::function_slot_object() const {
} } // namespace v8::internal
-#endif // V8_FRAMES_ARM_H_
+#endif // V8_ARM_FRAMES_ARM_H_
diff --git a/deps/v8/src/ic-arm.cc b/deps/v8/src/arm/ic-arm.cc
index 4db3980c5..b07c4742d 100644
--- a/deps/v8/src/ic-arm.cc
+++ b/deps/v8/src/arm/ic-arm.cc
@@ -39,7 +39,7 @@ namespace v8 { namespace internal {
// Static IC stub generators.
//
-#define __ masm->
+#define __ ACCESS_MASM(masm)
// Helper function used from LoadIC/CallIC GenerateNormal.
@@ -96,7 +96,9 @@ static void GenerateDictionaryLoad(MacroAssembler* masm,
// Compute the masked index: (hash + i + i * i) & mask.
__ ldr(t1, FieldMemOperand(r2, String::kLengthOffset));
__ mov(t1, Operand(t1, LSR, String::kHashShift));
- if (i > 0) __ add(t1, t1, Operand(Dictionary::GetProbeOffset(i)));
+ if (i > 0) {
+ __ add(t1, t1, Operand(Dictionary::GetProbeOffset(i)));
+ }
__ and_(t1, t1, Operand(r3));
// Scale the index by multiplying by the element size.
@@ -125,27 +127,20 @@ static void GenerateDictionaryLoad(MacroAssembler* masm,
}
-// Helper function used to check that a value is either not a function
-// or is loaded if it is a function.
-static void GenerateCheckNonFunctionOrLoaded(MacroAssembler* masm,
- Label* miss,
- Register value,
- Register scratch) {
+// Helper function used to check that a value is either not an object
+// or is loaded if it is an object.
+static void GenerateCheckNonObjectOrLoaded(MacroAssembler* masm,
+ Label* miss,
+ Register value,
+ Register scratch) {
Label done;
// Check if the value is a Smi.
__ tst(value, Operand(kSmiTagMask));
__ b(eq, &done);
- // Check if the value is a function.
- __ ldr(scratch, FieldMemOperand(value, HeapObject::kMapOffset));
- __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
- __ cmp(scratch, Operand(JS_FUNCTION_TYPE));
- __ b(ne, &done);
- // Check if the function has been loaded.
- __ ldr(scratch,
- FieldMemOperand(value, JSFunction::kSharedFunctionInfoOffset));
- __ ldr(scratch,
- FieldMemOperand(scratch, SharedFunctionInfo::kLazyLoadDataOffset));
- __ cmp(scratch, Operand(Factory::undefined_value()));
+ // Check if the object has been loaded.
+ __ ldr(scratch, FieldMemOperand(value, JSObject::kMapOffset));
+ __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitField2Offset));
+ __ tst(scratch, Operand(1 << Map::kNeedsLoading));
__ b(ne, miss);
__ bind(&done);
}
@@ -282,9 +277,9 @@ static void GenerateNormalHelper(MacroAssembler* masm,
__ b(ne, miss);
// Check that the function has been loaded.
- __ ldr(r0, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
- __ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kLazyLoadDataOffset));
- __ cmp(r0, Operand(Factory::undefined_value()));
+ __ ldr(r0, FieldMemOperand(r1, JSObject::kMapOffset));
+ __ ldrb(r0, FieldMemOperand(r0, Map::kBitField2Offset));
+ __ tst(r0, Operand(1 << Map::kNeedsLoading));
__ b(ne, miss);
// Patch the receiver with the global proxy if necessary.
@@ -468,7 +463,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
__ bind(&probe);
GenerateDictionaryLoad(masm, &miss, r1, r0);
- GenerateCheckNonFunctionOrLoaded(masm, &miss, r0, r1);
+ GenerateCheckNonObjectOrLoaded(masm, &miss, r0, r1);
__ Ret();
// Global object access: Check access rights.
@@ -502,10 +497,18 @@ void LoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
}
-// TODO(181): Implement map patching once loop nesting is tracked on
-// the ARM platform so we can generate inlined fast-case code for
-// array indexing in loops.
-void KeyedLoadIC::PatchInlinedMapCheck(Address address, Object* value) { }
+// TODO(181): Implement map patching once loop nesting is tracked on the
+// ARM platform so we can generate inlined fast-case code loads in
+// loops.
+void LoadIC::ClearInlinedVersion(Address address) {}
+bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) {
+ return false;
+}
+
+void KeyedLoadIC::ClearInlinedVersion(Address address) {}
+bool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) {
+ return false;
+}
Object* KeyedLoadIC_Miss(Arguments args);
diff --git a/deps/v8/src/jump-target-arm.cc b/deps/v8/src/arm/jump-target-arm.cc
index 3ce5f308e..6d375e5ce 100644
--- a/deps/v8/src/jump-target-arm.cc
+++ b/deps/v8/src/arm/jump-target-arm.cc
@@ -35,7 +35,7 @@ namespace v8 { namespace internal {
// -------------------------------------------------------------------------
// JumpTarget implementation.
-#define __ masm_->
+#define __ ACCESS_MASM(masm_)
void JumpTarget::DoJump() {
ASSERT(cgen_ != NULL);
diff --git a/deps/v8/src/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc
index 88a300b11..365c1ad7f 100644
--- a/deps/v8/src/macro-assembler-arm.cc
+++ b/deps/v8/src/arm/macro-assembler-arm.cc
@@ -168,11 +168,11 @@ void MacroAssembler::Call(Handle<Code> code, RelocInfo::Mode rmode,
}
-void MacroAssembler::Ret() {
+void MacroAssembler::Ret(Condition cond) {
#if USE_BX
- bx(lr);
+ bx(lr, cond);
#else
- mov(pc, Operand(lr));
+ mov(pc, Operand(lr), LeaveCC, cond);
#endif
}
@@ -320,16 +320,19 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
add(r6, fp, Operand(r4, LSL, kPointerSizeLog2));
add(r6, r6, Operand(ExitFrameConstants::kPPDisplacement - kPointerSize));
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Save the state of all registers to the stack from the memory
// location. This is needed to allow nested break points.
if (type == StackFrame::EXIT_DEBUG) {
// Use sp as base to push.
CopyRegistersFromMemoryToStack(sp, kJSCallerSaved);
}
+#endif
}
void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Restore the memory copy of the registers by digging them out from
// the stack. This is needed to allow nested break points.
if (type == StackFrame::EXIT_DEBUG) {
@@ -339,6 +342,7 @@ void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
add(r3, fp, Operand(kOffset));
CopyRegistersFromStackToMemory(r3, r2, kJSCallerSaved);
}
+#endif
// Clear top frame.
mov(r3, Operand(0));
@@ -348,9 +352,9 @@ void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
// Restore current context from top and clear it in debug mode.
mov(ip, Operand(ExternalReference(Top::k_context_address)));
ldr(cp, MemOperand(ip));
- if (kDebug) {
- str(r3, MemOperand(ip));
- }
+#ifdef DEBUG
+ str(r3, MemOperand(ip));
+#endif
// Pop the arguments, restore registers, and return.
mov(sp, Operand(fp)); // respect ABI stack constraint
@@ -491,6 +495,7 @@ void MacroAssembler::InvokeFunction(Register fun,
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
void MacroAssembler::SaveRegistersToMemory(RegList regs) {
ASSERT((regs & ~kJSCallerSaved) == 0);
// Copy the content of registers to memory location.
@@ -548,7 +553,7 @@ void MacroAssembler::CopyRegistersFromStackToMemory(Register base,
}
}
}
-
+#endif
void MacroAssembler::PushTryHandler(CodeLocation try_location,
HandlerType type) {
@@ -674,10 +679,10 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
// Load current lexical context from the stack frame.
ldr(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset));
// In debug mode, make sure the lexical context is set.
- if (kDebug) {
- cmp(scratch, Operand(0));
- Check(ne, "we should not have an empty lexical context");
- }
+#ifdef DEBUG
+ cmp(scratch, Operand(0));
+ Check(ne, "we should not have an empty lexical context");
+#endif
// Load the global context of the current context.
int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
diff --git a/deps/v8/src/macro-assembler-arm.h b/deps/v8/src/arm/macro-assembler-arm.h
index 4b999fdfc..e336757e0 100644
--- a/deps/v8/src/macro-assembler-arm.h
+++ b/deps/v8/src/arm/macro-assembler-arm.h
@@ -25,8 +25,8 @@
// (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_MACRO_ASSEMBLER_ARM_H_
-#define V8_MACRO_ASSEMBLER_ARM_H_
+#ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_
+#define V8_ARM_MACRO_ASSEMBLER_ARM_H_
#include "assembler.h"
@@ -86,7 +86,7 @@ class MacroAssembler: public Assembler {
void Call(Register target, Condition cond = al);
void Call(byte* target, RelocInfo::Mode rmode, Condition cond = al);
void Call(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
- void Ret();
+ void Ret(Condition cond = al);
// Jumps to the label at the index given by the Smi in "index".
void SmiJumpTable(Register index, Vector<Label*> targets);
@@ -138,6 +138,7 @@ class MacroAssembler: public Assembler {
InvokeFlag flag);
+#ifdef ENABLE_DEBUGGER_SUPPORT
// ---------------------------------------------------------------------------
// Debugger Support
@@ -147,7 +148,7 @@ class MacroAssembler: public Assembler {
void CopyRegistersFromStackToMemory(Register base,
Register scratch,
RegList regs);
-
+#endif
// ---------------------------------------------------------------------------
// Exception handling
@@ -297,7 +298,16 @@ static inline MemOperand FieldMemOperand(Register object, int offset) {
}
+#ifdef GENERATED_CODE_COVERAGE
+#define CODE_COVERAGE_STRINGIFY(x) #x
+#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
+#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
+#define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm->
+#else
+#define ACCESS_MASM(masm) masm->
+#endif
+
} } // namespace v8::internal
-#endif // V8_MACRO_ASSEMBLER_ARM_H_
+#endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_
diff --git a/deps/v8/src/regexp-macro-assembler-arm.cc b/deps/v8/src/arm/regexp-macro-assembler-arm.cc
index bcfddf67e..bf07f0e3d 100644
--- a/deps/v8/src/regexp-macro-assembler-arm.cc
+++ b/deps/v8/src/arm/regexp-macro-assembler-arm.cc
@@ -28,7 +28,7 @@
#include "v8.h"
#include "ast.h"
#include "regexp-macro-assembler.h"
-#include "regexp-macro-assembler-arm.h"
+#include "arm/regexp-macro-assembler-arm.h"
namespace v8 { namespace internal {
diff --git a/deps/v8/src/regexp-macro-assembler-arm.h b/deps/v8/src/arm/regexp-macro-assembler-arm.h
index 51352bc27..2f38bb73e 100644
--- a/deps/v8/src/regexp-macro-assembler-arm.h
+++ b/deps/v8/src/arm/regexp-macro-assembler-arm.h
@@ -25,8 +25,8 @@
// (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 REGEXP_MACRO_ASSEMBLER_ARM_H_
-#define REGEXP_MACRO_ASSEMBLER_ARM_H_
+#ifndef V8_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_
+#define V8_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_
namespace v8 { namespace internal {
@@ -38,4 +38,4 @@ class RegExpMacroAssemblerARM: public RegExpMacroAssembler {
}} // namespace v8::internal
-#endif /* REGEXP_MACRO_ASSEMBLER_ARM_H_ */
+#endif // V8_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_
diff --git a/deps/v8/src/register-allocator-arm.cc b/deps/v8/src/arm/register-allocator-arm.cc
index 36a4d20e1..d468c84e3 100644
--- a/deps/v8/src/register-allocator-arm.cc
+++ b/deps/v8/src/arm/register-allocator-arm.cc
@@ -66,6 +66,14 @@ void RegisterAllocator::UnuseReserved(RegisterFile* register_file) {
}
+bool RegisterAllocator::IsReserved(int reg_code) {
+ return (reg_code == sp.code())
+ || (reg_code == fp.code())
+ || (reg_code == cp.code())
+ || (reg_code == pc.code());
+}
+
+
void RegisterAllocator::Initialize() {
Reset();
// The following registers are live on function entry, saved in the
diff --git a/deps/v8/src/simulator-arm.cc b/deps/v8/src/arm/simulator-arm.cc
index 5a61107cf..9737e9539 100644
--- a/deps/v8/src/simulator-arm.cc
+++ b/deps/v8/src/arm/simulator-arm.cc
@@ -30,8 +30,8 @@
#include "v8.h"
#include "disasm.h"
-#include "constants-arm.h"
-#include "simulator-arm.h"
+#include "arm/constants-arm.h"
+#include "arm/simulator-arm.h"
#if !defined(__arm__)
@@ -90,12 +90,44 @@ Debugger::~Debugger() {
}
+
+#ifdef GENERATED_CODE_COVERAGE
+static FILE* coverage_log = NULL;
+
+
+static void InitializeCoverage() {
+ char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
+ if (file_name != NULL) {
+ coverage_log = fopen(file_name, "aw+");
+ }
+}
+
+
+void Debugger::Stop(Instr* instr) {
+ char* str = reinterpret_cast<char*>(instr->InstructionBits() & 0x0fffffff);
+ if (strlen(str) > 0) {
+ if (coverage_log != NULL) {
+ fprintf(coverage_log, "%s\n", str);
+ fflush(coverage_log);
+ }
+ instr->SetInstructionBits(0xe1a00000); // Overwrite with nop.
+ }
+ sim_->set_pc(sim_->get_pc() + Instr::kInstrSize);
+}
+
+#else // ndef GENERATED_CODE_COVERAGE
+
+static void InitializeCoverage() {
+}
+
+
void Debugger::Stop(Instr* instr) {
const char* str = (const char*)(instr->InstructionBits() & 0x0fffffff);
PrintF("Simulator hit %s\n", str);
sim_->set_pc(sim_->get_pc() + Instr::kInstrSize);
Debug();
}
+#endif
static const char* reg_names[] = { "r0", "r1", "r2", "r3",
@@ -375,6 +407,7 @@ Simulator::Simulator() {
// access violation if the simulator ever tries to execute it.
registers_[pc] = bad_lr;
registers_[lr] = bad_lr;
+ InitializeCoverage();
}
@@ -427,6 +460,37 @@ int32_t Simulator::get_pc() const {
}
+// For use in calls that take two double values, constructed from r0, r1, r2
+// and r3.
+void Simulator::GetFpArgs(double* x, double* y) {
+ // We use a char buffer to get around the strict-aliasing rules which
+ // otherwise allow the compiler to optimize away the copy.
+ char buffer[2 * sizeof(registers_[0])];
+ // Registers 0 and 1 -> x.
+ memcpy(buffer, registers_, sizeof(buffer));
+ memcpy(x, buffer, sizeof(buffer));
+ // Registers 2 and 3 -> y.
+ memcpy(buffer, registers_ + 2, sizeof(buffer));
+ memcpy(y, buffer, sizeof(buffer));
+}
+
+
+void Simulator::SetFpResult(const double& result) {
+ char buffer[2 * sizeof(registers_[0])];
+ memcpy(buffer, &result, sizeof(buffer));
+ // result -> registers 0 and 1.
+ memcpy(registers_, buffer, sizeof(buffer));
+}
+
+
+void Simulator::TrashCallerSaveRegisters() {
+ // We don't trash the registers with the return value.
+ registers_[2] = 0x50Bad4U;
+ registers_[3] = 0x50Bad4U;
+ registers_[12] = 0x50Bad4U;
+}
+
+
// The ARM cannot do unaligned reads and writes. On some ARM platforms an
// interrupt is caused. On others it does a funky rotation thing. For now we
// simply disallow unaligned reads, but at some point we may want to move to
@@ -862,7 +926,8 @@ typedef int64_t (*SimulatorRuntimeCall)(intptr_t arg0, intptr_t arg1);
// Software interrupt instructions are used by the simulator to call into the
// C-based V8 runtime.
void Simulator::SoftwareInterrupt(Instr* instr) {
- switch (instr->SwiField()) {
+ int swi = instr->SwiField();
+ switch (swi) {
case call_rt_r5: {
SimulatorRuntimeCall target =
reinterpret_cast<SimulatorRuntimeCall>(get_register(r5));
@@ -894,6 +959,30 @@ void Simulator::SoftwareInterrupt(Instr* instr) {
dbg.Debug();
break;
}
+ {
+ double x, y, z;
+ case simulator_fp_add:
+ GetFpArgs(&x, &y);
+ z = x + y;
+ SetFpResult(z);
+ TrashCallerSaveRegisters();
+ set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
+ break;
+ case simulator_fp_sub:
+ GetFpArgs(&x, &y);
+ z = x - y;
+ SetFpResult(z);
+ TrashCallerSaveRegisters();
+ set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
+ break;
+ case simulator_fp_mul:
+ GetFpArgs(&x, &y);
+ z = x * y;
+ SetFpResult(z);
+ TrashCallerSaveRegisters();
+ set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
+ break;
+ }
default: {
UNREACHABLE();
break;
diff --git a/deps/v8/src/simulator-arm.h b/deps/v8/src/arm/simulator-arm.h
index 4f3c53d41..2029fd3bc 100644
--- a/deps/v8/src/simulator-arm.h
+++ b/deps/v8/src/arm/simulator-arm.h
@@ -33,14 +33,14 @@
// which will start execution in the Simulator or forwards to the real entry
// on a ARM HW platform.
-#ifndef V8_SIMULATOR_ARM_H_
-#define V8_SIMULATOR_ARM_H_
+#ifndef V8_ARM_SIMULATOR_ARM_H_
+#define V8_ARM_SIMULATOR_ARM_H_
#if defined(__arm__)
// When running without a simulator we call the entry directly.
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
- entry(p0, p1, p2, p3, p4)
+ reinterpret_cast<Object*>(entry(p0, p1, p2, p3, p4))
// Calculated the stack limit beyond which we will throw stack overflow errors.
// This macro must be called from a C++ method. It relies on being able to take
@@ -174,6 +174,12 @@ class Simulator {
// Executes one instruction.
void InstructionDecode(Instr* instr);
+ // For use in calls that take two double values, constructed from r0, r1, r2
+ // and r3.
+ void GetFpArgs(double* x, double* y);
+ void SetFpResult(const double& result);
+ void TrashCallerSaveRegisters();
+
// architecture state
int32_t registers_[16];
bool n_flag_;
@@ -195,4 +201,4 @@ class Simulator {
#endif // defined(__arm__)
-#endif // V8_SIMULATOR_ARM_H_
+#endif // V8_ARM_SIMULATOR_ARM_H_
diff --git a/deps/v8/src/stub-cache-arm.cc b/deps/v8/src/arm/stub-cache-arm.cc
index 211b643fa..56afa0288 100644
--- a/deps/v8/src/stub-cache-arm.cc
+++ b/deps/v8/src/arm/stub-cache-arm.cc
@@ -33,7 +33,7 @@
namespace v8 { namespace internal {
-#define __ masm->
+#define __ ACCESS_MASM(masm)
static void ProbeTable(MacroAssembler* masm,
@@ -183,7 +183,7 @@ void StubCompiler::GenerateLoadField(MacroAssembler* masm,
// Check that the maps haven't changed.
Register reg =
- __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+ masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
GenerateFastPropertyLoad(masm, r0, reg, holder, index);
__ Ret();
}
@@ -203,7 +203,7 @@ void StubCompiler::GenerateLoadConstant(MacroAssembler* masm,
// Check that the maps haven't changed.
Register reg =
- __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+ masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
// Return the constant value.
__ mov(r0, Operand(Handle<Object>(value)));
@@ -226,7 +226,7 @@ void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
// Check that the maps haven't changed.
Register reg =
- __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+ masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
// Push the arguments on the JS stack of the caller.
__ push(receiver); // receiver
@@ -256,7 +256,7 @@ void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
// Check that the maps haven't changed.
Register reg =
- __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+ masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
// Push the arguments on the JS stack of the caller.
__ push(receiver); // receiver
@@ -456,8 +456,7 @@ void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
#undef __
-
-#define __ masm()->
+#define __ ACCESS_MASM(masm())
Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
@@ -511,7 +510,7 @@ Object* CallStubCompiler::CompileCallField(Object* object,
// Do the right check and compute the holder register.
Register reg =
- __ CheckMaps(JSObject::cast(object), r0, holder, r3, r2, &miss);
+ masm()->CheckMaps(JSObject::cast(object), r0, holder, r3, r2, &miss);
GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
// Check that the function really is a function.
diff --git a/deps/v8/src/virtual-frame-arm.cc b/deps/v8/src/arm/virtual-frame-arm.cc
index baf08145b..43100f1ec 100644
--- a/deps/v8/src/virtual-frame-arm.cc
+++ b/deps/v8/src/arm/virtual-frame-arm.cc
@@ -36,7 +36,8 @@ namespace v8 { namespace internal {
// -------------------------------------------------------------------------
// VirtualFrame implementation.
-#define __ masm_->
+#define __ ACCESS_MASM(masm_)
+
// On entry to a function, the virtual frame already contains the
// receiver and the parameters. All initial frame elements are in
@@ -70,6 +71,16 @@ void VirtualFrame::SyncElementByPushing(int index) {
}
+void VirtualFrame::SyncRange(int begin, int end) {
+ // All elements are in memory on ARM (ie, synced).
+#ifdef DEBUG
+ for (int i = begin; i <= end; i++) {
+ ASSERT(elements_[i].is_synced());
+ }
+#endif
+}
+
+
void VirtualFrame::MergeTo(VirtualFrame* expected) {
Comment cmnt(masm_, "[ Merge frame");
// We should always be merging the code generator's current frame to an
diff --git a/deps/v8/src/virtual-frame-arm.h b/deps/v8/src/arm/virtual-frame-arm.h
index af3c08ce7..371a23e93 100644
--- a/deps/v8/src/virtual-frame-arm.h
+++ b/deps/v8/src/arm/virtual-frame-arm.h
@@ -25,8 +25,8 @@
// (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_VIRTUAL_FRAME_ARM_H_
-#define V8_VIRTUAL_FRAME_ARM_H_
+#ifndef V8_ARM_VIRTUAL_FRAME_ARM_H_
+#define V8_ARM_VIRTUAL_FRAME_ARM_H_
#include "register-allocator.h"
@@ -477,4 +477,4 @@ class VirtualFrame : public Malloced {
} } // namespace v8::internal
-#endif // V8_VIRTUAL_FRAME_ARM_H_
+#endif // V8_ARM_VIRTUAL_FRAME_ARM_H_
diff --git a/deps/v8/src/array.js b/deps/v8/src/array.js
index d30a98960..ed84b5f72 100644
--- a/deps/v8/src/array.js
+++ b/deps/v8/src/array.js
@@ -709,32 +709,91 @@ function ArraySort(comparefn) {
QuickSort(a, high_start, to);
}
- var old_length = ToUint32(this.length);
- if (old_length < 2) return this;
+ // Copies elements in the range 0..length from obj's prototype chain
+ // to obj itself, if obj has holes. Returns one more than the maximal index
+ // of a prototype property.
+ function CopyFromPrototype(obj, length) {
+ var max = 0;
+ for (var proto = obj.__proto__; proto; proto = proto.__proto__) {
+ var indices = %GetArrayKeys(proto, length);
+ if (indices.length > 0) {
+ if (indices[0] == -1) {
+ // It's an interval.
+ var proto_length = indices[1];
+ for (var i = 0; i < proto_length; i++) {
+ if (!obj.hasOwnProperty(i) && proto.hasOwnProperty(i)) {
+ obj[i] = proto[i];
+ if (i >= max) { max = i + 1; }
+ }
+ }
+ } else {
+ for (var i = 0; i < indices.length; i++) {
+ var index = indices[i];
+ if (!IS_UNDEFINED(index) &&
+ !obj.hasOwnProperty(index) && proto.hasOwnProperty(index)) {
+ obj[index] = proto[index];
+ if (index >= max) { max = index + 1; }
+ }
+ }
+ }
+ }
+ }
+ return max;
+ }
- %RemoveArrayHoles(this);
+ // Set a value of "undefined" on all indices in the range from..to
+ // where a prototype of obj has an element. I.e., shadow all prototype
+ // elements in that range.
+ function ShadowPrototypeElements(obj, from, to) {
+ for (var proto = obj.__proto__; proto; proto = proto.__proto__) {
+ var indices = %GetArrayKeys(proto, to);
+ if (indices.length > 0) {
+ if (indices[0] == -1) {
+ // It's an interval.
+ var proto_length = indices[1];
+ for (var i = from; i < proto_length; i++) {
+ if (proto.hasOwnProperty(i)) {
+ obj[i] = void 0;
+ }
+ }
+ } else {
+ for (var i = 0; i < indices.length; i++) {
+ var index = indices[i];
+ if (!IS_UNDEFINED(index) && from <= index &&
+ proto.hasOwnProperty(index)) {
+ obj[index] = void 0;
+ }
+ }
+ }
+ }
+ }
+ }
var length = ToUint32(this.length);
-
- // Move undefined elements to the end of the array.
- for (var i = 0; i < length; ) {
- if (IS_UNDEFINED(this[i])) {
- length--;
- this[i] = this[length];
- this[length] = void 0;
- } else {
- i++;
- }
+ if (length < 2) return this;
+
+ var is_array = IS_ARRAY(this);
+ var max_prototype_element;
+ if (!is_array) {
+ // For compatibility with JSC, we also sort elements inherited from
+ // the prototype chain on non-Array objects.
+ // We do this by copying them to this object and sorting only
+ // local elements. This is not very efficient, but sorting with
+ // inherited elements happens very, very rarely, if at all.
+ // The specification allows "implementation dependent" behavior
+ // if an element on the prototype chain has an element that
+ // might interact with sorting.
+ max_prototype_element = CopyFromPrototype(this, length);
}
- QuickSort(this, 0, length);
+ var num_non_undefined = %RemoveArrayHoles(this, length);
- // We only changed the length of the this object (in
- // RemoveArrayHoles) if it was an array. We are not allowed to set
- // the length of the this object if it is not an array because this
- // might introduce a new length property.
- if (IS_ARRAY(this)) {
- this.length = old_length;
+ QuickSort(this, 0, num_non_undefined);
+
+ if (!is_array && (num_non_undefined + 1 < max_prototype_element)) {
+ // For compatibility with JSC, we shadow any elements in the prototype
+ // chain that has become exposed by sort moving a hole to its position.
+ ShadowPrototypeElements(this, num_non_undefined, max_prototype_element);
}
return this;
@@ -879,6 +938,62 @@ function ArrayLastIndexOf(element, index) {
}
+function ArrayReduce(callback, current) {
+ if (!IS_FUNCTION(callback)) {
+ throw MakeTypeError('called_non_callable', [callback]);
+ }
+ // Pull out the length so that modifications to the length in the
+ // loop will not affect the looping.
+ var length = this.length;
+ var i = 0;
+
+ find_initial: if (%_ArgumentsLength() < 2) {
+ for (; i < length; i++) {
+ current = this[i];
+ if (!IS_UNDEFINED(current) || i in this) {
+ i++;
+ break find_initial;
+ }
+ }
+ throw MakeTypeError('reduce_no_initial', []);
+ }
+
+ for (; i < length; i++) {
+ var element = this[i];
+ if (!IS_UNDEFINED(element) || i in this) {
+ current = callback.call(null, current, element, i, this);
+ }
+ }
+ return current;
+}
+
+function ArrayReduceRight(callback, current) {
+ if (!IS_FUNCTION(callback)) {
+ throw MakeTypeError('called_non_callable', [callback]);
+ }
+ var i = this.length - 1;
+
+ find_initial: if (%_ArgumentsLength() < 2) {
+ for (; i >= 0; i--) {
+ current = this[i];
+ if (!IS_UNDEFINED(current) || i in this) {
+ i--;
+ break find_initial;
+ }
+ }
+ throw MakeTypeError('reduce_no_initial', []);
+ }
+
+ for (; i >= 0; i--) {
+ var element = this[i];
+ if (!IS_UNDEFINED(element) || i in this) {
+ current = callback.call(null, current, element, i, this);
+ }
+ }
+ return current;
+}
+
+
// -------------------------------------------------------------------
@@ -890,7 +1005,6 @@ function UpdateFunctionLengths(lengths) {
// -------------------------------------------------------------------
-
function SetupArray() {
// Setup non-enumerable constructor property on the Array.prototype
// object.
@@ -898,7 +1012,7 @@ function SetupArray() {
// Setup non-enumerable functions of the Array.prototype object and
// set their names.
- InstallFunctions($Array.prototype, DONT_ENUM, $Array(
+ InstallFunctionsOnHiddenPrototype($Array.prototype, DONT_ENUM, $Array(
"toString", ArrayToString,
"toLocaleString", ArrayToLocaleString,
"join", ArrayJoin,
@@ -917,8 +1031,9 @@ function SetupArray() {
"every", ArrayEvery,
"map", ArrayMap,
"indexOf", ArrayIndexOf,
- "lastIndexOf", ArrayLastIndexOf
- ));
+ "lastIndexOf", ArrayLastIndexOf,
+ "reduce", ArrayReduce,
+ "reduceRight", ArrayReduceRight));
// Manipulate the length of some of the functions to meet
// expectations set by ECMA-262 or Mozilla.
@@ -930,7 +1045,9 @@ function SetupArray() {
ArrayMap: 1,
ArrayIndexOf: 1,
ArrayLastIndexOf: 1,
- ArrayPush: 1
+ ArrayPush: 1,
+ ArrayReduce: 1,
+ ArrayReduceRight: 1
});
}
diff --git a/deps/v8/src/assembler.cc b/deps/v8/src/assembler.cc
index ad4b24cc1..ec0e4fd14 100644
--- a/deps/v8/src/assembler.cc
+++ b/deps/v8/src/assembler.cc
@@ -521,10 +521,10 @@ ExternalReference::ExternalReference(Runtime::Function* f)
ExternalReference::ExternalReference(const IC_Utility& ic_utility)
: address_(ic_utility.address()) {}
-
+#ifdef ENABLE_DEBUGGER_SUPPORT
ExternalReference::ExternalReference(const Debug_Address& debug_address)
: address_(debug_address.address()) {}
-
+#endif
ExternalReference::ExternalReference(StatsCounter* counter)
: address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {}
@@ -557,29 +557,71 @@ ExternalReference ExternalReference::address_of_regexp_stack_limit() {
}
-ExternalReference ExternalReference::debug_break() {
- return ExternalReference(FUNCTION_ADDR(Debug::Break));
-}
-
-
ExternalReference ExternalReference::new_space_start() {
return ExternalReference(Heap::NewSpaceStart());
}
+
ExternalReference ExternalReference::new_space_allocation_top_address() {
return ExternalReference(Heap::NewSpaceAllocationTopAddress());
}
+
ExternalReference ExternalReference::heap_always_allocate_scope_depth() {
return ExternalReference(Heap::always_allocate_scope_depth_address());
}
+
ExternalReference ExternalReference::new_space_allocation_limit_address() {
return ExternalReference(Heap::NewSpaceAllocationLimitAddress());
}
+
+static double add_two_doubles(double x, double y) {
+ return x + y;
+}
+
+
+static double sub_two_doubles(double x, double y) {
+ return x - y;
+}
+
+
+static double mul_two_doubles(double x, double y) {
+ return x * y;
+}
+
+
+ExternalReference ExternalReference::double_fp_operation(
+ Token::Value operation) {
+ typedef double BinaryFPOperation(double x, double y);
+ BinaryFPOperation* function = NULL;
+ switch (operation) {
+ case Token::ADD:
+ function = &add_two_doubles;
+ break;
+ case Token::SUB:
+ function = &sub_two_doubles;
+ break;
+ case Token::MUL:
+ function = &mul_two_doubles;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ return ExternalReference(FUNCTION_ADDR(function));
+}
+
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+ExternalReference ExternalReference::debug_break() {
+ return ExternalReference(FUNCTION_ADDR(Debug::Break));
+}
+
+
ExternalReference ExternalReference::debug_step_in_fp_address() {
return ExternalReference(Debug::step_in_fp_addr());
}
+#endif
} } // namespace v8::internal
diff --git a/deps/v8/src/assembler.h b/deps/v8/src/assembler.h
index 49c9b90f0..8abdbc767 100644
--- a/deps/v8/src/assembler.h
+++ b/deps/v8/src/assembler.h
@@ -38,6 +38,7 @@
#include "runtime.h"
#include "top.h"
#include "zone-inl.h"
+#include "token.h"
namespace v8 { namespace internal {
@@ -340,29 +341,15 @@ class RelocIterator: public Malloced {
};
-// A stack-allocated code region logs a name for the code generated
-// while the region is in effect. This information is used by the
-// profiler to categorize ticks within generated code.
-class CodeRegion BASE_EMBEDDED {
- public:
- inline CodeRegion(Assembler* assm, const char *name) : assm_(assm) {
- LOG(BeginCodeRegionEvent(this, assm, name));
- }
- inline ~CodeRegion() {
- LOG(EndCodeRegionEvent(this, assm_));
- }
- private:
- Assembler* assm_;
-};
-
-
//------------------------------------------------------------------------------
// External function
//----------------------------------------------------------------------------
class IC_Utility;
-class Debug_Address;
class SCTableReference;
+#ifdef ENABLE_DEBUGGER_SUPPORT
+class Debug_Address;
+#endif
// An ExternalReference represents a C++ address called from the generated
// code. All references to C++ functions and must be encapsulated in an
@@ -380,7 +367,9 @@ class ExternalReference BASE_EMBEDDED {
explicit ExternalReference(const IC_Utility& ic_utility);
+#ifdef ENABLE_DEBUGGER_SUPPORT
explicit ExternalReference(const Debug_Address& debug_address);
+#endif
explicit ExternalReference(StatsCounter* counter);
@@ -403,9 +392,6 @@ class ExternalReference BASE_EMBEDDED {
// Static variable RegExpStack::limit_address()
static ExternalReference address_of_regexp_stack_limit();
- // Function Debug::Break()
- static ExternalReference debug_break();
-
// Static variable Heap::NewSpaceStart()
static ExternalReference new_space_start();
static ExternalReference heap_always_allocate_scope_depth();
@@ -414,11 +400,18 @@ class ExternalReference BASE_EMBEDDED {
static ExternalReference new_space_allocation_top_address();
static ExternalReference new_space_allocation_limit_address();
- // Used to check if single stepping is enabled in generated code.
- static ExternalReference debug_step_in_fp_address();
+ static ExternalReference double_fp_operation(Token::Value operation);
Address address() const {return address_;}
+#ifdef ENABLE_DEBUGGER_SUPPORT
+ // Function Debug::Break()
+ static ExternalReference debug_break();
+
+ // Used to check if single stepping is enabled in generated code.
+ static ExternalReference debug_step_in_fp_address();
+#endif
+
private:
explicit ExternalReference(void* address)
: address_(reinterpret_cast<Address>(address)) {}
diff --git a/deps/v8/src/ast.cc b/deps/v8/src/ast.cc
index 1a6010a00..d19e3b3e0 100644
--- a/deps/v8/src/ast.cc
+++ b/deps/v8/src/ast.cc
@@ -152,6 +152,27 @@ ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) {
}
+bool ObjectLiteral::IsValidJSON() {
+ int length = properties()->length();
+ for (int i = 0; i < length; i++) {
+ Property* prop = properties()->at(i);
+ if (!prop->value()->IsValidJSON())
+ return false;
+ }
+ return true;
+}
+
+
+bool ArrayLiteral::IsValidJSON() {
+ int length = values()->length();
+ for (int i = 0; i < length; i++) {
+ if (!values()->at(i)->IsValidJSON())
+ return false;
+ }
+ return true;
+}
+
+
void TargetCollector::AddTarget(BreakTarget* target) {
// Add the label to the collector, but discard duplicates.
int length = targets_->length();
diff --git a/deps/v8/src/ast.h b/deps/v8/src/ast.h
index b496816f7..6a2f67105 100644
--- a/deps/v8/src/ast.h
+++ b/deps/v8/src/ast.h
@@ -155,6 +155,7 @@ class Expression: public Node {
public:
virtual Expression* AsExpression() { return this; }
+ virtual bool IsValidJSON() { return false; }
virtual bool IsValidLeftHandSide() { return false; }
// Mark the expression as being compiled as an expression
@@ -625,6 +626,8 @@ class Literal: public Expression {
return handle_.is_identical_to(other->handle_);
}
+ virtual bool IsValidJSON() { return true; }
+
// Identity testers.
bool IsNull() const { return handle_.is_identical_to(Factory::null_value()); }
bool IsTrue() const { return handle_.is_identical_to(Factory::true_value()); }
@@ -653,6 +656,8 @@ class MaterializedLiteral: public Expression {
// constants and simple object and array literals.
bool is_simple() const { return is_simple_; }
+ virtual bool IsValidJSON() { return true; }
+
int depth() const { return depth_; }
private:
@@ -704,6 +709,7 @@ class ObjectLiteral: public MaterializedLiteral {
virtual ObjectLiteral* AsObjectLiteral() { return this; }
virtual void Accept(AstVisitor* v);
+ virtual bool IsValidJSON();
Handle<FixedArray> constant_properties() const {
return constant_properties_;
@@ -751,6 +757,7 @@ class ArrayLiteral: public MaterializedLiteral {
virtual void Accept(AstVisitor* v);
virtual ArrayLiteral* AsArrayLiteral() { return this; }
+ virtual bool IsValidJSON();
Handle<FixedArray> literals() const { return literals_; }
ZoneList<Expression*>* values() const { return values_; }
diff --git a/deps/v8/src/bootstrapper.cc b/deps/v8/src/bootstrapper.cc
index 0a0ed8300..09cf68dea 100644
--- a/deps/v8/src/bootstrapper.cc
+++ b/deps/v8/src/bootstrapper.cc
@@ -530,7 +530,7 @@ void Genesis::CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,
global_context()->function_instance_map()->set_prototype(*empty_function);
// Allocate the function map first and then patch the prototype later
- Handle<Map> empty_fm = Factory::CopyMap(fm);
+ Handle<Map> empty_fm = Factory::CopyMapDropDescriptors(fm);
empty_fm->set_instance_descriptors(*function_map_descriptors);
empty_fm->set_prototype(global_context()->object_function()->prototype());
empty_function->set_map(*empty_fm);
@@ -741,6 +741,19 @@ void Genesis::CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,
global_context()->set_regexp_function(*regexp_fun);
}
+ { // -- J S O N
+ Handle<String> name = Factory::NewStringFromAscii(CStrVector("JSON"));
+ Handle<JSFunction> cons = Factory::NewFunction(
+ name,
+ Factory::the_hole_value());
+ cons->SetInstancePrototype(global_context()->initial_object_prototype());
+ cons->SetInstanceClassName(*name);
+ Handle<JSObject> json_object = Factory::NewJSObject(cons, TENURED);
+ ASSERT(json_object->IsJSObject());
+ SetProperty(global, name, json_object, DONT_ENUM);
+ global_context()->set_json_object(*json_object);
+ }
+
{ // --- arguments_boilerplate_
// Make sure we can recognize argument objects at runtime.
// This is done by introducing an anonymous function with
@@ -820,6 +833,9 @@ void Genesis::CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,
// Initialize the out of memory slot.
global_context()->set_out_of_memory(Heap::false_value());
+
+ // Initialize the data slot.
+ global_context()->set_data(Heap::undefined_value());
}
@@ -832,12 +848,16 @@ bool Genesis::CompileBuiltin(int index) {
bool Genesis::CompileNative(Vector<const char> name, Handle<String> source) {
HandleScope scope;
+#ifdef ENABLE_DEBUGGER_SUPPORT
Debugger::set_compiling_natives(true);
+#endif
bool result =
CompileScriptCached(name, source, &natives_cache, NULL, true);
ASSERT(Top::has_pending_exception() != result);
if (!result) Top::clear_pending_exception();
+#ifdef ENABLE_DEBUGGER_SUPPORT
Debugger::set_compiling_natives(false);
+#endif
return result;
}
@@ -853,9 +873,7 @@ bool Genesis::CompileScriptCached(Vector<const char> name,
// If we can't find the function in the cache, we compile a new
// function and insert it into the cache.
if (!cache->Lookup(name, &boilerplate)) {
-#ifdef DEBUG
- ASSERT(StringShape(*source).IsAsciiRepresentation());
-#endif
+ ASSERT(source->IsAsciiRepresentation());
Handle<String> script_name = Factory::NewStringFromUtf8(name);
boilerplate =
Compiler::Compile(source, script_name, 0, 0, extension, NULL);
@@ -1015,6 +1033,13 @@ bool Genesis::InstallNatives() {
Factory::LookupAsciiSymbol("column_offset"),
proxy_column_offset,
common_attributes);
+ Handle<Proxy> proxy_data = Factory::NewProxy(&Accessors::ScriptData);
+ script_descriptors =
+ Factory::CopyAppendProxyDescriptor(
+ script_descriptors,
+ Factory::LookupAsciiSymbol("data"),
+ proxy_data,
+ common_attributes);
Handle<Proxy> proxy_type = Factory::NewProxy(&Accessors::ScriptType);
script_descriptors =
Factory::CopyAppendProxyDescriptor(
@@ -1030,6 +1055,14 @@ bool Genesis::InstallNatives() {
Factory::LookupAsciiSymbol("line_ends"),
proxy_line_ends,
common_attributes);
+ Handle<Proxy> proxy_context_data =
+ Factory::NewProxy(&Accessors::ScriptContextData);
+ script_descriptors =
+ Factory::CopyAppendProxyDescriptor(
+ script_descriptors,
+ Factory::LookupAsciiSymbol("context_data"),
+ proxy_context_data,
+ common_attributes);
Handle<Map> script_map = Handle<Map>(script_fun->initial_map());
script_map->set_instance_descriptors(*script_descriptors);
@@ -1057,6 +1090,10 @@ bool Genesis::InstallNatives() {
Natives::GetIndex("regexp"),
Top::global_context(),
Handle<Context>(Top::context()->runtime_context()));
+ SetupLazy(Handle<JSObject>(global_context()->json_object()),
+ Natives::GetIndex("json"),
+ Top::global_context(),
+ Handle<Context>(Top::context()->runtime_context()));
} else if (strlen(FLAG_natives_file) != 0) {
// Otherwise install natives from natives file if file exists and
@@ -1132,6 +1169,7 @@ bool Genesis::InstallSpecialObjects() {
Handle<JSObject>(js_global->builtins()), DONT_ENUM);
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Expose the debug global object in global if a name for it is specified.
if (FLAG_expose_debug_as != NULL && strlen(FLAG_expose_debug_as) != 0) {
// If loading fails we just bail out without installing the
@@ -1149,6 +1187,7 @@ bool Genesis::InstallSpecialObjects() {
SetProperty(js_global, debug_string,
Handle<Object>(Debug::debug_context()->global_proxy()), DONT_ENUM);
}
+#endif
return true;
}
@@ -1403,7 +1442,7 @@ void Genesis::MakeFunctionInstancePrototypeWritable() {
Handle<DescriptorArray> function_map_descriptors =
ComputeFunctionInstanceDescriptor(false, true);
- Handle<Map> fm = Factory::CopyMap(Top::function_map());
+ Handle<Map> fm = Factory::CopyMapDropDescriptors(Top::function_map());
fm->set_instance_descriptors(*function_map_descriptors);
Top::context()->global_context()->set_function_map(*fm);
}
@@ -1442,11 +1481,20 @@ void Genesis::BuildSpecialFunctionTable() {
Handle<JSFunction> function =
Handle<JSFunction>(
JSFunction::cast(global->GetProperty(Heap::Array_symbol())));
- Handle<JSObject> prototype =
+ Handle<JSObject> visible_prototype =
Handle<JSObject>(JSObject::cast(function->prototype()));
- AddSpecialFunction(prototype, "pop",
+ // Remember to put push and pop on the hidden prototype if it's there.
+ Handle<JSObject> push_and_pop_prototype;
+ Handle<Object> superproto(visible_prototype->GetPrototype());
+ if (superproto->IsJSObject() &&
+ JSObject::cast(*superproto)->map()->is_hidden_prototype()) {
+ push_and_pop_prototype = Handle<JSObject>::cast(superproto);
+ } else {
+ push_and_pop_prototype = visible_prototype;
+ }
+ AddSpecialFunction(push_and_pop_prototype, "pop",
Handle<Code>(Builtins::builtin(Builtins::ArrayPop)));
- AddSpecialFunction(prototype, "push",
+ AddSpecialFunction(push_and_pop_prototype, "push",
Handle<Code>(Builtins::builtin(Builtins::ArrayPush)));
}
diff --git a/deps/v8/src/builtins.cc b/deps/v8/src/builtins.cc
index c3935f1ae..b27974ffd 100644
--- a/deps/v8/src/builtins.cc
+++ b/deps/v8/src/builtins.cc
@@ -559,6 +559,7 @@ static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
static void Generate_LoadIC_DebugBreak(MacroAssembler* masm) {
Debug::GenerateLoadICDebugBreak(masm);
}
@@ -597,7 +598,7 @@ static void Generate_Return_DebugBreakEntry(MacroAssembler* masm) {
static void Generate_StubNoRegisters_DebugBreak(MacroAssembler* masm) {
Debug::GenerateStubNoRegistersDebugBreak(masm);
}
-
+#endif
Object* Builtins::builtins_[builtin_count] = { NULL, };
const char* Builtins::names_[builtin_count] = { NULL, };
diff --git a/deps/v8/src/builtins.h b/deps/v8/src/builtins.h
index 853c90e83..4e74a3cc4 100644
--- a/deps/v8/src/builtins.h
+++ b/deps/v8/src/builtins.h
@@ -83,6 +83,7 @@ namespace v8 { namespace internal {
V(FunctionApply, BUILTIN, UNINITIALIZED)
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Define list of builtins used by the debugger implemented in assembly.
#define BUILTIN_LIST_DEBUG_A(V) \
V(Return_DebugBreak, BUILTIN, DEBUG_BREAK) \
@@ -93,7 +94,9 @@ namespace v8 { namespace internal {
V(KeyedLoadIC_DebugBreak, KEYED_LOAD_IC, DEBUG_BREAK) \
V(StoreIC_DebugBreak, STORE_IC, DEBUG_BREAK) \
V(KeyedStoreIC_DebugBreak, KEYED_STORE_IC, DEBUG_BREAK)
-
+#else
+#define BUILTIN_LIST_DEBUG_A(V)
+#endif
// Define list of builtins implemented in JavaScript.
#define BUILTINS_LIST_JS(V) \
diff --git a/deps/v8/src/checks.h b/deps/v8/src/checks.h
index 0ff79afbc..b302e5bee 100644
--- a/deps/v8/src/checks.h
+++ b/deps/v8/src/checks.h
@@ -254,7 +254,7 @@ template <int> class StaticAssertionHelper { };
#define ASSERT_TAG_ALIGNED(address) \
- ASSERT((reinterpret_cast<int>(address) & kHeapObjectTagMask) == 0)
+ ASSERT((reinterpret_cast<intptr_t>(address) & kHeapObjectTagMask) == 0)
#define ASSERT_SIZE_TAG_ALIGNED(size) ASSERT((size & kHeapObjectTagMask) == 0)
diff --git a/deps/v8/src/code-stubs.h b/deps/v8/src/code-stubs.h
index d21b0eed2..67634aa13 100644
--- a/deps/v8/src/code-stubs.h
+++ b/deps/v8/src/code-stubs.h
@@ -72,7 +72,7 @@ class CodeStub BASE_EMBEDDED {
protected:
static const int kMajorBits = 5;
- static const int kMinorBits = kBitsPerPointer - kMajorBits - kSmiTagSize;
+ static const int kMinorBits = kBitsPerInt - kSmiTagSize - kMajorBits;
private:
// Generates the assembler code for the stub.
diff --git a/deps/v8/src/codegen.cc b/deps/v8/src/codegen.cc
index edc498d14..40c2583f4 100644
--- a/deps/v8/src/codegen.cc
+++ b/deps/v8/src/codegen.cc
@@ -304,8 +304,10 @@ Handle<JSFunction> CodeGenerator::BuildBoilerplate(FunctionLiteral* node) {
node->is_expression(), false, script_,
node->inferred_name());
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Notify debugger that a new function has been added.
Debugger::OnNewFunction(function);
+#endif
// Set the expected number of properties for instances and return
// the resulting function.
@@ -384,57 +386,69 @@ void CodeGenerator::ProcessDeclarations(ZoneList<Declaration*>* declarations) {
}
-struct InlineRuntimeLUT {
- void (CodeGenerator::*method)(ZoneList<Expression*>*);
- const char* name;
+
+// Special cases: These 'runtime calls' manipulate the current
+// frame and are only used 1 or two places, so we generate them
+// inline instead of generating calls to them. They are used
+// for implementing Function.prototype.call() and
+// Function.prototype.apply().
+CodeGenerator::InlineRuntimeLUT CodeGenerator::kInlineRuntimeLUT[] = {
+ {&CodeGenerator::GenerateIsSmi, "_IsSmi"},
+ {&CodeGenerator::GenerateIsNonNegativeSmi, "_IsNonNegativeSmi"},
+ {&CodeGenerator::GenerateIsArray, "_IsArray"},
+ {&CodeGenerator::GenerateArgumentsLength, "_ArgumentsLength"},
+ {&CodeGenerator::GenerateArgumentsAccess, "_Arguments"},
+ {&CodeGenerator::GenerateValueOf, "_ValueOf"},
+ {&CodeGenerator::GenerateSetValueOf, "_SetValueOf"},
+ {&CodeGenerator::GenerateFastCharCodeAt, "_FastCharCodeAt"},
+ {&CodeGenerator::GenerateObjectEquals, "_ObjectEquals"},
+ {&CodeGenerator::GenerateLog, "_Log"}
};
+CodeGenerator::InlineRuntimeLUT* CodeGenerator::FindInlineRuntimeLUT(
+ Handle<String> name) {
+ const int entries_count =
+ sizeof(kInlineRuntimeLUT) / sizeof(InlineRuntimeLUT);
+ for (int i = 0; i < entries_count; i++) {
+ InlineRuntimeLUT* entry = &kInlineRuntimeLUT[i];
+ if (name->IsEqualTo(CStrVector(entry->name))) {
+ return entry;
+ }
+ }
+ return NULL;
+}
+
+
bool CodeGenerator::CheckForInlineRuntimeCall(CallRuntime* node) {
ZoneList<Expression*>* args = node->arguments();
- // Special cases: These 'runtime calls' manipulate the current
- // frame and are only used 1 or two places, so we generate them
- // inline instead of generating calls to them. They are used
- // for implementing Function.prototype.call() and
- // Function.prototype.apply().
- static const InlineRuntimeLUT kInlineRuntimeLUT[] = {
- {&v8::internal::CodeGenerator::GenerateIsSmi,
- "_IsSmi"},
- {&v8::internal::CodeGenerator::GenerateIsNonNegativeSmi,
- "_IsNonNegativeSmi"},
- {&v8::internal::CodeGenerator::GenerateIsArray,
- "_IsArray"},
- {&v8::internal::CodeGenerator::GenerateArgumentsLength,
- "_ArgumentsLength"},
- {&v8::internal::CodeGenerator::GenerateArgumentsAccess,
- "_Arguments"},
- {&v8::internal::CodeGenerator::GenerateValueOf,
- "_ValueOf"},
- {&v8::internal::CodeGenerator::GenerateSetValueOf,
- "_SetValueOf"},
- {&v8::internal::CodeGenerator::GenerateFastCharCodeAt,
- "_FastCharCodeAt"},
- {&v8::internal::CodeGenerator::GenerateObjectEquals,
- "_ObjectEquals"},
- {&v8::internal::CodeGenerator::GenerateLog,
- "_Log"}
- };
Handle<String> name = node->name();
if (name->length() > 0 && name->Get(0) == '_') {
- for (unsigned i = 0;
- i < sizeof(kInlineRuntimeLUT) / sizeof(InlineRuntimeLUT);
- i++) {
- const InlineRuntimeLUT* entry = kInlineRuntimeLUT + i;
- if (name->IsEqualTo(CStrVector(entry->name))) {
- ((*this).*(entry->method))(args);
- return true;
- }
+ InlineRuntimeLUT* entry = FindInlineRuntimeLUT(name);
+ if (entry != NULL) {
+ ((*this).*(entry->method))(args);
+ return true;
}
}
return false;
}
+bool CodeGenerator::PatchInlineRuntimeEntry(Handle<String> name,
+ const CodeGenerator::InlineRuntimeLUT& new_entry,
+ CodeGenerator::InlineRuntimeLUT* old_entry) {
+ InlineRuntimeLUT* entry = FindInlineRuntimeLUT(name);
+ if (entry == NULL) return false;
+ if (old_entry != NULL) {
+ old_entry->name = entry->name;
+ old_entry->method = entry->method;
+ }
+ entry->name = new_entry.name;
+ entry->method = new_entry.method;
+ return true;
+}
+
+
void CodeGenerator::GenerateFastCaseSwitchStatement(SwitchStatement* node,
int min_index,
int range,
diff --git a/deps/v8/src/codegen.h b/deps/v8/src/codegen.h
index dd43cc0c8..a6cd693eb 100644
--- a/deps/v8/src/codegen.h
+++ b/deps/v8/src/codegen.h
@@ -59,7 +59,9 @@
// ComputeCallInitializeInLoop
// ProcessDeclarations
// DeclareGlobals
+// FindInlineRuntimeLUT
// CheckForInlineRuntimeCall
+// PatchInlineRuntimeEntry
// GenerateFastCaseSwitchStatement
// GenerateFastCaseSwitchCases
// TryGenerateFastCaseSwitchStatement
@@ -71,10 +73,17 @@
// CodeForStatementPosition
// CodeForSourcePosition
-#ifdef ARM
-#include "codegen-arm.h"
-#else
-#include "codegen-ia32.h"
+
+// Mode to overwrite BinaryExpression values.
+enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
+
+
+#if V8_TARGET_ARCH_IA32
+#include "ia32/codegen-ia32.h"
+#elif V8_TARGET_ARCH_X64
+#include "x64/codegen-x64.h"
+#elif V8_TARGET_ARCH_ARM
+#include "arm/codegen-arm.h"
#endif
namespace v8 { namespace internal {
@@ -111,6 +120,9 @@ class DeferredCode: public ZoneObject {
JumpTarget* enter() { return &enter_; }
void BindExit() { exit_.Bind(0); }
void BindExit(Result* result) { exit_.Bind(result, 1); }
+ void BindExit(Result* result0, Result* result1) {
+ exit_.Bind(result0, result1, 2);
+ }
void BindExit(Result* result0, Result* result1, Result* result2) {
exit_.Bind(result0, result1, result2, 3);
}
diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc
index 63fed4a1b..256c69696 100644
--- a/deps/v8/src/compiler.cc
+++ b/deps/v8/src/compiler.cc
@@ -80,8 +80,20 @@ static Handle<Code> MakeCode(FunctionLiteral* literal,
}
+static bool IsValidJSON(FunctionLiteral* lit) {
+ if (!lit->body()->length() == 1)
+ return false;
+ Statement* stmt = lit->body()->at(0);
+ if (stmt->AsExpressionStatement() == NULL)
+ return false;
+ Expression *expr = stmt->AsExpressionStatement()->expression();
+ return expr->IsValidJSON();
+}
+
+
static Handle<JSFunction> MakeFunction(bool is_global,
bool is_eval,
+ bool is_json,
Handle<Script> script,
Handle<Context> context,
v8::Extension* extension,
@@ -92,8 +104,12 @@ static Handle<JSFunction> MakeFunction(bool is_global,
StackGuard guard;
PostponeInterruptsScope postpone;
+ ASSERT(!i::Top::global_context().is_null());
+ script->set_context_data((*i::Top::global_context())->data());
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Notify debugger
Debugger::OnBeforeCompile(script);
+#endif
// Only allow non-global compiles for eval.
ASSERT(is_eval || is_global);
@@ -107,6 +123,19 @@ static Handle<JSFunction> MakeFunction(bool is_global,
return Handle<JSFunction>::null();
}
+ // When parsing JSON we do an ordinary parse and then afterwards
+ // check the AST to ensure it was well-formed. If not we give a
+ // syntax error.
+ if (is_json && !IsValidJSON(lit)) {
+ HandleScope scope;
+ Handle<JSArray> args = Factory::NewJSArray(1);
+ Handle<Object> source(script->source());
+ SetElement(args, 0, source);
+ Handle<Object> result = Factory::NewSyntaxError("invalid_json", args);
+ Top::Throw(*result, NULL);
+ return Handle<JSFunction>::null();
+ }
+
// Measure how long it takes to do the compilation; only take the
// rest of the function into account to avoid overlap with the
// parsing statistics.
@@ -160,8 +189,10 @@ static Handle<JSFunction> MakeFunction(bool is_global,
// the instances of the function.
SetExpectedNofPropertiesFromEstimate(fun, lit->expected_property_count());
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Notify debugger
Debugger::OnAfterCompile(script, fun);
+#endif
return fun;
}
@@ -211,6 +242,7 @@ Handle<JSFunction> Compiler::Compile(Handle<String> source,
// Compile the function and add it to the cache.
result = MakeFunction(true,
false,
+ false,
script,
Handle<Context>::null(),
extension,
@@ -233,7 +265,8 @@ Handle<JSFunction> Compiler::Compile(Handle<String> source,
Handle<JSFunction> Compiler::CompileEval(Handle<String> source,
Handle<Context> context,
int line_offset,
- bool is_global) {
+ bool is_global,
+ bool is_json) {
int source_length = source->length();
Counters::total_eval_size.Increment(source_length);
Counters::total_compile_size.Increment(source_length);
@@ -252,7 +285,13 @@ Handle<JSFunction> Compiler::CompileEval(Handle<String> source,
// Create a script object describing the script to be compiled.
Handle<Script> script = Factory::NewScript(source);
script->set_line_offset(Smi::FromInt(line_offset));
- result = MakeFunction(is_global, true, script, context, NULL, NULL);
+ result = MakeFunction(is_global,
+ true,
+ is_json,
+ script,
+ context,
+ NULL,
+ NULL);
if (!result.is_null()) {
CompilationCache::PutEval(source, context, entry, result);
}
diff --git a/deps/v8/src/compiler.h b/deps/v8/src/compiler.h
index 4f589b7ee..8abe130d8 100644
--- a/deps/v8/src/compiler.h
+++ b/deps/v8/src/compiler.h
@@ -60,7 +60,8 @@ class Compiler : public AllStatic {
static Handle<JSFunction> CompileEval(Handle<String> source,
Handle<Context> context,
int line_offset,
- bool is_global);
+ bool is_global,
+ bool is_json);
// Compile from function info (used for lazy compilation). Returns
// true on success and false if the compilation resulted in a stack
diff --git a/deps/v8/src/contexts.h b/deps/v8/src/contexts.h
index 3c25bd3ea..f56143175 100644
--- a/deps/v8/src/contexts.h
+++ b/deps/v8/src/contexts.h
@@ -64,6 +64,7 @@ enum ContextLookupFlags {
V(OBJECT_FUNCTION_INDEX, JSFunction, object_function) \
V(ARRAY_FUNCTION_INDEX, JSFunction, array_function) \
V(DATE_FUNCTION_INDEX, JSFunction, date_function) \
+ V(JSON_OBJECT_INDEX, JSObject, json_object) \
V(REGEXP_FUNCTION_INDEX, JSFunction, regexp_function) \
V(INITIAL_OBJECT_PROTOTYPE_INDEX, JSObject, initial_object_prototype) \
V(CREATE_DATE_FUN_INDEX, JSFunction, create_date_fun) \
@@ -93,7 +94,8 @@ enum ContextLookupFlags {
V(SCRIPT_FUNCTION_INDEX, JSFunction, script_function) \
V(CONTEXT_EXTENSION_FUNCTION_INDEX, JSFunction, context_extension_function) \
V(OUT_OF_MEMORY_INDEX, Object, out_of_memory) \
- V(MAP_CACHE_INDEX, Object, map_cache)
+ V(MAP_CACHE_INDEX, Object, map_cache) \
+ V(CONTEXT_DATA_INDEX, Object, data)
// JSFunctions are pairs (context, function code), sometimes also called
// closures. A Context object is used to represent function contexts and
@@ -186,6 +188,7 @@ class Context: public FixedArray {
OBJECT_FUNCTION_INDEX,
ARRAY_FUNCTION_INDEX,
DATE_FUNCTION_INDEX,
+ JSON_OBJECT_INDEX,
REGEXP_FUNCTION_INDEX,
CREATE_DATE_FUN_INDEX,
TO_NUMBER_FUN_INDEX,
@@ -211,6 +214,7 @@ class Context: public FixedArray {
CONTEXT_EXTENSION_FUNCTION_INDEX,
OUT_OF_MEMORY_INDEX,
MAP_CACHE_INDEX,
+ CONTEXT_DATA_INDEX,
GLOBAL_CONTEXT_SLOTS
};
diff --git a/deps/v8/src/d8.cc b/deps/v8/src/d8.cc
index 9648168b3..70143c3c0 100644
--- a/deps/v8/src/d8.cc
+++ b/deps/v8/src/d8.cc
@@ -163,6 +163,22 @@ Handle<Value> Shell::Print(const Arguments& args) {
}
+Handle<Value> Shell::Read(const Arguments& args) {
+ if (args.Length() != 1) {
+ return ThrowException(String::New("Bad parameters"));
+ }
+ String::Utf8Value file(args[0]);
+ if (*file == NULL) {
+ return ThrowException(String::New("Error loading file"));
+ }
+ Handle<String> source = ReadFile(*file);
+ if (source.IsEmpty()) {
+ return ThrowException(String::New("Error loading file"));
+ }
+ return source;
+}
+
+
Handle<Value> Shell::Load(const Arguments& args) {
for (int i = 0; i < args.Length(); i++) {
HandleScope handle_scope;
@@ -246,6 +262,7 @@ Handle<Array> Shell::GetCompletions(Handle<String> text, Handle<String> full) {
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
Handle<Object> Shell::DebugMessageDetails(Handle<String> message) {
Context::Scope context_scope(utility_context_);
Handle<Object> global = utility_context_->Global();
@@ -266,6 +283,7 @@ Handle<Value> Shell::DebugCommandToJSONRequest(Handle<String> command) {
Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
return val;
}
+#endif
int32_t* Counter::Bind(const char* name, bool is_histogram) {
@@ -381,6 +399,7 @@ void Shell::Initialize() {
HandleScope scope;
Handle<ObjectTemplate> global_template = ObjectTemplate::New();
global_template->Set(String::New("print"), FunctionTemplate::New(Print));
+ global_template->Set(String::New("read"), FunctionTemplate::New(Read));
global_template->Set(String::New("load"), FunctionTemplate::New(Load));
global_template->Set(String::New("quit"), FunctionTemplate::New(Quit));
global_template->Set(String::New("version"), FunctionTemplate::New(Version));
@@ -406,11 +425,13 @@ void Shell::Initialize() {
global_template->Set(String::New("arguments"),
Utils::ToLocal(arguments_jsarray));
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Install the debugger object in the utility scope
i::Debug::Load();
i::JSObject* debug = i::Debug::debug_context()->global();
utility_context_->Global()->Set(String::New("$debug"),
Utils::ToLocal(&debug));
+#endif
// Run the d8 shell utility script in the utility context
int source_index = i::NativesCollection<i::D8>::GetIndex("d8");
@@ -436,8 +457,10 @@ void Shell::Initialize() {
evaluation_context_ = Context::New(NULL, global_template);
evaluation_context_->SetSecurityToken(Undefined());
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Set the security token of the debug context to allow access.
i::Debug::debug_context()->set_security_token(i::Heap::undefined_value());
+#endif
}
@@ -555,6 +578,8 @@ void ShellThread::Run() {
Handle<ObjectTemplate> global_template = ObjectTemplate::New();
global_template->Set(String::New("print"),
FunctionTemplate::New(Shell::Print));
+ global_template->Set(String::New("read"),
+ FunctionTemplate::New(Shell::Read));
global_template->Set(String::New("load"),
FunctionTemplate::New(Shell::Load));
global_template->Set(String::New("yield"),
@@ -690,6 +715,7 @@ int Shell::Main(int argc, char* argv[]) {
Locker::StartPreemption(preemption_interval);
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Run the remote debugger if requested.
if (i::FLAG_remote_debugger) {
RunRemoteDebugger(i::FLAG_debugger_port);
@@ -705,6 +731,7 @@ int Shell::Main(int argc, char* argv[]) {
if (i::FLAG_debugger && !i::FLAG_debugger_agent) {
v8::Debug::SetDebugEventListener(HandleDebugEvent);
}
+#endif
}
if (run_shell)
RunShell();
diff --git a/deps/v8/src/d8.h b/deps/v8/src/d8.h
index 342a0d2c2..092e3a381 100644
--- a/deps/v8/src/d8.h
+++ b/deps/v8/src/d8.h
@@ -132,13 +132,16 @@ class Shell: public i::AllStatic {
static int Main(int argc, char* argv[]);
static Handle<Array> GetCompletions(Handle<String> text,
Handle<String> full);
+#ifdef ENABLE_DEBUGGER_SUPPORT
static Handle<Object> DebugMessageDetails(Handle<String> message);
static Handle<Value> DebugCommandToJSONRequest(Handle<String> command);
+#endif
static Handle<Value> Print(const Arguments& args);
static Handle<Value> Yield(const Arguments& args);
static Handle<Value> Quit(const Arguments& args);
static Handle<Value> Version(const Arguments& args);
+ static Handle<Value> Read(const Arguments& args);
static Handle<Value> Load(const Arguments& args);
// The OS object on the global object contains methods for performing
// operating system calls:
diff --git a/deps/v8/src/d8.js b/deps/v8/src/d8.js
index e2766d06c..ea2fb4498 100644
--- a/deps/v8/src/d8.js
+++ b/deps/v8/src/d8.js
@@ -653,17 +653,47 @@ DebugRequest.prototype.breakCommandToJSONRequest_ = function(args) {
// Process arguments if any.
if (args && args.length > 0) {
var target = args;
+ var type = 'function';
+ var line;
+ var column;
var condition;
+ var pos;
- var pos = args.indexOf(' ');
+ // Check for breakpoint condition.
+ pos = args.indexOf(' ');
if (pos > 0) {
target = args.substring(0, pos);
condition = args.substring(pos + 1, args.length);
}
+ // Check for script breakpoint (name:line[:column]). If no ':' in break
+ // specification it is considered a function break point.
+ pos = target.indexOf(':');
+ if (pos > 0) {
+ type = 'script';
+ var tmp = target.substring(pos + 1, target.length);
+ target = target.substring(0, pos);
+
+ // Check for both line and column.
+ pos = tmp.indexOf(':');
+ if (pos > 0) {
+ column = parseInt(tmp.substring(pos + 1, tmp.length)) - 1;
+ line = parseInt(tmp.substring(0, pos)) - 1;
+ } else {
+ line = parseInt(tmp) - 1;
+ }
+ } else if (target[0] == '#' && target[target.length - 1] == '#') {
+ type = 'handle';
+ target = target.substring(1, target.length - 1);
+ } else {
+ type = 'function';
+ }
+
request.arguments = {};
- request.arguments.type = 'function';
+ request.arguments.type = type;
request.arguments.target = target;
+ request.arguments.line = line;
+ request.arguments.column = column;
request.arguments.condition = condition;
} else {
throw new Error('Invalid break arguments.');
@@ -721,6 +751,9 @@ DebugRequest.prototype.helpCommand_ = function(args) {
}
print('break location [condition]');
+ print(' break on named function: location is a function name');
+ print(' break on function: location is #<id>#');
+ print(' break on script position: location is name:line[:column]');
print('clear <breakpoint #>');
print('backtrace [from frame #] [to frame #]]');
print('frame <frame #>');
diff --git a/deps/v8/src/date-delay.js b/deps/v8/src/date-delay.js
index 2421e5bae..f06e8b75b 100644
--- a/deps/v8/src/date-delay.js
+++ b/deps/v8/src/date-delay.js
@@ -985,6 +985,25 @@ function DateToGMTString() {
}
+function PadInt(n) {
+ // Format integers to have at least two digits.
+ return n < 10 ? '0' + n : n;
+}
+
+
+function DateToISOString() {
+ return this.getUTCFullYear() + '-' + PadInt(this.getUTCMonth() + 1) +
+ '-' + PadInt(this.getUTCDate()) + 'T' + PadInt(this.getUTCHours()) +
+ ':' + PadInt(this.getUTCMinutes()) + ':' + PadInt(this.getUTCSeconds()) +
+ 'Z';
+}
+
+
+function DateToJSON(key) {
+ return CheckJSONPrimitive(this.toISOString());
+}
+
+
// -------------------------------------------------------------------
function SetupDate() {
@@ -1000,7 +1019,7 @@ function SetupDate() {
// Setup non-enumerable functions of the Date prototype object and
// set their names.
- InstallFunctions($Date.prototype, DONT_ENUM, $Array(
+ InstallFunctionsOnHiddenPrototype($Date.prototype, DONT_ENUM, $Array(
"toString", DateToString,
"toDateString", DateToDateString,
"toTimeString", DateToTimeString,
@@ -1044,7 +1063,9 @@ function SetupDate() {
"toGMTString", DateToGMTString,
"toUTCString", DateToUTCString,
"getYear", DateGetYear,
- "setYear", DateSetYear
+ "setYear", DateSetYear,
+ "toISOString", DateToISOString,
+ "toJSON", DateToJSON
));
}
diff --git a/deps/v8/src/dateparser-inl.h b/deps/v8/src/dateparser-inl.h
index 734c151d2..61a8c72e2 100644
--- a/deps/v8/src/dateparser-inl.h
+++ b/deps/v8/src/dateparser-inl.h
@@ -25,6 +25,9 @@
// (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_DATEPARSER_INL_H_
+#define V8_DATEPARSER_INL_H_
+
namespace v8 { namespace internal {
template <typename Char>
@@ -104,3 +107,5 @@ bool DateParser::Parse(Vector<Char> str, FixedArray* out) {
}
} } // namespace v8::internal
+
+#endif // V8_DATEPARSER_INL_H_
diff --git a/deps/v8/src/debug-agent.cc b/deps/v8/src/debug-agent.cc
index e865e0e29..63f143a79 100644
--- a/deps/v8/src/debug-agent.cc
+++ b/deps/v8/src/debug-agent.cc
@@ -29,16 +29,17 @@
#include "v8.h"
#include "debug-agent.h"
+#ifdef ENABLE_DEBUGGER_SUPPORT
namespace v8 { namespace internal {
-
// Public V8 debugger API message handler function. This function just delegates
// to the debugger agent through it's data parameter.
-void DebuggerAgentMessageHandler(const uint16_t* message, int length,
- void *data) {
- reinterpret_cast<DebuggerAgent*>(data)->DebuggerMessage(message, length);
+void DebuggerAgentMessageHandler(const v8::Debug::Message& message) {
+ DebuggerAgent::instance_->DebuggerMessage(message);
}
+// static
+DebuggerAgent* DebuggerAgent::instance_ = NULL;
// Debugger agent main thread.
void DebuggerAgent::Run() {
@@ -105,7 +106,7 @@ void DebuggerAgent::CreateSession(Socket* client) {
// Create a new session and hook up the debug message handler.
session_ = new DebuggerAgentSession(this, client);
- v8::Debug::SetMessageHandler(DebuggerAgentMessageHandler, this);
+ v8::Debug::SetMessageHandler2(DebuggerAgentMessageHandler);
session_->Start();
}
@@ -123,13 +124,14 @@ void DebuggerAgent::CloseSession() {
}
-void DebuggerAgent::DebuggerMessage(const uint16_t* message, int length) {
+void DebuggerAgent::DebuggerMessage(const v8::Debug::Message& message) {
ScopedLock with(session_access_);
// Forward the message handling to the session.
if (session_ != NULL) {
- session_->DebuggerMessage(Vector<uint16_t>(const_cast<uint16_t*>(message),
- length));
+ v8::String::Value val(message.GetJSON());
+ session_->DebuggerMessage(Vector<uint16_t>(const_cast<uint16_t*>(*val),
+ val.length()));
}
}
@@ -410,5 +412,6 @@ int DebuggerAgentUtil::ReceiveAll(const Socket* conn, char* data, int len) {
return total_received;
}
-
} } // namespace v8::internal
+
+#endif // ENABLE_DEBUGGER_SUPPORT
diff --git a/deps/v8/src/debug-agent.h b/deps/v8/src/debug-agent.h
index 177af0c9e..a3c6025cd 100644
--- a/deps/v8/src/debug-agent.h
+++ b/deps/v8/src/debug-agent.h
@@ -25,15 +25,15 @@
// (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_V8_DEBUG_AGENT_H_
-#define V8_V8_DEBUG_AGENT_H_
+#ifndef V8_DEBUG_AGENT_H_
+#define V8_DEBUG_AGENT_H_
+#ifdef ENABLE_DEBUGGER_SUPPORT
#include "../include/v8-debug.h"
#include "platform.h"
namespace v8 { namespace internal {
-
// Forward decelrations.
class DebuggerAgentSession;
@@ -46,15 +46,21 @@ class DebuggerAgent: public Thread {
: name_(StrDup(name)), port_(port),
server_(OS::CreateSocket()), terminate_(false),
session_access_(OS::CreateMutex()), session_(NULL),
- terminate_now_(OS::CreateSemaphore(0)) {}
- ~DebuggerAgent() { delete server_; }
+ terminate_now_(OS::CreateSemaphore(0)) {
+ ASSERT(instance_ == NULL);
+ instance_ = this;
+ }
+ ~DebuggerAgent() {
+ instance_ = NULL;
+ delete server_;
+ }
void Shutdown();
private:
void Run();
void CreateSession(Socket* socket);
- void DebuggerMessage(const uint16_t* message, int length);
+ void DebuggerMessage(const v8::Debug::Message& message);
void CloseSession();
void OnSessionClosed(DebuggerAgentSession* session);
@@ -66,9 +72,10 @@ class DebuggerAgent: public Thread {
DebuggerAgentSession* session_; // Current active session if any.
Semaphore* terminate_now_; // Semaphore to signal termination.
+ static DebuggerAgent* instance_;
+
friend class DebuggerAgentSession;
- friend void DebuggerAgentMessageHandler(const uint16_t* message, int length,
- void *data);
+ friend void DebuggerAgentMessageHandler(const v8::Debug::Message& message);
DISALLOW_COPY_AND_ASSIGN(DebuggerAgent);
};
@@ -111,7 +118,8 @@ class DebuggerAgentUtil {
static int ReceiveAll(const Socket* conn, char* data, int len);
};
-
} } // namespace v8::internal
-#endif // V8_V8_DEBUG_AGENT_H_
+#endif // ENABLE_DEBUGGER_SUPPORT
+
+#endif // V8_DEBUG_AGENT_H_
diff --git a/deps/v8/src/debug-delay.js b/deps/v8/src/debug-delay.js
index 9944fb330..ff7d6fbd9 100644
--- a/deps/v8/src/debug-delay.js
+++ b/deps/v8/src/debug-delay.js
@@ -977,6 +977,7 @@ CompileEvent.prototype.script = function() {
CompileEvent.prototype.toJSONProtocol = function() {
var o = new ProtocolMessage();
+ o.running = true;
if (this.before_) {
o.event = "beforeCompile";
} else {
@@ -1021,6 +1022,9 @@ function MakeScriptObject_(script, include_source) {
columnOffset: script.columnOffset(),
lineCount: script.lineCount(),
};
+ if (!IS_UNDEFINED(script.data())) {
+ o.data = script.data();
+ }
if (include_source) {
o.source = script.source();
}
@@ -1058,6 +1062,14 @@ function ProtocolMessage(request) {
}
+ProtocolMessage.prototype.setOption = function(name, value) {
+ if (!this.options_) {
+ this.options_ = {};
+ }
+ this.options_[name] = value;
+}
+
+
ProtocolMessage.prototype.failed = function(message) {
this.success = false;
this.message = message;
@@ -1086,7 +1098,7 @@ ProtocolMessage.prototype.toJSONProtocol = function() {
if (this.body) {
json += ',"body":';
// Encode the body part.
- var serializer = MakeMirrorSerializer(true);
+ var serializer = MakeMirrorSerializer(true, this.options_);
if (this.body instanceof Mirror) {
json += serializer.serializeValue(this.body);
} else if (this.body instanceof Array) {
@@ -1130,7 +1142,7 @@ DebugCommandProcessor.prototype.processDebugJSONRequest = function(json_request)
try {
try {
// Convert the JSON string to an object.
- request = %CompileString('(' + json_request + ')', 0)();
+ request = %CompileString('(' + json_request + ')', 0, false)();
// Create an initial response.
response = this.createResponse(request);
@@ -1270,11 +1282,12 @@ DebugCommandProcessor.prototype.setBreakPointRequest_ =
var ignoreCount = request.arguments.ignoreCount;
// Check for legal arguments.
- if (!type || !target) {
+ if (!type || IS_UNDEFINED(target)) {
response.failed('Missing argument "type" or "target"');
return;
}
- if (type != 'function' && type != 'script' && type != 'scriptId') {
+ if (type != 'function' && type != 'handle' &&
+ type != 'script' && type != 'scriptId') {
response.failed('Illegal type "' + type + '"');
return;
}
@@ -1303,6 +1316,20 @@ DebugCommandProcessor.prototype.setBreakPointRequest_ =
// Set function break point.
break_point_number = Debug.setBreakPoint(f, line, column, condition);
+ } else if (type == 'handle') {
+ // Find the object pointed by the specified handle.
+ var handle = parseInt(target, 10);
+ var mirror = LookupMirror(handle);
+ if (!mirror) {
+ return response.failed('Object #' + handle + '# not found');
+ }
+ if (!mirror.isFunction()) {
+ return response.failed('Object #' + handle + '# is not a function');
+ }
+
+ // Set function break point.
+ break_point_number = Debug.setBreakPoint(mirror.value(),
+ line, column, condition);
} else if (type == 'script') {
// set script break point.
break_point_number =
@@ -1547,20 +1574,24 @@ DebugCommandProcessor.prototype.lookupRequest_ = function(request, response) {
}
// Pull out arguments.
- var handle = request.arguments.handle;
+ var handles = request.arguments.handles;
// Check for legal arguments.
- if (IS_UNDEFINED(handle)) {
- return response.failed('Argument "handle" missing');
+ if (IS_UNDEFINED(handles)) {
+ return response.failed('Argument "handles" missing');
}
- // Lookup handle.
- var mirror = LookupMirror(handle);
- if (mirror) {
- response.body = mirror;
- } else {
- return response.failed('Object #' + handle + '# not found');
+ // Lookup handles.
+ var mirrors = {};
+ for (var i = 0; i < handles.length; i++) {
+ var handle = handles[i];
+ var mirror = LookupMirror(handle);
+ if (!mirror) {
+ return response.failed('Object #' + handle + '# not found');
+ }
+ mirrors[handle] = mirror;
}
+ response.body = mirrors;
};
@@ -1657,6 +1688,7 @@ DebugCommandProcessor.prototype.scriptsRequest_ = function(request, response) {
if (!IS_UNDEFINED(request.arguments.includeSource)) {
includeSource = %ToBoolean(request.arguments.includeSource);
+ response.setOption('includeSource', includeSource);
}
}
@@ -1667,22 +1699,7 @@ DebugCommandProcessor.prototype.scriptsRequest_ = function(request, response) {
for (var i = 0; i < scripts.length; i++) {
if (types & ScriptTypeFlag(scripts[i].type)) {
- var script = {};
- if (scripts[i].name) {
- script.name = scripts[i].name;
- }
- script.id = scripts[i].id;
- script.lineOffset = scripts[i].line_offset;
- script.columnOffset = scripts[i].column_offset;
- script.lineCount = scripts[i].lineCount();
- if (includeSource) {
- script.source = scripts[i].source;
- } else {
- script.sourceStart = scripts[i].source.substring(0, 80);
- }
- script.sourceLength = scripts[i].source.length;
- script.type = scripts[i].type;
- response.body.push(script);
+ response.body.push(MakeMirror(scripts[i]));
}
}
};
diff --git a/deps/v8/src/debug.cc b/deps/v8/src/debug.cc
index a4bb04dc6..8422a6710 100644
--- a/deps/v8/src/debug.cc
+++ b/deps/v8/src/debug.cc
@@ -35,12 +35,17 @@
#include "debug.h"
#include "execution.h"
#include "global-handles.h"
+#include "ic.h"
+#include "ic-inl.h"
#include "natives.h"
#include "stub-cache.h"
#include "log.h"
+#include "../include/v8-debug.h"
+
namespace v8 { namespace internal {
+#ifdef ENABLE_DEBUGGER_SUPPORT
static void PrintLn(v8::Local<v8::Value> value) {
v8::Local<v8::String> s = value->ToString();
char* data = NewArray<char>(s->Length() + 1);
@@ -288,14 +293,8 @@ void BreakLocationIterator::SetDebugBreak() {
// Patch the frame exit code with a break point.
SetDebugBreakAtReturn();
} else {
- // Patch the original code with the current address as the current address
- // might have changed by the inline caching since the code was copied.
- original_rinfo()->set_target_address(rinfo()->target_address());
-
- // Patch the code to invoke the builtin debug break function matching the
- // calling convention used by the call site.
- Handle<Code> dbgbrk_code(Debug::FindDebugBreak(rinfo()));
- rinfo()->set_target_address(dbgbrk_code->entry());
+ // Patch the IC call.
+ SetDebugBreakAtIC();
}
ASSERT(IsDebugBreak());
}
@@ -306,8 +305,8 @@ void BreakLocationIterator::ClearDebugBreak() {
// Restore the frame exit code.
ClearDebugBreakAtReturn();
} else {
- // Patch the code to the original invoke.
- rinfo()->set_target_address(original_rinfo()->target_address());
+ // Patch the IC call.
+ ClearDebugBreakAtIC();
}
ASSERT(!IsDebugBreak());
}
@@ -360,6 +359,37 @@ bool BreakLocationIterator::IsDebugBreak() {
}
+void BreakLocationIterator::SetDebugBreakAtIC() {
+ // Patch the original code with the current address as the current address
+ // might have changed by the inline caching since the code was copied.
+ original_rinfo()->set_target_address(rinfo()->target_address());
+
+ RelocInfo::Mode mode = rmode();
+ if (RelocInfo::IsCodeTarget(mode)) {
+ Address target = rinfo()->target_address();
+ Handle<Code> code(Code::GetCodeFromTargetAddress(target));
+
+ // Patch the code to invoke the builtin debug break function matching the
+ // calling convention used by the call site.
+ Handle<Code> dbgbrk_code(Debug::FindDebugBreak(code, mode));
+ rinfo()->set_target_address(dbgbrk_code->entry());
+
+ // For stubs that refer back to an inlined version clear the cached map for
+ // the inlined case to always go through the IC. As long as the break point
+ // is set the patching performed by the runtime system will take place in
+ // the code copy and will therefore have no effect on the running code
+ // keeping it from using the inlined code.
+ if (code->is_keyed_load_stub()) KeyedLoadIC::ClearInlinedVersion(pc());
+ }
+}
+
+
+void BreakLocationIterator::ClearDebugBreakAtIC() {
+ // Patch the code to the original invoke.
+ rinfo()->set_target_address(original_rinfo()->target_address());
+}
+
+
Object* BreakLocationIterator::BreakPointObjects() {
return debug_info_->GetBreakPointObjects(code_position());
}
@@ -1055,48 +1085,42 @@ bool Debug::IsBreakStub(Code* code) {
// Find the builtin to use for invoking the debug break
-Handle<Code> Debug::FindDebugBreak(RelocInfo* rinfo) {
+Handle<Code> Debug::FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode) {
// Find the builtin debug break function matching the calling convention
// used by the call site.
- RelocInfo::Mode mode = rinfo->rmode();
-
- if (RelocInfo::IsCodeTarget(mode)) {
- Address target = rinfo->target_address();
- Code* code = Code::GetCodeFromTargetAddress(target);
- if (code->is_inline_cache_stub()) {
- if (code->is_call_stub()) {
- return ComputeCallDebugBreak(code->arguments_count());
- }
- if (code->is_load_stub()) {
- return Handle<Code>(Builtins::builtin(Builtins::LoadIC_DebugBreak));
- }
- if (code->is_store_stub()) {
- return Handle<Code>(Builtins::builtin(Builtins::StoreIC_DebugBreak));
- }
- if (code->is_keyed_load_stub()) {
- Handle<Code> result =
- Handle<Code>(Builtins::builtin(Builtins::KeyedLoadIC_DebugBreak));
- return result;
- }
- if (code->is_keyed_store_stub()) {
- Handle<Code> result =
- Handle<Code>(Builtins::builtin(Builtins::KeyedStoreIC_DebugBreak));
- return result;
- }
+ if (code->is_inline_cache_stub()) {
+ if (code->is_call_stub()) {
+ return ComputeCallDebugBreak(code->arguments_count());
}
- if (RelocInfo::IsConstructCall(mode)) {
+ if (code->is_load_stub()) {
+ return Handle<Code>(Builtins::builtin(Builtins::LoadIC_DebugBreak));
+ }
+ if (code->is_store_stub()) {
+ return Handle<Code>(Builtins::builtin(Builtins::StoreIC_DebugBreak));
+ }
+ if (code->is_keyed_load_stub()) {
Handle<Code> result =
- Handle<Code>(Builtins::builtin(Builtins::ConstructCall_DebugBreak));
+ Handle<Code>(Builtins::builtin(Builtins::KeyedLoadIC_DebugBreak));
return result;
}
- if (code->kind() == Code::STUB) {
- ASSERT(code->major_key() == CodeStub::CallFunction ||
- code->major_key() == CodeStub::StackCheck);
+ if (code->is_keyed_store_stub()) {
Handle<Code> result =
- Handle<Code>(Builtins::builtin(Builtins::StubNoRegisters_DebugBreak));
+ Handle<Code>(Builtins::builtin(Builtins::KeyedStoreIC_DebugBreak));
return result;
}
}
+ if (RelocInfo::IsConstructCall(mode)) {
+ Handle<Code> result =
+ Handle<Code>(Builtins::builtin(Builtins::ConstructCall_DebugBreak));
+ return result;
+ }
+ if (code->kind() == Code::STUB) {
+ ASSERT(code->major_key() == CodeStub::CallFunction ||
+ code->major_key() == CodeStub::StackCheck);
+ Handle<Code> result =
+ Handle<Code>(Builtins::builtin(Builtins::StubNoRegisters_DebugBreak));
+ return result;
+ }
UNREACHABLE();
return Handle<Code>::null();
@@ -1396,17 +1420,13 @@ Handle<Object> Debugger::event_listener_data_ = Handle<Object>();
bool Debugger::compiling_natives_ = false;
bool Debugger::is_loading_debugger_ = false;
bool Debugger::never_unload_debugger_ = false;
-DebugMessageThread* Debugger::message_thread_ = NULL;
-v8::DebugMessageHandler Debugger::message_handler_ = NULL;
+v8::Debug::MessageHandler2 Debugger::message_handler_ = NULL;
bool Debugger::message_handler_cleared_ = false;
-void* Debugger::message_handler_data_ = NULL;
-v8::DebugHostDispatchHandler Debugger::host_dispatch_handler_ = NULL;
-void* Debugger::host_dispatch_handler_data_ = NULL;
+v8::Debug::HostDispatchHandler Debugger::host_dispatch_handler_ = NULL;
+int Debugger::host_dispatch_micros_ = 100 * 1000;
DebuggerAgent* Debugger::agent_ = NULL;
-LockingMessageQueue Debugger::command_queue_(kQueueInitialSize);
-LockingMessageQueue Debugger::message_queue_(kQueueInitialSize);
+LockingCommandMessageQueue Debugger::command_queue_(kQueueInitialSize);
Semaphore* Debugger::command_received_ = OS::CreateSemaphore(0);
-Semaphore* Debugger::message_received_ = OS::CreateSemaphore(0);
Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name,
@@ -1534,8 +1554,8 @@ void Debugger::OnException(Handle<Object> exception, bool uncaught) {
return;
}
- // Process debug event
- ProcessDebugEvent(v8::Exception, event_data, false);
+ // Process debug event.
+ ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
// Return to continue execution from where the exception was thrown.
}
@@ -1566,8 +1586,10 @@ void Debugger::OnDebugBreak(Handle<Object> break_points_hit,
return;
}
- // Process debug event
- ProcessDebugEvent(v8::Break, event_data, auto_continue);
+ // Process debug event.
+ ProcessDebugEvent(v8::Break,
+ Handle<JSObject>::cast(event_data),
+ auto_continue);
}
@@ -1591,8 +1613,10 @@ void Debugger::OnBeforeCompile(Handle<Script> script) {
return;
}
- // Process debug event
- ProcessDebugEvent(v8::BeforeCompile, event_data, false);
+ // Process debug event.
+ ProcessDebugEvent(v8::BeforeCompile,
+ Handle<JSObject>::cast(event_data),
+ true);
}
@@ -1652,8 +1676,10 @@ void Debugger::OnAfterCompile(Handle<Script> script, Handle<JSFunction> fun) {
if (caught_exception) {
return;
}
- // Process debug event
- ProcessDebugEvent(v8::AfterCompile, event_data, false);
+ // Process debug event.
+ ProcessDebugEvent(v8::AfterCompile,
+ Handle<JSObject>::cast(event_data),
+ true);
}
@@ -1678,12 +1704,12 @@ void Debugger::OnNewFunction(Handle<JSFunction> function) {
return;
}
// Process debug event.
- ProcessDebugEvent(v8::NewFunction, event_data, false);
+ ProcessDebugEvent(v8::NewFunction, Handle<JSObject>::cast(event_data), true);
}
void Debugger::ProcessDebugEvent(v8::DebugEvent event,
- Handle<Object> event_data,
+ Handle<JSObject> event_data,
bool auto_continue) {
HandleScope scope;
@@ -1695,7 +1721,10 @@ void Debugger::ProcessDebugEvent(v8::DebugEvent event,
}
// First notify the message handler if any.
if (message_handler_ != NULL) {
- NotifyMessageHandler(event, exec_state, event_data, auto_continue);
+ NotifyMessageHandler(event,
+ Handle<JSObject>::cast(exec_state),
+ event_data,
+ auto_continue);
}
// Notify registered debug event listener. This can be either a C or a
// JavaScript function.
@@ -1703,11 +1732,11 @@ void Debugger::ProcessDebugEvent(v8::DebugEvent event,
if (event_listener_->IsProxy()) {
// C debug event listener.
Handle<Proxy> callback_obj(Handle<Proxy>::cast(event_listener_));
- v8::DebugEventCallback callback =
- FUNCTION_CAST<v8::DebugEventCallback>(callback_obj->proxy());
+ v8::Debug::EventCallback callback =
+ FUNCTION_CAST<v8::Debug::EventCallback>(callback_obj->proxy());
callback(event,
v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
- v8::Utils::ToLocal(Handle<JSObject>::cast(event_data)),
+ v8::Utils::ToLocal(event_data),
v8::Utils::ToLocal(Handle<Object>::cast(event_listener_data_)));
} else {
// JavaScript debug event listener.
@@ -1718,7 +1747,7 @@ void Debugger::ProcessDebugEvent(v8::DebugEvent event,
const int argc = 4;
Object** argv[argc] = { Handle<Object>(Smi::FromInt(event)).location(),
exec_state.location(),
- event_data.location(),
+ Handle<Object>::cast(event_data).location(),
event_listener_data_.location() };
Handle<Object> result = Execution::TryCall(fun, Top::global(),
argc, argv, &caught_exception);
@@ -1748,25 +1777,26 @@ void Debugger::UnloadDebugger() {
void Debugger::NotifyMessageHandler(v8::DebugEvent event,
- Handle<Object> exec_state,
- Handle<Object> event_data,
+ Handle<JSObject> exec_state,
+ Handle<JSObject> event_data,
bool auto_continue) {
HandleScope scope;
if (!Debug::Load()) return;
// Process the individual events.
- bool interactive = false;
+ bool sendEventMessage = false;
switch (event) {
case v8::Break:
- interactive = true; // Break event is always interactive
+ sendEventMessage = !auto_continue;
break;
case v8::Exception:
- interactive = true; // Exception event is always interactive
+ sendEventMessage = true;
break;
case v8::BeforeCompile:
break;
case v8::AfterCompile:
+ sendEventMessage = true;
break;
case v8::NewFunction:
break;
@@ -1774,8 +1804,25 @@ void Debugger::NotifyMessageHandler(v8::DebugEvent event,
UNREACHABLE();
}
- // Done if not interactive.
- if (!interactive) return;
+ // The debug command interrupt flag might have been set when the command was
+ // added. It should be enough to clear the flag only once while we are in the
+ // debugger.
+ ASSERT(Debug::InDebugger());
+ StackGuard::Continue(DEBUGCOMMAND);
+
+ // Notify the debugger that a debug event has occurred unless auto continue is
+ // active in which case no event is send.
+ if (sendEventMessage) {
+ MessageImpl message = MessageImpl::NewEvent(
+ event,
+ auto_continue,
+ Handle<JSObject>::cast(exec_state),
+ Handle<JSObject>::cast(event_data));
+ InvokeMessageHandler(message);
+ }
+ if (auto_continue && !HasCommands()) {
+ return;
+ }
// Get the DebugCommandProcessor.
v8::Local<v8::Object> api_exec_state =
@@ -1792,45 +1839,30 @@ void Debugger::NotifyMessageHandler(v8::DebugEvent event,
return;
}
- // Notify the debugger that a debug event has occurred unless auto continue is
- // active in which case no event is send.
- if (!auto_continue) {
- bool success = SendEventMessage(event_data);
- if (!success) {
- // If failed to notify debugger just continue running.
- return;
- }
- }
-
// Process requests from the debugger.
while (true) {
// Wait for new command in the queue.
- command_received_->Wait();
-
- // The debug command interrupt flag might have been set when the command was
- // added.
- StackGuard::Continue(DEBUGCOMMAND);
+ if (Debugger::host_dispatch_handler_) {
+ // In case there is a host dispatch - do periodic dispatches.
+ if (!command_received_->Wait(host_dispatch_micros_)) {
+ // Timout expired, do the dispatch.
+ Debugger::host_dispatch_handler_();
+ continue;
+ }
+ } else {
+ // In case there is no host dispatch - just wait.
+ command_received_->Wait();
+ }
// Get the command from the queue.
- Vector<uint16_t> command = command_queue_.Get();
+ CommandMessage command = command_queue_.Get();
Logger::DebugTag("Got request from command queue, in interactive loop.");
if (!Debugger::IsDebuggerActive()) {
+ // Delete command text and user data.
+ command.Dispose();
return;
}
- // Check if the command is a host dispatch.
- if (command[0] == 0) {
- if (Debugger::host_dispatch_handler_) {
- int32_t dispatch = (command[1] << 16) | command[2];
- Debugger::host_dispatch_handler_(reinterpret_cast<void*>(dispatch),
- Debugger::host_dispatch_handler_data_);
- }
- if (auto_continue && !HasCommands()) {
- return;
- }
- continue;
- }
-
// Invoke JavaScript to process the debug request.
v8::Local<v8::String> fun_name;
v8::Local<v8::Function> fun;
@@ -1838,8 +1870,9 @@ void Debugger::NotifyMessageHandler(v8::DebugEvent event,
v8::TryCatch try_catch;
fun_name = v8::String::New("processDebugRequest");
fun = v8::Function::Cast(*cmd_processor->Get(fun_name));
- request = v8::String::New(reinterpret_cast<uint16_t*>(command.start()),
- command.length());
+
+ request = v8::String::New(command.text().start(),
+ command.text().length());
static const int kArgc = 1;
v8::Handle<Value> argv[kArgc] = { request };
v8::Local<v8::Value> response_val = fun->Call(cmd_processor, kArgc, argv);
@@ -1875,13 +1908,16 @@ void Debugger::NotifyMessageHandler(v8::DebugEvent event,
response = try_catch.Exception()->ToString();
}
- // Convert text result to C string.
- v8::String::Value val(response);
- Vector<uint16_t> str(reinterpret_cast<uint16_t*>(*val),
- response->Length());
-
// Return the result.
- SendMessage(str);
+ MessageImpl message = MessageImpl::NewResponse(
+ event,
+ running,
+ Handle<JSObject>::cast(exec_state),
+ Handle<JSObject>::cast(event_data),
+ Handle<String>(Utils::OpenHandle(*response)),
+ command.client_data());
+ InvokeMessageHandler(message);
+ command.Dispose();
// Return from debug event processing if either the VM is put into the
// runnning state (through a continue command) or auto continue is active
@@ -1927,18 +1963,11 @@ void Debugger::SetEventListener(Handle<Object> callback,
}
-void Debugger::SetMessageHandler(v8::DebugMessageHandler handler, void* data,
- bool message_handler_thread) {
+void Debugger::SetMessageHandler(v8::Debug::MessageHandler2 handler) {
ScopedLock with(debugger_access_);
message_handler_ = handler;
- message_handler_data_ = data;
- if (handler != NULL) {
- if (!message_thread_ && message_handler_thread) {
- message_thread_ = new DebugMessageThread();
- message_thread_->Start();
- }
- } else {
+ if (handler == NULL) {
// Indicate that the message handler was recently cleared.
message_handler_cleared_ = true;
@@ -1951,87 +1980,37 @@ void Debugger::SetMessageHandler(v8::DebugMessageHandler handler, void* data,
}
-void Debugger::SetHostDispatchHandler(v8::DebugHostDispatchHandler handler,
- void* data) {
+void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
+ int period) {
host_dispatch_handler_ = handler;
- host_dispatch_handler_data_ = data;
+ host_dispatch_micros_ = period * 1000;
}
// Calls the registered debug message handler. This callback is part of the
-// public API. Messages are kept internally as Vector<uint16_t> strings, which
-// are allocated in various places and deallocated by the calling function
-// sometime after this call.
-void Debugger::InvokeMessageHandler(Vector<uint16_t> message) {
+// public API.
+void Debugger::InvokeMessageHandler(MessageImpl message) {
ScopedLock with(debugger_access_);
if (message_handler_ != NULL) {
- message_handler_(message.start(), message.length(), message_handler_data_);
- }
-}
-
-
-void Debugger::SendMessage(Vector<uint16_t> message) {
- if (message_thread_ == NULL) {
- // If there is no message thread just invoke the message handler from the
- // V8 thread.
- InvokeMessageHandler(message);
- } else {
- // Put a copy of the message coming from V8 on the queue. The new copy of
- // the event string is destroyed by the message thread.
- Vector<uint16_t> message_copy = message.Clone();
- Logger::DebugTag("Put message on event message_queue.");
- message_queue_.Put(message_copy);
- message_received_->Signal();
- }
-}
-
-
-bool Debugger::SendEventMessage(Handle<Object> event_data) {
- v8::HandleScope scope;
- // Call toJSONProtocol on the debug event object.
- v8::Local<v8::Object> api_event_data =
- v8::Utils::ToLocal(Handle<JSObject>::cast(event_data));
- v8::Local<v8::String> fun_name = v8::String::New("toJSONProtocol");
- v8::Local<v8::Function> fun =
- v8::Function::Cast(*api_event_data->Get(fun_name));
- v8::TryCatch try_catch;
- v8::Local<v8::Value> json_event = *fun->Call(api_event_data, 0, NULL);
- v8::Local<v8::String> json_event_string;
- if (!try_catch.HasCaught()) {
- if (!json_event->IsUndefined()) {
- json_event_string = json_event->ToString();
- if (FLAG_trace_debug_json) {
- PrintLn(json_event_string);
- }
- v8::String::Value val(json_event_string);
- Vector<uint16_t> str(reinterpret_cast<uint16_t*>(*val),
- json_event_string->Length());
- SendMessage(str);
- } else {
- SendMessage(Vector<uint16_t>::empty());
- }
- } else {
- PrintLn(try_catch.Exception());
- return false;
+ message_handler_(message);
}
- return true;
}
// Puts a command coming from the public API on the queue. Creates
// a copy of the command string managed by the debugger. Up to this
// point, the command data was managed by the API client. Called
-// by the API client thread. This is where the API client hands off
-// processing of the command to the DebugMessageThread thread.
-// The new copy of the command is destroyed in HandleCommand().
-void Debugger::ProcessCommand(Vector<const uint16_t> command) {
- // Make a copy of the command. Need to cast away const for Clone to work.
- Vector<uint16_t> command_copy =
+// by the API client thread.
+void Debugger::ProcessCommand(Vector<const uint16_t> command,
+ v8::Debug::ClientData* client_data) {
+ // Need to cast away const.
+ CommandMessage message = CommandMessage::New(
Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
- command.length()).Clone();
+ command.length()),
+ client_data);
Logger::DebugTag("Put command on command_queue.");
- command_queue_.Put(command_copy);
+ command_queue_.Put(message);
command_received_->Signal();
// Set the debug command break flag to have the command processed.
@@ -2046,23 +2025,6 @@ bool Debugger::HasCommands() {
}
-void Debugger::ProcessHostDispatch(void* dispatch) {
- // Puts a host dispatch comming from the public API on the queue.
- uint16_t hack[3];
- hack[0] = 0;
- hack[1] = reinterpret_cast<uint32_t>(dispatch) >> 16;
- hack[2] = reinterpret_cast<uint32_t>(dispatch) & 0xFFFF;
- Logger::DebugTag("Put dispatch on command_queue.");
- command_queue_.Put(Vector<uint16_t>(hack, 3).Clone());
- command_received_->Signal();
-
- // Set the debug command break flag to have the host dispatch processed.
- if (!Debug::InDebugger()) {
- StackGuard::DebugCommand();
- }
-}
-
-
bool Debugger::IsDebuggerActive() {
ScopedLock with(debugger_access_);
@@ -2118,47 +2080,152 @@ void Debugger::StopAgent() {
}
-void Debugger::TearDown() {
- if (message_thread_ != NULL) {
- message_thread_->Stop();
- delete message_thread_;
- message_thread_ = NULL;
- }
+MessageImpl MessageImpl::NewEvent(DebugEvent event,
+ bool running,
+ Handle<JSObject> exec_state,
+ Handle<JSObject> event_data) {
+ MessageImpl message(true, event, running,
+ exec_state, event_data, Handle<String>(), NULL);
+ return message;
+}
+
+
+MessageImpl MessageImpl::NewResponse(DebugEvent event,
+ bool running,
+ Handle<JSObject> exec_state,
+ Handle<JSObject> event_data,
+ Handle<String> response_json,
+ v8::Debug::ClientData* client_data) {
+ MessageImpl message(false, event, running,
+ exec_state, event_data, response_json, client_data);
+ return message;
+}
+
+
+MessageImpl::MessageImpl(bool is_event,
+ DebugEvent event,
+ bool running,
+ Handle<JSObject> exec_state,
+ Handle<JSObject> event_data,
+ Handle<String> response_json,
+ v8::Debug::ClientData* client_data)
+ : is_event_(is_event),
+ event_(event),
+ running_(running),
+ exec_state_(exec_state),
+ event_data_(event_data),
+ response_json_(response_json),
+ client_data_(client_data) {}
+
+
+bool MessageImpl::IsEvent() const {
+ return is_event_;
+}
+
+
+bool MessageImpl::IsResponse() const {
+ return !is_event_;
+}
+
+
+DebugEvent MessageImpl::GetEvent() const {
+ return event_;
+}
+
+
+bool MessageImpl::WillStartRunning() const {
+ return running_;
+}
+
+
+v8::Handle<v8::Object> MessageImpl::GetExecutionState() const {
+ return v8::Utils::ToLocal(exec_state_);
+}
+
+
+v8::Handle<v8::Object> MessageImpl::GetEventData() const {
+ return v8::Utils::ToLocal(event_data_);
}
-void DebugMessageThread::Run() {
- // Sends debug events to an installed debugger message callback.
- while (keep_running_) {
- // Wait and Get are paired so that semaphore count equals queue length.
- Debugger::message_received_->Wait();
- Logger::DebugTag("Get message from event message_queue.");
- Vector<uint16_t> message = Debugger::message_queue_.Get();
- if (message.length() > 0) {
- Debugger::InvokeMessageHandler(message);
+v8::Handle<v8::String> MessageImpl::GetJSON() const {
+ v8::HandleScope scope;
+
+ if (IsEvent()) {
+ // Call toJSONProtocol on the debug event object.
+ Handle<Object> fun = GetProperty(event_data_, "toJSONProtocol");
+ if (!fun->IsJSFunction()) {
+ return v8::Handle<v8::String>();
+ }
+ bool caught_exception;
+ Handle<Object> json = Execution::TryCall(Handle<JSFunction>::cast(fun),
+ event_data_,
+ 0, NULL, &caught_exception);
+ if (caught_exception || !json->IsString()) {
+ return v8::Handle<v8::String>();
}
+ return scope.Close(v8::Utils::ToLocal(Handle<String>::cast(json)));
+ } else {
+ return v8::Utils::ToLocal(response_json_);
}
}
-void DebugMessageThread::Stop() {
- keep_running_ = false;
- Debugger::SendMessage(Vector<uint16_t>(NULL, 0));
- Join();
+v8::Handle<v8::Context> MessageImpl::GetEventContext() const {
+ return v8::Utils::ToLocal(Debug::debugger_entry()->GetContext());
+}
+
+
+v8::Debug::ClientData* MessageImpl::GetClientData() const {
+ return client_data_;
}
-MessageQueue::MessageQueue(int size) : start_(0), end_(0), size_(size) {
- messages_ = NewArray<Vector<uint16_t> >(size);
+CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
+ client_data_(NULL) {
}
-MessageQueue::~MessageQueue() {
+CommandMessage::CommandMessage(const Vector<uint16_t>& text,
+ v8::Debug::ClientData* data)
+ : text_(text),
+ client_data_(data) {
+}
+
+
+CommandMessage::~CommandMessage() {
+}
+
+
+void CommandMessage::Dispose() {
+ text_.Dispose();
+ delete client_data_;
+ client_data_ = NULL;
+}
+
+
+CommandMessage CommandMessage::New(const Vector<uint16_t>& command,
+ v8::Debug::ClientData* data) {
+ return CommandMessage(command.Clone(), data);
+}
+
+
+CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0),
+ size_(size) {
+ messages_ = NewArray<CommandMessage>(size);
+}
+
+
+CommandMessageQueue::~CommandMessageQueue() {
+ while (!IsEmpty()) {
+ CommandMessage m = Get();
+ m.Dispose();
+ }
DeleteArray(messages_);
}
-Vector<uint16_t> MessageQueue::Get() {
+CommandMessage CommandMessageQueue::Get() {
ASSERT(!IsEmpty());
int result = start_;
start_ = (start_ + 1) % size_;
@@ -2166,7 +2233,7 @@ Vector<uint16_t> MessageQueue::Get() {
}
-void MessageQueue::Put(const Vector<uint16_t>& message) {
+void CommandMessageQueue::Put(const CommandMessage& message) {
if ((end_ + 1) % size_ == start_) {
Expand();
}
@@ -2175,53 +2242,57 @@ void MessageQueue::Put(const Vector<uint16_t>& message) {
}
-void MessageQueue::Expand() {
- MessageQueue new_queue(size_ * 2);
+void CommandMessageQueue::Expand() {
+ CommandMessageQueue new_queue(size_ * 2);
while (!IsEmpty()) {
new_queue.Put(Get());
}
- Vector<uint16_t>* array_to_free = messages_;
+ CommandMessage* array_to_free = messages_;
*this = new_queue;
new_queue.messages_ = array_to_free;
+ // Make the new_queue empty so that it doesn't call Dispose on any messages.
+ new_queue.start_ = new_queue.end_;
// Automatic destructor called on new_queue, freeing array_to_free.
}
-LockingMessageQueue::LockingMessageQueue(int size) : queue_(size) {
+LockingCommandMessageQueue::LockingCommandMessageQueue(int size)
+ : queue_(size) {
lock_ = OS::CreateMutex();
}
-LockingMessageQueue::~LockingMessageQueue() {
+LockingCommandMessageQueue::~LockingCommandMessageQueue() {
delete lock_;
}
-bool LockingMessageQueue::IsEmpty() const {
+bool LockingCommandMessageQueue::IsEmpty() const {
ScopedLock sl(lock_);
return queue_.IsEmpty();
}
-Vector<uint16_t> LockingMessageQueue::Get() {
+CommandMessage LockingCommandMessageQueue::Get() {
ScopedLock sl(lock_);
- Vector<uint16_t> result = queue_.Get();
- Logger::DebugEvent("Get", result);
+ CommandMessage result = queue_.Get();
+ Logger::DebugEvent("Get", result.text());
return result;
}
-void LockingMessageQueue::Put(const Vector<uint16_t>& message) {
+void LockingCommandMessageQueue::Put(const CommandMessage& message) {
ScopedLock sl(lock_);
queue_.Put(message);
- Logger::DebugEvent("Put", message);
+ Logger::DebugEvent("Put", message.text());
}
-void LockingMessageQueue::Clear() {
+void LockingCommandMessageQueue::Clear() {
ScopedLock sl(lock_);
queue_.Clear();
}
+#endif // ENABLE_DEBUGGER_SUPPORT
} } // namespace v8::internal
diff --git a/deps/v8/src/debug.h b/deps/v8/src/debug.h
index 8822c5025..35336cb1d 100644
--- a/deps/v8/src/debug.h
+++ b/deps/v8/src/debug.h
@@ -25,10 +25,9 @@
// (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_V8_DEBUG_H_
-#define V8_V8_DEBUG_H_
+#ifndef V8_DEBUG_H_
+#define V8_DEBUG_H_
-#include "../include/v8-debug.h"
#include "assembler.h"
#include "code-stubs.h"
#include "debug-agent.h"
@@ -38,6 +37,8 @@
#include "string-stream.h"
#include "v8threads.h"
+#ifdef ENABLE_DEBUGGER_SUPPORT
+#include "../include/v8-debug.h"
namespace v8 { namespace internal {
@@ -131,6 +132,10 @@ class BreakLocationIterator {
private:
void SetDebugBreak();
void ClearDebugBreak();
+
+ void SetDebugBreakAtIC();
+ void ClearDebugBreakAtIC();
+
bool IsDebugBreakAtReturn();
void SetDebugBreakAtReturn();
void ClearDebugBreakAtReturn();
@@ -204,7 +209,7 @@ class Debug {
static bool IsBreakStub(Code* code);
// Find the builtin to use for invoking the debug break
- static Handle<Code> FindDebugBreak(RelocInfo* rinfo);
+ static Handle<Code> FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode);
static Handle<Object> GetSourceBreakLocations(
Handle<SharedFunctionInfo> shared);
@@ -396,48 +401,117 @@ class Debug {
};
-// A Queue of Vector<uint16_t> objects. A thread-safe version is
-// LockingMessageQueue, based on this class.
-class MessageQueue BASE_EMBEDDED {
+// Message delivered to the message handler callback. This is either a debugger
+// event or the response to a command.
+class MessageImpl: public v8::Debug::Message {
+ public:
+ // Create a message object for a debug event.
+ static MessageImpl NewEvent(DebugEvent event,
+ bool running,
+ Handle<JSObject> exec_state,
+ Handle<JSObject> event_data);
+
+ // Create a message object for the response to a debug command.
+ static MessageImpl NewResponse(DebugEvent event,
+ bool running,
+ Handle<JSObject> exec_state,
+ Handle<JSObject> event_data,
+ Handle<String> response_json,
+ v8::Debug::ClientData* client_data);
+
+ // Implementation of interface v8::Debug::Message.
+ virtual bool IsEvent() const;
+ virtual bool IsResponse() const;
+ virtual DebugEvent GetEvent() const;
+ virtual bool WillStartRunning() const;
+ virtual v8::Handle<v8::Object> GetExecutionState() const;
+ virtual v8::Handle<v8::Object> GetEventData() const;
+ virtual v8::Handle<v8::String> GetJSON() const;
+ virtual v8::Handle<v8::Context> GetEventContext() const;
+ virtual v8::Debug::ClientData* GetClientData() const;
+
+ private:
+ MessageImpl(bool is_event,
+ DebugEvent event,
+ bool running,
+ Handle<JSObject> exec_state,
+ Handle<JSObject> event_data,
+ Handle<String> response_json,
+ v8::Debug::ClientData* client_data);
+
+ bool is_event_; // Does this message represent a debug event?
+ DebugEvent event_; // Debug event causing the break.
+ bool running_; // Will the VM start running after this event?
+ Handle<JSObject> exec_state_; // Current execution state.
+ Handle<JSObject> event_data_; // Data associated with the event.
+ Handle<String> response_json_; // Response JSON if message holds a response.
+ v8::Debug::ClientData* client_data_; // Client data passed with the request.
+};
+
+
+// Message send by user to v8 debugger or debugger output message.
+// In addition to command text it may contain a pointer to some user data
+// which are expected to be passed along with the command reponse to message
+// handler.
+class CommandMessage {
public:
- explicit MessageQueue(int size);
- ~MessageQueue();
+ static CommandMessage New(const Vector<uint16_t>& command,
+ v8::Debug::ClientData* data);
+ CommandMessage();
+ ~CommandMessage();
+
+ // Deletes user data and disposes of the text.
+ void Dispose();
+ Vector<uint16_t> text() const { return text_; }
+ v8::Debug::ClientData* client_data() const { return client_data_; }
+ private:
+ CommandMessage(const Vector<uint16_t>& text,
+ v8::Debug::ClientData* data);
+
+ Vector<uint16_t> text_;
+ v8::Debug::ClientData* client_data_;
+};
+
+// A Queue of CommandMessage objects. A thread-safe version is
+// LockingCommandMessageQueue, based on this class.
+class CommandMessageQueue BASE_EMBEDDED {
+ public:
+ explicit CommandMessageQueue(int size);
+ ~CommandMessageQueue();
bool IsEmpty() const { return start_ == end_; }
- Vector<uint16_t> Get();
- void Put(const Vector<uint16_t>& message);
+ CommandMessage Get();
+ void Put(const CommandMessage& message);
void Clear() { start_ = end_ = 0; } // Queue is empty after Clear().
private:
// Doubles the size of the message queue, and copies the messages.
void Expand();
- Vector<uint16_t>* messages_;
+ CommandMessage* messages_;
int start_;
int end_;
int size_; // The size of the queue buffer. Queue can hold size-1 messages.
};
-// LockingMessageQueue is a thread-safe circular buffer of Vector<uint16_t>
-// messages. The message data is not managed by LockingMessageQueue.
+// LockingCommandMessageQueue is a thread-safe circular buffer of CommandMessage
+// messages. The message data is not managed by LockingCommandMessageQueue.
// Pointers to the data are passed in and out. Implemented by adding a
-// Mutex to MessageQueue. Includes logging of all puts and gets.
-class LockingMessageQueue BASE_EMBEDDED {
+// Mutex to CommandMessageQueue. Includes logging of all puts and gets.
+class LockingCommandMessageQueue BASE_EMBEDDED {
public:
- explicit LockingMessageQueue(int size);
- ~LockingMessageQueue();
+ explicit LockingCommandMessageQueue(int size);
+ ~LockingCommandMessageQueue();
bool IsEmpty() const;
- Vector<uint16_t> Get();
- void Put(const Vector<uint16_t>& message);
+ CommandMessage Get();
+ void Put(const CommandMessage& message);
void Clear();
private:
- MessageQueue queue_;
+ CommandMessageQueue queue_;
Mutex* lock_;
- DISALLOW_COPY_AND_ASSIGN(LockingMessageQueue);
+ DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue);
};
-class DebugMessageThread;
-
class Debugger {
public:
static void DebugRequest(const uint16_t* json_request, int length);
@@ -465,36 +539,27 @@ class Debugger {
Handle<JSFunction> fun);
static void OnNewFunction(Handle<JSFunction> fun);
static void ProcessDebugEvent(v8::DebugEvent event,
- Handle<Object> event_data,
+ Handle<JSObject> event_data,
bool auto_continue);
static void NotifyMessageHandler(v8::DebugEvent event,
- Handle<Object> exec_state,
- Handle<Object> event_data,
+ Handle<JSObject> exec_state,
+ Handle<JSObject> event_data,
bool auto_continue);
static void SetEventListener(Handle<Object> callback, Handle<Object> data);
- static void SetMessageHandler(v8::DebugMessageHandler handler, void* data,
- bool message_handler_thread);
- static void TearDown();
- static void SetHostDispatchHandler(v8::DebugHostDispatchHandler handler,
- void* data);
+ static void SetMessageHandler(v8::Debug::MessageHandler2 handler);
+ static void SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
+ int period);
// Invoke the message handler function.
- static void InvokeMessageHandler(Vector< uint16_t> message);
-
- // Send a message to the message handler eiher through the message thread or
- // directly.
- static void SendMessage(Vector<uint16_t> message);
-
- // Send the JSON message for a debug event.
- static bool SendEventMessage(Handle<Object> event_data);
+ static void InvokeMessageHandler(MessageImpl message);
// Add a debugger command to the command queue.
- static void ProcessCommand(Vector<const uint16_t> command);
+ static void ProcessCommand(Vector<const uint16_t> command,
+ v8::Debug::ClientData* client_data = NULL);
// Check whether there are commands in the command queue.
static bool HasCommands();
- static void ProcessHostDispatch(void* dispatch);
static Handle<Object> Call(Handle<JSFunction> fun,
Handle<Object> data,
bool* pending_exception);
@@ -537,42 +602,18 @@ class Debugger {
static bool compiling_natives_; // Are we compiling natives?
static bool is_loading_debugger_; // Are we loading the debugger?
static bool never_unload_debugger_; // Can we unload the debugger?
- static DebugMessageThread* message_thread_;
- static v8::DebugMessageHandler message_handler_;
+ static v8::Debug::MessageHandler2 message_handler_;
static bool message_handler_cleared_; // Was message handler cleared?
- static void* message_handler_data_;
- static v8::DebugHostDispatchHandler host_dispatch_handler_;
- static void* host_dispatch_handler_data_;
+ static v8::Debug::HostDispatchHandler host_dispatch_handler_;
+ static int host_dispatch_micros_;
static DebuggerAgent* agent_;
static const int kQueueInitialSize = 4;
- static LockingMessageQueue command_queue_;
- static LockingMessageQueue message_queue_;
+ static LockingCommandMessageQueue command_queue_;
static Semaphore* command_received_; // Signaled for each command received.
- static Semaphore* message_received_; // Signalled for each message send.
friend class EnterDebugger;
- friend class DebugMessageThread;
-};
-
-
-// Thread to read messages from the message queue and invoke the debug message
-// handler in another thread as the V8 thread. This thread is started if the
-// registration of the debug message handler requested to be called in a thread
-// seperate from the V8 thread.
-class DebugMessageThread: public Thread {
- public:
- DebugMessageThread() : keep_running_(true) {}
- virtual ~DebugMessageThread() {}
-
- // Main function of DebugMessageThread thread.
- void Run();
- void Stop();
-
- private:
- bool keep_running_;
- DISALLOW_COPY_AND_ASSIGN(DebugMessageThread);
};
@@ -646,6 +687,9 @@ class EnterDebugger BASE_EMBEDDED {
// Check whether there are any JavaScript frames on the stack.
inline bool HasJavaScriptFrames() { return has_js_frames_; }
+ // Get the active context from before entering the debugger.
+ inline Handle<Context> GetContext() { return save_.context(); }
+
private:
EnterDebugger* prev_; // Previous debugger entry if entered recursively.
JavaScriptFrameIterator it_;
@@ -719,4 +763,6 @@ class Debug_Address {
} } // namespace v8::internal
-#endif // V8_V8_DEBUG_H_
+#endif // ENABLE_DEBUGGER_SUPPORT
+
+#endif // V8_DEBUG_H_
diff --git a/deps/v8/src/execution.cc b/deps/v8/src/execution.cc
index 03017d017..32dde9e4c 100644
--- a/deps/v8/src/execution.cc
+++ b/deps/v8/src/execution.cc
@@ -32,10 +32,12 @@
#include "api.h"
#include "codegen-inl.h"
-#ifdef ARM
-#include "simulator-arm.h"
-#else // ia32
-#include "simulator-ia32.h"
+#if V8_TARGET_ARCH_IA32
+#include "ia32/simulator-ia32.h"
+#elif V8_TARGET_ARCH_X64
+#include "x64/simulator-x64.h"
+#elif V8_TARGET_ARCH_ARM
+#include "arm/simulator-arm.h"
#endif
#include "debug.h"
@@ -305,6 +307,7 @@ void StackGuard::Preempt() {
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
bool StackGuard::IsDebugBreak() {
ExecutionAccess access;
return thread_local_.interrupt_flags_ & DEBUGBREAK;
@@ -331,7 +334,7 @@ void StackGuard::DebugCommand() {
set_limits(kInterruptLimit, access);
}
}
-
+#endif
void StackGuard::Continue(InterruptFlag after_what) {
ExecutionAccess access;
@@ -539,6 +542,7 @@ static Object* RuntimePreempt() {
ContextSwitcher::PreemptionReceived();
+#ifdef ENABLE_DEBUGGER_SUPPORT
if (Debug::InDebugger()) {
// If currently in the debugger don't do any actual preemption but record
// that preemption occoured while in the debugger.
@@ -548,11 +552,17 @@ static Object* RuntimePreempt() {
v8::Unlocker unlocker;
Thread::YieldCPU();
}
+#else
+ // Perform preemption.
+ v8::Unlocker unlocker;
+ Thread::YieldCPU();
+#endif
return Heap::undefined_value();
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
Object* Execution::DebugBreakHelper() {
// Just continue if breaks are disabled.
if (Debug::disable_break()) {
@@ -598,12 +608,14 @@ Object* Execution::DebugBreakHelper() {
// Return to continue execution.
return Heap::undefined_value();
}
-
+#endif
Object* Execution::HandleStackGuardInterrupt() {
+#ifdef ENABLE_DEBUGGER_SUPPORT
if (StackGuard::IsDebugBreak() || StackGuard::IsDebugCommand()) {
DebugBreakHelper();
}
+#endif
if (StackGuard::IsPreempted()) RuntimePreempt();
if (StackGuard::IsInterrupted()) {
// interrupt
@@ -626,7 +638,7 @@ v8::Handle<v8::FunctionTemplate> GCExtension::GetNativeFunction(
v8::Handle<v8::Value> GCExtension::GC(const v8::Arguments& args) {
// All allocation spaces other than NEW_SPACE have the same effect.
- Heap::CollectGarbage(0, OLD_DATA_SPACE);
+ Heap::CollectAllGarbage();
return v8::Undefined();
}
diff --git a/deps/v8/src/execution.h b/deps/v8/src/execution.h
index 6531572e4..6f2f68922 100644
--- a/deps/v8/src/execution.h
+++ b/deps/v8/src/execution.h
@@ -118,8 +118,9 @@ class Execution : public AllStatic {
Handle<JSFunction> fun,
Handle<Object> pos,
Handle<Object> is_global);
-
+#ifdef ENABLE_DEBUGGER_SUPPORT
static Object* DebugBreakHelper();
+#endif
// If the stack guard is triggered, but it is not an actual
// stack overflow, then handle the interruption accordingly.
@@ -158,11 +159,13 @@ class StackGuard BASE_EMBEDDED {
static void Preempt();
static bool IsInterrupted();
static void Interrupt();
- static bool IsDebugBreak();
+ static void Continue(InterruptFlag after_what);
+#ifdef ENABLE_DEBUGGER_SUPPORT
static void DebugBreak();
- static bool IsDebugCommand();
static void DebugCommand();
- static void Continue(InterruptFlag after_what);
+ static bool IsDebugBreak();
+ static bool IsDebugCommand();
+#endif
private:
// You should hold the ExecutionAccess lock when calling this method.
diff --git a/deps/v8/src/factory.cc b/deps/v8/src/factory.cc
index e29c84d2b..4b0b7f51f 100644
--- a/deps/v8/src/factory.cc
+++ b/deps/v8/src/factory.cc
@@ -167,14 +167,17 @@ Handle<Script> Factory::NewScript(Handle<String> source) {
Heap::SetLastScriptId(Smi::FromInt(id));
// Create and initialize script object.
+ Handle<Proxy> wrapper = Factory::NewProxy(0, TENURED);
Handle<Script> script = Handle<Script>::cast(NewStruct(SCRIPT_TYPE));
script->set_source(*source);
script->set_name(Heap::undefined_value());
script->set_id(Heap::last_script_id());
script->set_line_offset(Smi::FromInt(0));
script->set_column_offset(Smi::FromInt(0));
+ script->set_data(Heap::undefined_value());
+ script->set_context_data(Heap::undefined_value());
script->set_type(Smi::FromInt(SCRIPT_TYPE_NORMAL));
- script->set_wrapper(*Factory::NewProxy(0, TENURED));
+ script->set_wrapper(*wrapper);
script->set_line_ends(Heap::undefined_value());
return script;
@@ -207,14 +210,14 @@ Handle<JSObject> Factory::NewFunctionPrototype(Handle<JSFunction> function) {
}
-Handle<Map> Factory::CopyMap(Handle<Map> src) {
- CALL_HEAP_FUNCTION(src->Copy(), Map);
+Handle<Map> Factory::CopyMapDropDescriptors(Handle<Map> src) {
+ CALL_HEAP_FUNCTION(src->CopyDropDescriptors(), Map);
}
Handle<Map> Factory::CopyMap(Handle<Map> src,
int extra_inobject_properties) {
- Handle<Map> copy = CopyMap(src);
+ Handle<Map> copy = CopyMapDropDescriptors(src);
// Check that we do not overflow the instance size when adding the
// extra inobject properties.
int instance_size_delta = extra_inobject_properties * kPointerSize;
@@ -671,6 +674,7 @@ Handle<Object> Factory::ToObject(Handle<Object> object,
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
Handle<DebugInfo> Factory::NewDebugInfo(Handle<SharedFunctionInfo> shared) {
// Get the original code of the function.
Handle<Code> code(shared->code());
@@ -700,6 +704,7 @@ Handle<DebugInfo> Factory::NewDebugInfo(Handle<SharedFunctionInfo> shared) {
return debug_info;
}
+#endif
Handle<JSObject> Factory::NewArgumentsObject(Handle<Object> callee,
diff --git a/deps/v8/src/factory.h b/deps/v8/src/factory.h
index 2564c3c54..6ac2706ec 100644
--- a/deps/v8/src/factory.h
+++ b/deps/v8/src/factory.h
@@ -153,7 +153,7 @@ class Factory : public AllStatic {
static Handle<JSObject> NewFunctionPrototype(Handle<JSFunction> function);
- static Handle<Map> CopyMap(Handle<Map> map);
+ static Handle<Map> CopyMapDropDescriptors(Handle<Map> map);
// Copy the map adding more inobject properties if possible without
// overflowing the instance size.
@@ -310,8 +310,9 @@ class Factory : public AllStatic {
uint32_t key,
Handle<Object> value);
+#ifdef ENABLE_DEBUGGER_SUPPORT
static Handle<DebugInfo> NewDebugInfo(Handle<SharedFunctionInfo> shared);
-
+#endif
// Return a map using the map cache in the global context.
// The key the an ordered set of property names.
diff --git a/deps/v8/src/frames-inl.h b/deps/v8/src/frames-inl.h
index cb03e2fd7..bf46f6bf7 100644
--- a/deps/v8/src/frames-inl.h
+++ b/deps/v8/src/frames-inl.h
@@ -29,12 +29,14 @@
#define V8_FRAMES_INL_H_
#include "frames.h"
-#ifdef ARM
-#include "frames-arm.h"
-#else
-#include "frames-ia32.h"
-#endif
+#if V8_TARGET_ARCH_IA32
+#include "ia32/frames-ia32.h"
+#elif V8_TARGET_ARCH_X64
+#include "x64/frames-x64.h"
+#elif V8_TARGET_ARCH_ARM
+#include "arm/frames-arm.h"
+#endif
namespace v8 { namespace internal {
diff --git a/deps/v8/src/frames.cc b/deps/v8/src/frames.cc
index 88c723d69..1eedbf640 100644
--- a/deps/v8/src/frames.cc
+++ b/deps/v8/src/frames.cc
@@ -647,10 +647,10 @@ void EntryFrame::Iterate(ObjectVisitor* v) const {
handler->Iterate(v);
// Make sure that there's the entry frame does not contain more than
// one stack handler.
- if (kDebug) {
- it.Advance();
- ASSERT(it.done());
- }
+#ifdef DEBUG
+ it.Advance();
+ ASSERT(it.done());
+#endif
}
diff --git a/deps/v8/src/func-name-inferrer.cc b/deps/v8/src/func-name-inferrer.cc
index ef0c7dbb4..75f7a9937 100644
--- a/deps/v8/src/func-name-inferrer.cc
+++ b/deps/v8/src/func-name-inferrer.cc
@@ -63,11 +63,12 @@ Handle<String> FuncNameInferrer::MakeNameFromStackHelper(int pos,
}
-void FuncNameInferrer::MaybeInferFunctionName() {
- if (func_to_infer_ != NULL) {
- func_to_infer_->set_inferred_name(MakeNameFromStack());
- func_to_infer_ = NULL;
+void FuncNameInferrer::InferFunctionsNames() {
+ Handle<String> 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_.Rewind(0);
}
diff --git a/deps/v8/src/func-name-inferrer.h b/deps/v8/src/func-name-inferrer.h
index 9dcf7c59f..d8270c364 100644
--- a/deps/v8/src/func-name-inferrer.h
+++ b/deps/v8/src/func-name-inferrer.h
@@ -45,7 +45,7 @@ class FuncNameInferrer BASE_EMBEDDED {
FuncNameInferrer() :
entries_stack_(10),
names_stack_(5),
- func_to_infer_(NULL),
+ funcs_to_infer_(4),
dot_(Factory::NewStringFromAscii(CStrVector("."))) {
}
@@ -57,39 +57,34 @@ class FuncNameInferrer BASE_EMBEDDED {
entries_stack_.Add(names_stack_.length());
}
- void Leave() {
- ASSERT(IsOpen());
- names_stack_.Rewind(entries_stack_.RemoveLast());
- }
-
void PushName(Handle<String> name) {
if (IsOpen()) {
names_stack_.Add(name);
}
}
- void SetFuncToInfer(FunctionLiteral* func_to_infer) {
+ void AddFunction(FunctionLiteral* func_to_infer) {
if (IsOpen()) {
- // If we encounter another function literal after already having
- // encountered one, the second one replaces the first.
- func_to_infer_ = func_to_infer;
+ funcs_to_infer_.Add(func_to_infer);
}
}
void InferAndLeave() {
ASSERT(IsOpen());
- MaybeInferFunctionName();
- Leave();
+ if (!funcs_to_infer_.is_empty()) {
+ InferFunctionsNames();
+ }
+ names_stack_.Rewind(entries_stack_.RemoveLast());
}
private:
Handle<String> MakeNameFromStack();
Handle<String> MakeNameFromStackHelper(int pos, Handle<String> prev);
- void MaybeInferFunctionName();
+ void InferFunctionsNames();
List<int> entries_stack_;
List<Handle<String> > names_stack_;
- FunctionLiteral* func_to_infer_;
+ List<FunctionLiteral*> funcs_to_infer_;
Handle<String> dot_;
DISALLOW_COPY_AND_ASSIGN(FuncNameInferrer);
diff --git a/deps/v8/src/global-handles.cc b/deps/v8/src/global-handles.cc
index c2194fc89..46b7db322 100644
--- a/deps/v8/src/global-handles.cc
+++ b/deps/v8/src/global-handles.cc
@@ -258,7 +258,7 @@ void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) {
}
-void GlobalHandles::MarkWeakRoots(WeakSlotCallback f) {
+void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) {
for (Node* current = head_; current != NULL; current = current->next()) {
if (current->state_ == Node::WEAK) {
if (f(&current->object_)) {
diff --git a/deps/v8/src/global-handles.h b/deps/v8/src/global-handles.h
index c5f44503b..e6e9de1d1 100644
--- a/deps/v8/src/global-handles.h
+++ b/deps/v8/src/global-handles.h
@@ -98,8 +98,9 @@ class GlobalHandles : public AllStatic {
// Iterates over all weak roots in heap.
static void IterateWeakRoots(ObjectVisitor* v);
- // Mark the weak pointers based on the callback.
- static void MarkWeakRoots(WeakSlotCallback f);
+ // Find all weak handles satisfying the callback predicate, mark
+ // them as pending.
+ static void IdentifyWeakHandles(WeakSlotCallback f);
// Add an object group.
// Should only used in GC callback function before a collection.
diff --git a/deps/v8/src/globals.h b/deps/v8/src/globals.h
index 1579c3dfd..a0b5ac363 100644
--- a/deps/v8/src/globals.h
+++ b/deps/v8/src/globals.h
@@ -28,27 +28,27 @@
#ifndef V8_GLOBALS_H_
#define V8_GLOBALS_H_
-// -----------------------------------------------------------------------------
-// Types
-// Visual Studio C++ is missing the stdint.h header file. Instead we define
-// standard integer types for Windows here.
-
-#ifdef _MSC_VER
-typedef signed char int8_t;
-typedef unsigned char uint8_t;
-typedef short int16_t; // NOLINT
-typedef unsigned short uint16_t; // NOLINT
-typedef int int32_t;
-typedef unsigned int uint32_t;
-typedef __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-#else // _MSC_VER
-#include <stdint.h> // for intptr_t
-#endif // _MSC_VER
-
-
namespace v8 { namespace internal {
+// Processor architecture detection. For more info on what's defined, see:
+// http://msdn.microsoft.com/en-us/library/b0084kay.aspx
+// http://www.agner.org/optimize/calling_conventions.pdf
+// or with gcc, run: "echo | gcc -E -dM -"
+#if defined(_M_X64) || defined(__x86_64__)
+#define V8_HOST_ARCH_X64 1
+#define V8_HOST_ARCH_64_BIT 1
+#define V8_HOST_CAN_READ_UNALIGNED 1
+#elif defined(_M_IX86) || defined(__i386__)
+#define V8_HOST_ARCH_IA32 1
+#define V8_HOST_ARCH_32_BIT 1
+#define V8_HOST_CAN_READ_UNALIGNED 1
+#elif defined(__ARMEL__)
+#define V8_HOST_ARCH_ARM 1
+#define V8_HOST_ARCH_32_BIT 1
+#else
+#error Your architecture was not detected as supported by v8
+#endif
+
// Support for alternative bool type. This is only enabled if the code is
// compiled with USE_MYBOOL defined. This catches some nasty type bugs.
// For instance, 'bool b = "false";' results in b == true! This is a hidden
@@ -69,58 +69,73 @@ typedef unsigned int __my_bool__;
typedef uint8_t byte;
typedef byte* Address;
+// Define our own macros for writing 64-bit constants. This is less fragile
+// than defining __STDC_CONSTANT_MACROS before including <stdint.h>, and it
+// works on compilers that don't have it (like MSVC).
+#if V8_HOST_ARCH_64_BIT
+#ifdef _MSC_VER
+#define V8_UINT64_C(x) (x ## UI64)
+#define V8_INT64_C(x) (x ## I64)
+#define V8_PTR_PREFIX "ll"
+#else
+#define V8_UINT64_C(x) (x ## UL)
+#define V8_INT64_C(x) (x ## L)
+#define V8_PTR_PREFIX "l"
+#endif
+#else // V8_HOST_ARCH_64_BIT
+#define V8_PTR_PREFIX ""
+#endif
+
+#define V8PRIp V8_PTR_PREFIX "x"
+
// Code-point values in Unicode 4.0 are 21 bits wide.
typedef uint16_t uc16;
-typedef signed int uc32;
-
-#ifndef ARM
-#define CAN_READ_UNALIGNED 1
-#endif
+typedef int32_t uc32;
// -----------------------------------------------------------------------------
// Constants
-#ifdef DEBUG
-const bool kDebug = true;
-#else
-const bool kDebug = false;
-#endif // DEBUG
-
const int KB = 1024;
const int MB = KB * KB;
const int GB = KB * KB * KB;
const int kMaxInt = 0x7FFFFFFF;
const int kMinInt = -kMaxInt - 1;
+const uint32_t kMaxUInt32 = 0xFFFFFFFFu;
+
const int kCharSize = sizeof(char); // NOLINT
const int kShortSize = sizeof(short); // NOLINT
const int kIntSize = sizeof(int); // NOLINT
const int kDoubleSize = sizeof(double); // NOLINT
const int kPointerSize = sizeof(void*); // NOLINT
+#if V8_HOST_ARCH_64_BIT
+const int kPointerSizeLog2 = 3;
+#else
const int kPointerSizeLog2 = 2;
+#endif
-const int kObjectAlignmentBits = 2;
-const int kObjectAlignmentMask = (1 << kObjectAlignmentBits) - 1;
-const int kObjectAlignment = 1 << kObjectAlignmentBits;
+const int kObjectAlignmentBits = kPointerSizeLog2;
+const intptr_t kObjectAlignmentMask = (1 << kObjectAlignmentBits) - 1;
+const intptr_t kObjectAlignment = 1 << kObjectAlignmentBits;
// Tag information for HeapObject.
const int kHeapObjectTag = 1;
const int kHeapObjectTagSize = 2;
-const int kHeapObjectTagMask = (1 << kHeapObjectTagSize) - 1;
+const intptr_t kHeapObjectTagMask = (1 << kHeapObjectTagSize) - 1;
// Tag information for Smi.
const int kSmiTag = 0;
const int kSmiTagSize = 1;
-const int kSmiTagMask = (1 << kSmiTagSize) - 1;
+const intptr_t kSmiTagMask = (1 << kSmiTagSize) - 1;
// Tag information for Failure.
const int kFailureTag = 3;
const int kFailureTagSize = 2;
-const int kFailureTagMask = (1 << kFailureTagSize) - 1;
+const intptr_t kFailureTagMask = (1 << kFailureTagSize) - 1;
const int kBitsPerByte = 8;
@@ -129,11 +144,21 @@ const int kBitsPerPointer = kPointerSize * kBitsPerByte;
const int kBitsPerInt = kIntSize * kBitsPerByte;
-// Zap-value: The value used for zapping dead objects. Should be a recognizable
-// illegal heap object pointer.
+// Zap-value: The value used for zapping dead objects.
+// Should be a recognizable hex value tagged as a heap object pointer.
+#ifdef V8_HOST_ARCH_64_BIT
+const Address kZapValue =
+ reinterpret_cast<Address>(V8_UINT64_C(0xdeadbeedbeadbeed));
+const Address kHandleZapValue =
+ reinterpret_cast<Address>(V8_UINT64_C(0x1baddead0baddead));
+const Address kFromSpaceZapValue =
+ reinterpret_cast<Address>(V8_UINT64_C(0x1beefdad0beefdad));
+#else
const Address kZapValue = reinterpret_cast<Address>(0xdeadbeed);
const Address kHandleZapValue = reinterpret_cast<Address>(0xbaddead);
const Address kFromSpaceZapValue = reinterpret_cast<Address>(0xbeefdad);
+#endif
+
// -----------------------------------------------------------------------------
// Forward declarations for frequently used classes
@@ -146,7 +171,6 @@ class Assembler;
class BreakableStatement;
class Code;
class CodeGenerator;
-class CodeRegion;
class CodeStub;
class Context;
class Debug;
@@ -377,13 +401,13 @@ enum StateTag {
// Testers for test.
#define HAS_SMI_TAG(value) \
- ((reinterpret_cast<int>(value) & kSmiTagMask) == kSmiTag)
+ ((reinterpret_cast<intptr_t>(value) & kSmiTagMask) == kSmiTag)
#define HAS_FAILURE_TAG(value) \
- ((reinterpret_cast<int>(value) & kFailureTagMask) == kFailureTag)
+ ((reinterpret_cast<intptr_t>(value) & kFailureTagMask) == kFailureTag)
#define HAS_HEAP_OBJECT_TAG(value) \
- ((reinterpret_cast<int>(value) & kHeapObjectTagMask) == kHeapObjectTag)
+ ((reinterpret_cast<intptr_t>(value) & kHeapObjectTagMask) == kHeapObjectTag)
// OBJECT_SIZE_ALIGN returns the value aligned HeapObject size
#define OBJECT_SIZE_ALIGN(value) \
@@ -492,7 +516,7 @@ F FUNCTION_CAST(Address addr) {
// exception'.
//
// Bit_cast uses the memcpy exception to move the bits from a variable of one
-// type o a variable of another type. Of course the end result is likely to
+// type of a variable of another type. Of course the end result is likely to
// be implementation dependent. Most compilers (gcc-4.2 and MSVC 2005)
// will completely optimize bit_cast away.
//
diff --git a/deps/v8/src/handles.cc b/deps/v8/src/handles.cc
index 60d82362f..773483d60 100644
--- a/deps/v8/src/handles.cc
+++ b/deps/v8/src/handles.cc
@@ -212,10 +212,20 @@ Handle<Object> SetProperty(Handle<Object> object,
}
-Handle<Object> IgnoreAttributesAndSetLocalProperty(Handle<JSObject> object,
- Handle<String> key,
- Handle<Object> value,
- PropertyAttributes attributes) {
+Handle<Object> ForceSetProperty(Handle<JSObject> object,
+ Handle<Object> key,
+ Handle<Object> value,
+ PropertyAttributes attributes) {
+ CALL_HEAP_FUNCTION(
+ Runtime::ForceSetObjectProperty(object, key, value, attributes), Object);
+}
+
+
+Handle<Object> IgnoreAttributesAndSetLocalProperty(
+ Handle<JSObject> object,
+ Handle<String> key,
+ Handle<Object> value,
+ PropertyAttributes attributes) {
CALL_HEAP_FUNCTION(object->
IgnoreAttributesAndSetLocalProperty(*key, *value, attributes), Object);
}
@@ -491,17 +501,6 @@ Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object) {
break;
}
- // Compute the property keys.
- content = UnionOfKeys(content, GetEnumPropertyKeys(current));
-
- // Add the property keys from the interceptor.
- if (current->HasNamedInterceptor()) {
- v8::Handle<v8::Array> result =
- GetKeysForNamedInterceptor(object, current);
- if (!result.IsEmpty())
- content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
- }
-
// Compute the element keys.
Handle<FixedArray> element_keys =
Factory::NewFixedArray(current->NumberOfEnumElements());
@@ -515,6 +514,17 @@ Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object) {
if (!result.IsEmpty())
content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
}
+
+ // Compute the property keys.
+ content = UnionOfKeys(content, GetEnumPropertyKeys(current));
+
+ // Add the property keys from the interceptor.
+ if (current->HasNamedInterceptor()) {
+ v8::Handle<v8::Array> result =
+ GetKeysForNamedInterceptor(object, current);
+ if (!result.IsEmpty())
+ content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
+ }
}
}
return content;
@@ -549,7 +559,7 @@ Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object) {
index++;
}
}
- (*storage)->SortPairs(*sort_array);
+ (*storage)->SortPairs(*sort_array, sort_array->length());
Handle<FixedArray> bridge_storage =
Factory::NewFixedArray(DescriptorArray::kEnumCacheBridgeLength);
DescriptorArray* desc = object->map()->instance_descriptors();
@@ -617,9 +627,9 @@ OptimizedObjectForAddingMultipleProperties::
}
-void LoadLazy(Handle<JSFunction> fun, bool* pending_exception) {
+void LoadLazy(Handle<JSObject> obj, bool* pending_exception) {
HandleScope scope;
- Handle<FixedArray> info(FixedArray::cast(fun->shared()->lazy_load_data()));
+ Handle<FixedArray> info(FixedArray::cast(obj->map()->constructor()));
int index = Smi::cast(info->get(0))->value();
ASSERT(index >= 0);
Handle<Context> compile_context(Context::cast(info->get(1)));
@@ -651,6 +661,7 @@ void LoadLazy(Handle<JSFunction> fun, bool* pending_exception) {
// We shouldn't get here if compiling the script failed.
ASSERT(!boilerplate.is_null());
+#ifdef ENABLE_DEBUGGER_SUPPORT
// When the debugger running in its own context touches lazy loaded
// functions loading can be triggered. In that case ensure that the
// execution of the boilerplate is in the correct context.
@@ -659,30 +670,43 @@ void LoadLazy(Handle<JSFunction> fun, bool* pending_exception) {
Top::context() == *Debug::debug_context()) {
Top::set_context(*compile_context);
}
+#endif
// Reset the lazy load data before running the script to make sure
// not to get recursive lazy loading.
- fun->shared()->set_lazy_load_data(Heap::undefined_value());
+ obj->map()->set_needs_loading(false);
+ obj->map()->set_constructor(info->get(3));
// Run the script.
Handle<JSFunction> script_fun(
Factory::NewFunctionFromBoilerplate(boilerplate, function_context));
Execution::Call(script_fun, receiver, 0, NULL, pending_exception);
- // If lazy loading failed, restore the unloaded state of fun.
- if (*pending_exception) fun->shared()->set_lazy_load_data(*info);
+ // If lazy loading failed, restore the unloaded state of obj.
+ if (*pending_exception) {
+ obj->map()->set_needs_loading(true);
+ obj->map()->set_constructor(*info);
+ }
}
-void SetupLazy(Handle<JSFunction> fun,
+void SetupLazy(Handle<JSObject> obj,
int index,
Handle<Context> compile_context,
Handle<Context> function_context) {
- Handle<FixedArray> arr = Factory::NewFixedArray(3);
+ Handle<FixedArray> arr = Factory::NewFixedArray(4);
arr->set(0, Smi::FromInt(index));
arr->set(1, *compile_context); // Compile in this context
arr->set(2, *function_context); // Set function context to this
- fun->shared()->set_lazy_load_data(*arr);
+ arr->set(3, obj->map()->constructor()); // Remember the constructor
+ Handle<Map> old_map(obj->map());
+ Handle<Map> new_map = Factory::CopyMapDropTransitions(old_map);
+ obj->set_map(*new_map);
+ new_map->set_needs_loading(true);
+ // Store the lazy loading info in the constructor field. We'll
+ // reestablish the constructor from the fixed array after loading.
+ new_map->set_constructor(*arr);
+ ASSERT(!obj->IsLoaded());
}
} } // namespace v8::internal
diff --git a/deps/v8/src/handles.h b/deps/v8/src/handles.h
index c8e534eec..652d6c70e 100644
--- a/deps/v8/src/handles.h
+++ b/deps/v8/src/handles.h
@@ -196,6 +196,11 @@ Handle<Object> SetProperty(Handle<Object> object,
Handle<Object> value,
PropertyAttributes attributes);
+Handle<Object> ForceSetProperty(Handle<JSObject> object,
+ Handle<Object> key,
+ Handle<Object> value,
+ PropertyAttributes attributes);
+
Handle<Object> IgnoreAttributesAndSetLocalProperty(Handle<JSObject> object,
Handle<String> key,
Handle<Object> value,
@@ -296,11 +301,11 @@ bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag);
bool CompileLazyInLoop(Handle<JSFunction> function, ClearExceptionFlag flag);
// These deal with lazily loaded properties.
-void SetupLazy(Handle<JSFunction> fun,
+void SetupLazy(Handle<JSObject> obj,
int index,
Handle<Context> compile_context,
Handle<Context> function_context);
-void LoadLazy(Handle<JSFunction> fun, bool* pending_exception);
+void LoadLazy(Handle<JSObject> obj, bool* pending_exception);
class NoHandleAllocation BASE_EMBEDDED {
public:
diff --git a/deps/v8/src/heap-inl.h b/deps/v8/src/heap-inl.h
index 6090dd48c..86165ee1b 100644
--- a/deps/v8/src/heap-inl.h
+++ b/deps/v8/src/heap-inl.h
@@ -251,11 +251,11 @@ void Heap::SetLastScriptId(Object* last_script_id) {
__object__ = FUNCTION_CALL; \
} \
if (!__object__->IsFailure()) RETURN_VALUE; \
- if (__object__->IsOutOfMemoryFailure()) { \
+ if (__object__->IsOutOfMemoryFailure() || \
+ __object__->IsRetryAfterGC()) { \
/* TODO(1181417): Fix this. */ \
v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_2"); \
} \
- ASSERT(!__object__->IsRetryAfterGC()); \
RETURN_EMPTY; \
} while (false)
diff --git a/deps/v8/src/heap.cc b/deps/v8/src/heap.cc
index 7a8b7288d..6d600152e 100644
--- a/deps/v8/src/heap.cc
+++ b/deps/v8/src/heap.cc
@@ -538,7 +538,7 @@ class ScavengeVisitor: public ObjectVisitor {
// Shared state read by the scavenge collector and set by ScavengeObject.
-static Address promoted_top = NULL;
+static Address promoted_rear = NULL;
#ifdef DEBUG
@@ -554,24 +554,34 @@ class VerifyNonPointerSpacePointersVisitor: public ObjectVisitor {
}
}
};
-#endif
-void Heap::Scavenge() {
-#ifdef DEBUG
- if (FLAG_enable_slow_asserts) {
- VerifyNonPointerSpacePointersVisitor v;
- HeapObjectIterator it(code_space_);
- while (it.has_next()) {
- HeapObject* object = it.next();
- if (object->IsCode()) {
- Code::cast(object)->ConvertICTargetsFromAddressToObject();
- }
+
+static void VerifyNonPointerSpacePointers() {
+ // Verify that there are no pointers to new space in spaces where we
+ // do not expect them.
+ VerifyNonPointerSpacePointersVisitor v;
+ HeapObjectIterator code_it(Heap::code_space());
+ while (code_it.has_next()) {
+ HeapObject* object = code_it.next();
+ if (object->IsCode()) {
+ Code::cast(object)->ConvertICTargetsFromAddressToObject();
+ object->Iterate(&v);
+ Code::cast(object)->ConvertICTargetsFromObjectToAddress();
+ } else {
+ // If we find non-code objects in code space (e.g., free list
+ // nodes) we want to verify them as well.
object->Iterate(&v);
- if (object->IsCode()) {
- Code::cast(object)->ConvertICTargetsFromObjectToAddress();
- }
}
}
+
+ HeapObjectIterator data_it(Heap::old_data_space());
+ while (data_it.has_next()) data_it.next()->Iterate(&v);
+}
+#endif
+
+void Heap::Scavenge() {
+#ifdef DEBUG
+ if (FLAG_enable_slow_asserts) VerifyNonPointerSpacePointers();
#endif
gc_state_ = SCAVENGE;
@@ -596,72 +606,70 @@ void Heap::Scavenge() {
new_space_.Flip();
new_space_.ResetAllocationInfo();
- // We need to sweep newly copied objects which can be in either the to space
- // or the old space. For to space objects, we use a mark. Newly copied
- // objects lie between the mark and the allocation top. For objects
- // promoted to old space, we write their addresses downward from the top of
- // the new space. Sweeping newly promoted objects requires an allocation
- // pointer and a mark. Note that the allocation pointer 'top' actually
- // moves downward from the high address in the to space.
+ // We need to sweep newly copied objects which can be either in the
+ // to space or promoted to the old generation. For to-space
+ // objects, we treat the bottom of the to space as a queue. Newly
+ // copied and unswept objects lie between a 'front' mark and the
+ // allocation pointer.
+ //
+ // Promoted objects can go into various old-generation spaces, and
+ // can be allocated internally in the spaces (from the free list).
+ // We treat the top of the to space as a queue of addresses of
+ // promoted objects. The addresses of newly promoted and unswept
+ // objects lie between a 'front' mark and a 'rear' mark that is
+ // updated as a side effect of promoting an object.
//
- // There is guaranteed to be enough room at the top of the to space for the
- // addresses of promoted objects: every object promoted frees up its size in
- // bytes from the top of the new space, and objects are at least one pointer
- // in size. Using the new space to record promoted addresses makes the
- // scavenge collector agnostic to the allocation strategy (eg, linear or
- // free-list) used in old space.
- Address new_mark = new_space_.ToSpaceLow();
- Address promoted_mark = new_space_.ToSpaceHigh();
- promoted_top = new_space_.ToSpaceHigh();
+ // There is guaranteed to be enough room at the top of the to space
+ // for the addresses of promoted objects: every object promoted
+ // frees up its size in bytes from the top of the new space, and
+ // objects are at least one pointer in size.
+ Address new_space_front = new_space_.ToSpaceLow();
+ Address promoted_front = new_space_.ToSpaceHigh();
+ promoted_rear = new_space_.ToSpaceHigh();
ScavengeVisitor scavenge_visitor;
// Copy roots.
IterateRoots(&scavenge_visitor);
- // Copy objects reachable from the old generation. By definition, there
- // are no intergenerational pointers in code or data spaces.
+ // Copy objects reachable from weak pointers.
+ GlobalHandles::IterateWeakRoots(&scavenge_visitor);
+
+ // Copy objects reachable from the old generation. By definition,
+ // there are no intergenerational pointers in code or data spaces.
IterateRSet(old_pointer_space_, &ScavengePointer);
IterateRSet(map_space_, &ScavengePointer);
lo_space_->IterateRSet(&ScavengePointer);
- bool has_processed_weak_pointers = false;
-
- while (true) {
- ASSERT(new_mark <= new_space_.top());
- ASSERT(promoted_mark >= promoted_top);
+ do {
+ ASSERT(new_space_front <= new_space_.top());
+ ASSERT(promoted_front >= promoted_rear);
+
+ // The addresses new_space_front and new_space_.top() define a
+ // queue of unprocessed copied objects. Process them until the
+ // queue is empty.
+ while (new_space_front < new_space_.top()) {
+ HeapObject* object = HeapObject::FromAddress(new_space_front);
+ object->Iterate(&scavenge_visitor);
+ new_space_front += object->Size();
+ }
- // Copy objects reachable from newly copied objects.
- while (new_mark < new_space_.top() || promoted_mark > promoted_top) {
- // Sweep newly copied objects in the to space. The allocation pointer
- // can change during sweeping.
- Address previous_top = new_space_.top();
- SemiSpaceIterator new_it(new_space(), new_mark);
- while (new_it.has_next()) {
- new_it.next()->Iterate(&scavenge_visitor);
- }
- new_mark = previous_top;
-
- // Sweep newly copied objects in the old space. The promotion 'top'
- // pointer could change during sweeping.
- previous_top = promoted_top;
- for (Address current = promoted_mark - kPointerSize;
- current >= previous_top;
- current -= kPointerSize) {
- HeapObject* object = HeapObject::cast(Memory::Object_at(current));
- object->Iterate(&scavenge_visitor);
- UpdateRSet(object);
- }
- promoted_mark = previous_top;
+ // The addresses promoted_front and promoted_rear define a queue
+ // of unprocessed addresses of promoted objects. Process them
+ // until the queue is empty.
+ while (promoted_front > promoted_rear) {
+ promoted_front -= kPointerSize;
+ HeapObject* object =
+ HeapObject::cast(Memory::Object_at(promoted_front));
+ object->Iterate(&scavenge_visitor);
+ UpdateRSet(object);
}
- if (has_processed_weak_pointers) break; // We are done.
- // Copy objects reachable from weak pointers.
- GlobalHandles::IterateWeakRoots(&scavenge_visitor);
- has_processed_weak_pointers = true;
- }
+ // Take another spin if there are now unswept objects in new space
+ // (there are currently no more unswept promoted objects).
+ } while (new_space_front < new_space_.top());
// Set age mark.
- new_space_.set_age_mark(new_mark);
+ new_space_.set_age_mark(new_space_.top());
LOG(ResourceEvent("scavenge", "end"));
@@ -882,8 +890,8 @@ void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) {
if (target_space == Heap::old_pointer_space_) {
// Record the object's address at the top of the to space, to allow
// it to be swept by the scavenger.
- promoted_top -= kPointerSize;
- Memory::Object_at(promoted_top) = *p;
+ promoted_rear -= kPointerSize;
+ Memory::Object_at(promoted_rear) = *p;
} else {
#ifdef DEBUG
// Objects promoted to the data space should not have pointers to
@@ -939,6 +947,7 @@ Object* Heap::AllocateMap(InstanceType instance_type, int instance_size) {
map->set_code_cache(empty_fixed_array());
map->set_unused_property_fields(0);
map->set_bit_field(0);
+ map->set_bit_field2(0);
return map;
}
@@ -1409,7 +1418,6 @@ Object* Heap::AllocateSharedFunctionInfo(Object* name) {
share->set_formal_parameter_count(0);
share->set_instance_class_name(Object_symbol());
share->set_function_data(undefined_value());
- share->set_lazy_load_data(undefined_value());
share->set_script(undefined_value());
share->set_start_position_and_type(0);
share->set_debug_info(undefined_value());
@@ -1423,8 +1431,8 @@ Object* Heap::AllocateConsString(String* first,
int first_length = first->length();
int second_length = second->length();
int length = first_length + second_length;
- bool is_ascii = StringShape(first).IsAsciiRepresentation()
- && StringShape(second).IsAsciiRepresentation();
+ bool is_ascii = first->IsAsciiRepresentation()
+ && second->IsAsciiRepresentation();
// If the resulting string is small make a flat string.
if (length < String::kMinNonFlatLength) {
@@ -1484,15 +1492,15 @@ Object* Heap::AllocateSlicedString(String* buffer,
Map* map;
if (length <= String::kMaxShortStringSize) {
- map = StringShape(buffer).IsAsciiRepresentation() ?
+ map = buffer->IsAsciiRepresentation() ?
short_sliced_ascii_string_map() :
short_sliced_string_map();
} else if (length <= String::kMaxMediumStringSize) {
- map = StringShape(buffer).IsAsciiRepresentation() ?
+ map = buffer->IsAsciiRepresentation() ?
medium_sliced_ascii_string_map() :
medium_sliced_string_map();
} else {
- map = StringShape(buffer).IsAsciiRepresentation() ?
+ map = buffer->IsAsciiRepresentation() ?
long_sliced_ascii_string_map() :
long_sliced_string_map();
}
@@ -1524,7 +1532,7 @@ Object* Heap::AllocateSubString(String* buffer,
buffer->TryFlatten();
}
- Object* result = StringShape(buffer).IsAsciiRepresentation()
+ Object* result = buffer->IsAsciiRepresentation()
? AllocateRawAsciiString(length)
: AllocateRawTwoByteString(length);
if (result->IsFailure()) return result;
@@ -2679,7 +2687,10 @@ void Heap::IterateStrongRoots(ObjectVisitor* v) {
SYNCHRONIZE_TAG("bootstrapper");
Top::Iterate(v);
SYNCHRONIZE_TAG("top");
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
Debug::Iterate(v);
+#endif
SYNCHRONIZE_TAG("debug");
CompilationCache::Iterate(v);
SYNCHRONIZE_TAG("compilationcache");
diff --git a/deps/v8/src/assembler-ia32-inl.h b/deps/v8/src/ia32/assembler-ia32-inl.h
index c5213a7dc..a3d24b276 100644
--- a/deps/v8/src/assembler-ia32-inl.h
+++ b/deps/v8/src/ia32/assembler-ia32-inl.h
@@ -34,8 +34,8 @@
// A light-weight IA32 Assembler.
-#ifndef V8_ASSEMBLER_IA32_INL_H_
-#define V8_ASSEMBLER_IA32_INL_H_
+#ifndef V8_IA32_ASSEMBLER_IA32_INL_H_
+#define V8_IA32_ASSEMBLER_IA32_INL_H_
#include "cpu.h"
@@ -299,4 +299,4 @@ Operand::Operand(int32_t disp, RelocInfo::Mode rmode) {
} } // namespace v8::internal
-#endif // V8_ASSEMBLER_IA32_INL_H_
+#endif // V8_IA32_ASSEMBLER_IA32_INL_H_
diff --git a/deps/v8/src/assembler-ia32.cc b/deps/v8/src/ia32/assembler-ia32.cc
index 8549261a8..3a2d3f82d 100644
--- a/deps/v8/src/assembler-ia32.cc
+++ b/deps/v8/src/ia32/assembler-ia32.cc
@@ -283,6 +283,10 @@ bool Operand::is_reg(Register reg) const {
*pc_++ = (x)
+#ifdef GENERATED_CODE_COVERAGE
+static void InitCoverageLog();
+#endif
+
// spare_buffer_
static byte* spare_buffer_ = NULL;
@@ -315,9 +319,11 @@ Assembler::Assembler(void* buffer, int buffer_size) {
// Clear the buffer in debug mode unless it was provided by the
// caller in which case we can't be sure it's okay to overwrite
// existing code in it; see CodePatcher::CodePatcher(...).
- if (kDebug && own_buffer_) {
+#ifdef DEBUG
+ if (own_buffer_) {
memset(buffer_, 0xCC, buffer_size); // int3
}
+#endif
// setup buffer pointers
ASSERT(buffer_ != NULL);
@@ -329,6 +335,9 @@ Assembler::Assembler(void* buffer, int buffer_size) {
current_position_ = RelocInfo::kNoPosition;
written_statement_position_ = current_statement_position_;
written_position_ = current_position_;
+#ifdef GENERATED_CODE_COVERAGE
+ InitCoverageLog();
+#endif
}
@@ -2073,9 +2082,9 @@ void Assembler::GrowBuffer() {
// Clear the buffer in debug mode. Use 'int3' instructions to make
// sure to get into problems if we ever run uninitialized code.
- if (kDebug) {
- memset(desc.buffer, 0xCC, desc.buffer_size);
- }
+#ifdef DEBUG
+ memset(desc.buffer, 0xCC, desc.buffer_size);
+#endif
// copy the data
int pc_delta = desc.buffer - buffer_;
@@ -2202,4 +2211,30 @@ void Assembler::WriteInternalReference(int position, const Label& bound_label) {
long_at_put(position, label_loc);
}
+
+#ifdef GENERATED_CODE_COVERAGE
+static FILE* coverage_log = NULL;
+
+
+static void InitCoverageLog() {
+ char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
+ if (file_name != NULL) {
+ coverage_log = fopen(file_name, "aw+");
+ }
+}
+
+
+void LogGeneratedCodeCoverage(const char* file_line) {
+ const char* return_address = (&file_line)[-1];
+ char* push_insn = const_cast<char*>(return_address - 12);
+ push_insn[0] = 0xeb; // Relative branch insn.
+ push_insn[1] = 13; // Skip over coverage insns.
+ if (coverage_log != NULL) {
+ fprintf(coverage_log, "%s\n", file_line);
+ fflush(coverage_log);
+ }
+}
+
+#endif
+
} } // namespace v8::internal
diff --git a/deps/v8/src/assembler-ia32.h b/deps/v8/src/ia32/assembler-ia32.h
index a6640937e..4c995882e 100644
--- a/deps/v8/src/assembler-ia32.h
+++ b/deps/v8/src/ia32/assembler-ia32.h
@@ -34,8 +34,8 @@
// A light-weight IA32 Assembler.
-#ifndef V8_ASSEMBLER_IA32_H_
-#define V8_ASSEMBLER_IA32_H_
+#ifndef V8_IA32_ASSEMBLER_IA32_H_
+#define V8_IA32_ASSEMBLER_IA32_H_
namespace v8 { namespace internal {
@@ -860,4 +860,4 @@ class EnsureSpace BASE_EMBEDDED {
} } // namespace v8::internal
-#endif // V8_ASSEMBLER_IA32_H_
+#endif // V8_IA32_ASSEMBLER_IA32_H_
diff --git a/deps/v8/src/builtins-ia32.cc b/deps/v8/src/ia32/builtins-ia32.cc
index 0e9de8c0f..5c7ba8e1b 100644
--- a/deps/v8/src/builtins-ia32.cc
+++ b/deps/v8/src/ia32/builtins-ia32.cc
@@ -32,7 +32,7 @@
namespace v8 { namespace internal {
-#define __ masm->
+#define __ ACCESS_MASM(masm)
void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
@@ -54,6 +54,14 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
// -- edi: constructor function
// -----------------------------------
+ Label non_function_call;
+ // Check that function is not a smi.
+ __ test(edi, Immediate(kSmiTagMask));
+ __ j(zero, &non_function_call);
+ // Check that function is a JSFunction.
+ __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
+ __ j(not_equal, &non_function_call);
+
// Enter a construct frame.
__ EnterConstructFrame();
@@ -69,16 +77,12 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
Label rt_call, allocated;
if (FLAG_inline_new) {
Label undo_allocation;
+#ifdef ENABLE_DEBUGGER_SUPPORT
ExternalReference debug_step_in_fp =
ExternalReference::debug_step_in_fp_address();
__ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0));
__ j(not_equal, &rt_call);
- // Check that function is not a Smi.
- __ test(edi, Immediate(kSmiTagMask));
- __ j(zero, &rt_call);
- // Check that function is a JSFunction
- __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax);
- __ j(not_equal, &rt_call);
+#endif
// Verified that the constructor is a JSFunction.
// Load the initial map and verify that it is in fact a map.
@@ -300,6 +304,16 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
__ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver
__ push(ecx);
__ ret(0);
+
+ // edi: called object
+ // eax: number of arguments
+ __ bind(&non_function_call);
+
+ // Set expected number of arguments to zero (not changing eax).
+ __ Set(ebx, Immediate(0));
+ __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
+ __ jmp(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
+ RelocInfo::CODE_TARGET);
}
diff --git a/deps/v8/src/codegen-ia32.cc b/deps/v8/src/ia32/codegen-ia32.cc
index 663f235d7..e260ab2d3 100644
--- a/deps/v8/src/codegen-ia32.cc
+++ b/deps/v8/src/ia32/codegen-ia32.cc
@@ -30,6 +30,7 @@
#include "bootstrapper.h"
#include "codegen-inl.h"
#include "debug.h"
+#include "ic-inl.h"
#include "parser.h"
#include "register-allocator-inl.h"
#include "runtime.h"
@@ -37,7 +38,7 @@
namespace v8 { namespace internal {
-#define __ masm_->
+#define __ ACCESS_MASM(masm_)
// -------------------------------------------------------------------------
// CodeGenState implementation.
@@ -1274,12 +1275,9 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
smi_value,
overwrite_mode);
__ Set(answer.reg(), Immediate(value));
- if (operand->is_register()) {
- __ sub(answer.reg(), Operand(operand->reg()));
- } else {
- ASSERT(operand->is_constant());
- __ sub(Operand(answer.reg()), Immediate(operand->handle()));
- }
+ // We are in the reversed case so they can't both be Smi constants.
+ ASSERT(operand->is_register());
+ __ sub(answer.reg(), Operand(operand->reg()));
} else {
operand->ToRegister();
frame_->Spill(operand->reg());
@@ -1374,23 +1372,26 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
operand->ToRegister();
__ test(operand->reg(), Immediate(kSmiTagMask));
deferred->enter()->Branch(not_zero, operand, not_taken);
- Result answer = allocator()->Allocate();
- ASSERT(answer.is_valid());
- __ mov(answer.reg(), operand->reg());
- ASSERT(kSmiTag == 0); // adjust code if not the case
- // We do no shifts, only the Smi conversion, if shift_value is 1.
- if (shift_value == 0) {
- __ sar(answer.reg(), kSmiTagSize);
- } else if (shift_value > 1) {
- __ shl(answer.reg(), shift_value - 1);
+ if (shift_value != 0) {
+ Result answer = allocator()->Allocate();
+ ASSERT(answer.is_valid());
+ __ mov(answer.reg(), operand->reg());
+ ASSERT(kSmiTag == 0); // adjust code if not the case
+ // We do no shifts, only the Smi conversion, if shift_value is 1.
+ if (shift_value > 1) {
+ __ shl(answer.reg(), shift_value - 1);
+ }
+ // Convert int result to Smi, checking that it is in int range.
+ ASSERT(kSmiTagSize == times_2); // adjust code if not the case
+ __ add(answer.reg(), Operand(answer.reg()));
+ deferred->enter()->Branch(overflow, operand, not_taken);
+ operand->Unuse();
+ deferred->BindExit(&answer);
+ frame_->Push(&answer);
+ } else {
+ deferred->BindExit(operand);
+ frame_->Push(operand);
}
- // Convert int result to Smi, checking that it is in int range.
- ASSERT(kSmiTagSize == times_2); // adjust code if not the case
- __ add(answer.reg(), Operand(answer.reg()));
- deferred->enter()->Branch(overflow, operand, not_taken);
- operand->Unuse();
- deferred->BindExit(&answer);
- frame_->Push(&answer);
}
break;
}
@@ -1411,11 +1412,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
deferred->enter()->Branch(not_zero, operand, not_taken);
frame_->Spill(operand->reg());
if (op == Token::BIT_AND) {
- if (int_value == 0) {
- __ xor_(Operand(operand->reg()), operand->reg());
- } else {
- __ and_(Operand(operand->reg()), Immediate(value));
- }
+ __ and_(Operand(operand->reg()), Immediate(value));
} else if (op == Token::BIT_XOR) {
if (int_value != 0) {
__ xor_(Operand(operand->reg()), Immediate(value));
@@ -2009,18 +2006,18 @@ void CodeGenerator::GenerateReturnSequence(Result* return_value) {
// Add a label for checking the size of the code used for returning.
Label check_exit_codesize;
- __ bind(&check_exit_codesize);
+ masm_->bind(&check_exit_codesize);
// Leave the frame and return popping the arguments and the
// receiver.
frame_->Exit();
- __ ret((scope_->num_parameters() + 1) * kPointerSize);
+ masm_->ret((scope_->num_parameters() + 1) * kPointerSize);
DeleteFrame();
// Check that the size of the code used for returning matches what is
// expected by the debugger.
ASSERT_EQ(Debug::kIa32JSReturnSequenceLength,
- __ SizeOfCodeGeneratedSince(&check_exit_codesize));
+ masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
}
@@ -2143,7 +2140,7 @@ void CodeGenerator::GenerateFastCaseSwitchJumpTable(
times_1, 0x0, RelocInfo::INTERNAL_REFERENCE));
smi_value.Unuse();
// Calculate address to overwrite later with actual address of table.
- int32_t jump_table_ref = __ pc_offset() - sizeof(int32_t);
+ int32_t jump_table_ref = masm_->pc_offset() - sizeof(int32_t);
__ Align(4);
Label table_start;
__ bind(&table_start);
@@ -3179,10 +3176,12 @@ void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
ASSERT(!in_spilled_code());
Comment cmnt(masm_, "[ DebuggerStatement");
CodeForStatementPosition(node);
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Spill everything, even constants, to the frame.
frame_->SpillAll();
frame_->CallRuntime(Runtime::kDebugBreak, 0);
// Ignore the return value.
+#endif
}
@@ -3384,7 +3383,9 @@ Result CodeGenerator::LoadFromGlobalSlotCheckExtensions(
// Loop up the context chain. There is no frame effect so it is
// safe to use raw labels here.
Label next, fast;
- if (!context.reg().is(tmp.reg())) __ mov(tmp.reg(), context.reg());
+ if (!context.reg().is(tmp.reg())) {
+ __ mov(tmp.reg(), context.reg());
+ }
__ bind(&next);
// Terminate at global context.
__ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset),
@@ -3410,7 +3411,10 @@ Result CodeGenerator::LoadFromGlobalSlotCheckExtensions(
? RelocInfo::CODE_TARGET
: RelocInfo::CODE_TARGET_CONTEXT;
Result answer = frame_->CallLoadIC(mode);
-
+ // A test eax instruction following the call signals that the inobject
+ // property case was inlined. Ensure that there is not a test eax
+ // instruction here.
+ __ nop();
// Discard the global object. The result is in answer.
frame_->Drop();
return answer;
@@ -3933,6 +3937,9 @@ void CodeGenerator::VisitAssignment(Assignment* node) {
} else {
Literal* literal = node->value()->AsLiteral();
+ bool overwrite_value =
+ (node->value()->AsBinaryOperation() != NULL &&
+ node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
Variable* right_var = node->value()->AsVariableProxy()->AsVariable();
// There are two cases where the target is not read in the right hand
// side, that are easy to test for: the right hand side is a literal,
@@ -3945,7 +3952,9 @@ void CodeGenerator::VisitAssignment(Assignment* node) {
target.GetValue(NOT_INSIDE_TYPEOF);
}
Load(node->value());
- GenericBinaryOperation(node->binary_op(), node->type());
+ GenericBinaryOperation(node->binary_op(),
+ node->type(),
+ overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
}
if (var != NULL &&
@@ -4535,6 +4544,17 @@ void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
}
+void CodeGenerator::GenerateGetFramePointer(ZoneList<Expression*>* args) {
+ ASSERT(args->length() == 0);
+ ASSERT(kSmiTagSize == 1 && kSmiTag == 0); // shifting code depends on this
+ Result ebp_as_smi = allocator_->Allocate();
+ ASSERT(ebp_as_smi.is_valid());
+ __ mov(ebp_as_smi.reg(), Operand(ebp));
+ __ shr(ebp_as_smi.reg(), kSmiTagSize);
+ frame_->Push(&ebp_as_smi);
+}
+
+
void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
if (CheckForInlineRuntimeCall(node)) {
return;
@@ -5228,6 +5248,48 @@ bool CodeGenerator::HasValidEntryRegisters() {
#endif
+class DeferredReferenceGetNamedValue: public DeferredCode {
+ public:
+ DeferredReferenceGetNamedValue(CodeGenerator* cgen, Handle<String> name)
+ : DeferredCode(cgen), name_(name) {
+ set_comment("[ DeferredReferenceGetNamedValue");
+ }
+
+ virtual void Generate();
+
+ Label* patch_site() { return &patch_site_; }
+
+ private:
+ Label patch_site_;
+ Handle<String> name_;
+};
+
+
+void DeferredReferenceGetNamedValue::Generate() {
+ CodeGenerator* cgen = generator();
+ Result receiver(cgen);
+ enter()->Bind(&receiver);
+
+ cgen->frame()->Push(&receiver);
+ cgen->frame()->Push(name_);
+ Result answer = cgen->frame()->CallLoadIC(RelocInfo::CODE_TARGET);
+ // The call must be followed by a test eax instruction to indicate
+ // that the inobject property case was inlined.
+ ASSERT(answer.is_register() && answer.reg().is(eax));
+ // Store the delta to the map check instruction here in the test instruction.
+ // Use masm_-> instead of the double underscore macro since the latter can't
+ // return a value.
+ int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
+ // Here we use masm_-> instead of the double underscore macro because
+ // this is the instruction that gets patched and coverage code gets in
+ // the way.
+ masm_->test(answer.reg(), Immediate(-delta_to_patch_site));
+ __ IncrementCounter(&Counters::named_load_inline_miss, 1);
+ receiver = cgen->frame()->Pop();
+ exit_.Jump(&receiver, &answer);
+}
+
+
class DeferredReferenceGetKeyedValue: public DeferredCode {
public:
DeferredReferenceGetKeyedValue(CodeGenerator* generator, bool is_global)
@@ -5268,9 +5330,14 @@ void DeferredReferenceGetKeyedValue::Generate() {
// instruction.
ASSERT(value.is_register() && value.reg().is(eax));
// The delta from the start of the map-compare instruction to the
- // test eax instruction.
- int delta_to_patch_site = __ SizeOfCodeGeneratedSince(patch_site());
- __ test(value.reg(), Immediate(-delta_to_patch_site));
+ // test instruction. We use masm_ directly here instead of the
+ // double underscore macro because the macro sometimes uses macro
+ // expansion to turn into something that can't return a value. This
+ // is encountered when doing generated code coverage tests.
+ int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
+ // Here we use masm_-> instead of the double underscore macro because this
+ // is the instruction that gets patched and coverage code gets in the way.
+ masm_->test(value.reg(), Immediate(-delta_to_patch_site));
__ IncrementCounter(&Counters::keyed_load_inline_miss, 1);
// The receiver and key were spilled by the call, so their state as
@@ -5284,7 +5351,7 @@ void DeferredReferenceGetKeyedValue::Generate() {
#undef __
-#define __ masm->
+#define __ ACCESS_MASM(masm)
Handle<String> Reference::GetName() {
ASSERT(type_ == NAMED);
@@ -5324,16 +5391,66 @@ void Reference::GetValue(TypeofState typeof_state) {
// thrown below, we must distinguish between the two kinds of
// loads (typeof expression loads must not throw a reference
// error).
- Comment cmnt(masm, "[ Load from named Property");
- cgen_->frame()->Push(GetName());
-
Variable* var = expression_->AsVariableProxy()->AsVariable();
- ASSERT(var == NULL || var->is_global());
- RelocInfo::Mode mode = (var == NULL)
- ? RelocInfo::CODE_TARGET
- : RelocInfo::CODE_TARGET_CONTEXT;
- Result answer = cgen_->frame()->CallLoadIC(mode);
- cgen_->frame()->Push(&answer);
+ bool is_global = var != NULL;
+ ASSERT(!is_global || var->is_global());
+
+ if (is_global || cgen_->scope()->is_global_scope()) {
+ // Do not inline the inobject property case for loads from the
+ // global object or loads in toplevel code.
+ Comment cmnt(masm, "[ Load from named Property");
+ cgen_->frame()->Push(GetName());
+
+ RelocInfo::Mode mode = is_global
+ ? RelocInfo::CODE_TARGET_CONTEXT
+ : RelocInfo::CODE_TARGET;
+ Result answer = cgen_->frame()->CallLoadIC(mode);
+ // A test eax instruction following the call signals that the
+ // inobject property case was inlined. Ensure that there is not
+ // a test eax instruction here.
+ __ nop();
+ cgen_->frame()->Push(&answer);
+ } else {
+ // Inline the inobject property case.
+ Comment cmnt(masm, "[ Inlined named property load");
+ DeferredReferenceGetNamedValue* deferred =
+ new DeferredReferenceGetNamedValue(cgen_, GetName());
+ Result receiver = cgen_->frame()->Pop();
+ receiver.ToRegister();
+ // Check that the receiver is a heap object.
+ __ test(receiver.reg(), Immediate(kSmiTagMask));
+ deferred->enter()->Branch(zero, &receiver, not_taken);
+
+ // Preallocate the value register to ensure that there is no
+ // spill emitted between the patch site label and the offset in
+ // the load instruction.
+ Result value = cgen_->allocator()->Allocate();
+ ASSERT(value.is_valid());
+ __ bind(deferred->patch_site());
+ // This is the map check instruction that will be patched (so we can't
+ // use the double underscore macro that may insert instructions).
+ // Initially use an invalid map to force a failure.
+ masm->cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
+ Immediate(Factory::null_value()));
+ // This branch is always a forwards branch so it's always a fixed
+ // size which allows the assert below to succeed and patching to work.
+ deferred->enter()->Branch(not_equal, &receiver, not_taken);
+
+ // The delta from the patch label to the load offset must be
+ // statically known.
+ ASSERT(masm->SizeOfCodeGeneratedSince(deferred->patch_site()) ==
+ LoadIC::kOffsetToLoadInstruction);
+ // The initial (invalid) offset has to be large enough to force
+ // a 32-bit instruction encoding to allow patching with an
+ // arbitrary offset. Use kMaxInt (minus kHeapObjectTag).
+ int offset = kMaxInt;
+ masm->mov(value.reg(), FieldOperand(receiver.reg(), offset));
+
+ __ IncrementCounter(&Counters::named_load_inline, 1);
+ deferred->BindExit(&receiver, &value);
+ cgen_->frame()->Push(&receiver);
+ cgen_->frame()->Push(&value);
+ }
break;
}
@@ -5369,7 +5486,9 @@ void Reference::GetValue(TypeofState typeof_state) {
// Initially, use an invalid map. The map is patched in the IC
// initialization code.
__ bind(deferred->patch_site());
- __ cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
+ // Use masm-> here instead of the double underscore macro since extra
+ // coverage code can interfere with the patching.
+ masm->cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
Immediate(Factory::null_value()));
deferred->enter()->Branch(not_equal, &receiver, &key, not_taken);
@@ -5566,7 +5685,7 @@ void ToBooleanStub::Generate(MacroAssembler* masm) {
#undef __
-#define __ masm_->
+#define __ ACCESS_MASM(masm_)
Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
Result* right) {
@@ -5794,10 +5913,10 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
// Right operand must be in register cl because x86 likes it that way.
if (right->reg().is(ecx)) {
// Right is already in the right place. Left may be in the
- // same register, which causes problems. Use answer instead.
- if (left->reg().is(ecx)) {
- *left = answer;
- }
+ // same register, which causes problems. Always use answer
+ // instead of left, even if left is not ecx, since this avoids
+ // spilling left.
+ *left = answer;
} else if (left->reg().is(ecx)) {
generator()->frame()->Spill(left->reg());
__ mov(left->reg(), right->reg());
@@ -5811,6 +5930,9 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
ASSERT(reg_ecx.is_valid());
__ mov(ecx, right->reg());
*right = reg_ecx;
+ // Answer and left both contain the left operand. Use answer, so
+ // left is not spilled.
+ *left = answer;
}
ASSERT(left->reg().is_valid());
ASSERT(!left->reg().is(ecx));
@@ -5860,16 +5982,10 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
case Token::SHL: {
__ shl(left->reg());
// Check that the *signed* result fits in a smi.
- //
- // TODO(207): Can reduce registers from 4 to 3 by
- // preallocating ecx.
JumpTarget result_ok(generator());
- Result smi_test_reg = generator()->allocator()->Allocate();
- ASSERT(smi_test_reg.is_valid());
- __ lea(smi_test_reg.reg(), Operand(left->reg(), 0x40000000));
- __ test(smi_test_reg.reg(), Immediate(0x80000000));
- smi_test_reg.Unuse();
- result_ok.Branch(zero, left, taken);
+ __ cmp(left->reg(), 0xc0000000);
+ result_ok.Branch(positive, left, taken);
+
__ shr(left->reg());
ASSERT(kSmiTag == 0);
__ shl(left->reg(), kSmiTagSize);
@@ -5900,7 +6016,7 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
#undef __
-#define __ masm->
+#define __ ACCESS_MASM(masm)
void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) {
// Perform fast-case smi code for the operation (eax <op> ebx) and
@@ -6169,11 +6285,15 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
case Token::SHR: __ shr(eax); break;
default: UNREACHABLE();
}
-
- // Check if result is non-negative and fits in a smi.
- __ test(eax, Immediate(0xc0000000));
- __ j(not_zero, &non_smi_result);
-
+ if (op_ == Token::SHR) {
+ // Check if result is non-negative and fits in a smi.
+ __ test(eax, Immediate(0xc0000000));
+ __ j(not_zero, &non_smi_result);
+ } else {
+ // Check if result fits in a smi.
+ __ cmp(eax, 0xc0000000);
+ __ j(negative, &non_smi_result);
+ }
// Tag smi result and return.
ASSERT(kSmiTagSize == times_2); // adjust code if not the case
__ lea(eax, Operand(eax, eax, times_1, kSmiTag));
@@ -6225,7 +6345,9 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
}
// SHR should return uint32 - go to runtime for non-smi/negative result.
- if (op_ == Token::SHR) __ bind(&non_smi_result);
+ if (op_ == Token::SHR) {
+ __ bind(&non_smi_result);
+ }
__ mov(eax, Operand(esp, 1 * kPointerSize));
__ mov(edx, Operand(esp, 2 * kPointerSize));
break;
diff --git a/deps/v8/src/ia32/codegen-ia32.h b/deps/v8/src/ia32/codegen-ia32.h
new file mode 100644
index 000000000..0e019570e
--- /dev/null
+++ b/deps/v8/src/ia32/codegen-ia32.h
@@ -0,0 +1,633 @@
+// Copyright 2006-2008 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_IA32_CODEGEN_IA32_H_
+#define V8_IA32_CODEGEN_IA32_H_
+
+namespace v8 { namespace internal {
+
+// Forward declarations
+class DeferredCode;
+class RegisterAllocator;
+class RegisterFile;
+
+enum InitState { CONST_INIT, NOT_CONST_INIT };
+enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
+
+
+// -------------------------------------------------------------------------
+// Reference support
+
+// A reference is a C++ stack-allocated object that keeps an ECMA
+// reference on the execution stack while in scope. For variables
+// the reference is empty, indicating that it isn't necessary to
+// store state on the stack for keeping track of references to those.
+// For properties, we keep either one (named) or two (indexed) values
+// on the execution stack to represent the reference.
+
+class Reference BASE_EMBEDDED {
+ public:
+ // The values of the types is important, see size().
+ enum Type { ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 };
+ Reference(CodeGenerator* cgen, Expression* expression);
+ ~Reference();
+
+ Expression* expression() const { return expression_; }
+ Type type() const { return type_; }
+ void set_type(Type value) {
+ ASSERT(type_ == ILLEGAL);
+ type_ = value;
+ }
+
+ // The size the reference takes up on the stack.
+ int size() const { return (type_ == ILLEGAL) ? 0 : type_; }
+
+ bool is_illegal() const { return type_ == ILLEGAL; }
+ bool is_slot() const { return type_ == SLOT; }
+ bool is_property() const { return type_ == NAMED || type_ == KEYED; }
+
+ // Return the name. Only valid for named property references.
+ Handle<String> GetName();
+
+ // Generate code to push the value of the reference on top of the
+ // expression stack. The reference is expected to be already on top of
+ // the expression stack, and it is left in place with its value above it.
+ void GetValue(TypeofState typeof_state);
+
+ // Like GetValue except that the slot is expected to be written to before
+ // being read from again. Thae value of the reference may be invalidated,
+ // causing subsequent attempts to read it to fail.
+ void TakeValue(TypeofState typeof_state);
+
+ // Generate code to store the value on top of the expression stack in the
+ // reference. The reference is expected to be immediately below the value
+ // on the expression stack. The stored value is left in place (with the
+ // reference intact below it) to support chained assignments.
+ void SetValue(InitState init_state);
+
+ private:
+ CodeGenerator* cgen_;
+ Expression* expression_;
+ Type type_;
+};
+
+
+// -------------------------------------------------------------------------
+// Control destinations.
+
+// A control destination encapsulates a pair of jump targets and a
+// flag indicating which one is the preferred fall-through. The
+// preferred fall-through must be unbound, the other may be already
+// bound (ie, a backward target).
+//
+// The true and false targets may be jumped to unconditionally or
+// control may split conditionally. Unconditional jumping and
+// splitting should be emitted in tail position (as the last thing
+// when compiling an expression) because they can cause either label
+// to be bound or the non-fall through to be jumped to leaving an
+// invalid virtual frame.
+//
+// The labels in the control destination can be extracted and
+// manipulated normally without affecting the state of the
+// destination.
+
+class ControlDestination BASE_EMBEDDED {
+ public:
+ ControlDestination(JumpTarget* true_target,
+ JumpTarget* false_target,
+ bool true_is_fall_through)
+ : true_target_(true_target),
+ false_target_(false_target),
+ true_is_fall_through_(true_is_fall_through),
+ is_used_(false) {
+ ASSERT(true_is_fall_through ? !true_target->is_bound()
+ : !false_target->is_bound());
+ }
+
+ // Accessors for the jump targets. Directly jumping or branching to
+ // or binding the targets will not update the destination's state.
+ JumpTarget* true_target() const { return true_target_; }
+ JumpTarget* false_target() const { return false_target_; }
+
+ // True if the the destination has been jumped to unconditionally or
+ // control has been split to both targets. This predicate does not
+ // test whether the targets have been extracted and manipulated as
+ // raw jump targets.
+ bool is_used() const { return is_used_; }
+
+ // True if the destination is used and the true target (respectively
+ // false target) was the fall through. If the target is backward,
+ // "fall through" included jumping unconditionally to it.
+ bool true_was_fall_through() const {
+ return is_used_ && true_is_fall_through_;
+ }
+
+ bool false_was_fall_through() const {
+ return is_used_ && !true_is_fall_through_;
+ }
+
+ // Emit a branch to one of the true or false targets, and bind the
+ // other target. Because this binds the fall-through target, it
+ // should be emitted in tail position (as the last thing when
+ // compiling an expression).
+ void Split(Condition cc) {
+ ASSERT(!is_used_);
+ if (true_is_fall_through_) {
+ false_target_->Branch(NegateCondition(cc));
+ true_target_->Bind();
+ } else {
+ true_target_->Branch(cc);
+ false_target_->Bind();
+ }
+ is_used_ = true;
+ }
+
+ // Emit an unconditional jump in tail position, to the true target
+ // (if the argument is true) or the false target. The "jump" will
+ // actually bind the jump target if it is forward, jump to it if it
+ // is backward.
+ void Goto(bool where) {
+ ASSERT(!is_used_);
+ JumpTarget* target = where ? true_target_ : false_target_;
+ if (target->is_bound()) {
+ target->Jump();
+ } else {
+ target->Bind();
+ }
+ is_used_ = true;
+ true_is_fall_through_ = where;
+ }
+
+ // Mark this jump target as used as if Goto had been called, but
+ // without generating a jump or binding a label (the control effect
+ // should have already happened). This is used when the left
+ // subexpression of the short-circuit boolean operators are
+ // compiled.
+ void Use(bool where) {
+ ASSERT(!is_used_);
+ ASSERT((where ? true_target_ : false_target_)->is_bound());
+ is_used_ = true;
+ true_is_fall_through_ = where;
+ }
+
+ // Swap the true and false targets but keep the same actual label as
+ // the fall through. This is used when compiling negated
+ // expressions, where we want to swap the targets but preserve the
+ // state.
+ void Invert() {
+ JumpTarget* temp_target = true_target_;
+ true_target_ = false_target_;
+ false_target_ = temp_target;
+
+ true_is_fall_through_ = !true_is_fall_through_;
+ }
+
+ private:
+ // True and false jump targets.
+ JumpTarget* true_target_;
+ JumpTarget* false_target_;
+
+ // Before using the destination: true if the true target is the
+ // preferred fall through, false if the false target is. After
+ // using the destination: true if the true target was actually used
+ // as the fall through, false if the false target was.
+ bool true_is_fall_through_;
+
+ // True if the Split or Goto functions have been called.
+ bool is_used_;
+};
+
+
+// -------------------------------------------------------------------------
+// Code generation state
+
+// The state is passed down the AST by the code generator (and back up, in
+// the form of the state of the jump target pair). It is threaded through
+// the call stack. Constructing a state implicitly pushes it on the owning
+// code generator's stack of states, and destroying one implicitly pops it.
+//
+// The code generator state is only used for expressions, so statements have
+// the initial state.
+
+class CodeGenState BASE_EMBEDDED {
+ public:
+ // Create an initial code generator state. Destroying the initial state
+ // leaves the code generator with a NULL state.
+ explicit CodeGenState(CodeGenerator* owner);
+
+ // Create a code generator state based on a code generator's current
+ // state. The new state may or may not be inside a typeof, and has its
+ // own control destination.
+ CodeGenState(CodeGenerator* owner,
+ TypeofState typeof_state,
+ ControlDestination* destination);
+
+ // Destroy a code generator state and restore the owning code generator's
+ // previous state.
+ ~CodeGenState();
+
+ // Accessors for the state.
+ TypeofState typeof_state() const { return typeof_state_; }
+ ControlDestination* destination() const { return destination_; }
+
+ private:
+ // The owning code generator.
+ CodeGenerator* owner_;
+
+ // A flag indicating whether we are compiling the immediate subexpression
+ // of a typeof expression.
+ TypeofState typeof_state_;
+
+ // A control destination in case the expression has a control-flow
+ // effect.
+ ControlDestination* destination_;
+
+ // The previous state of the owning code generator, restored when
+ // this state is destroyed.
+ CodeGenState* previous_;
+};
+
+
+
+
+// -------------------------------------------------------------------------
+// CodeGenerator
+
+class CodeGenerator: public AstVisitor {
+ public:
+ // Takes a function literal, generates code for it. This function should only
+ // be called by compiler.cc.
+ static Handle<Code> MakeCode(FunctionLiteral* fun,
+ Handle<Script> script,
+ bool is_eval);
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+ static bool ShouldGenerateLog(Expression* type);
+#endif
+
+ static void SetFunctionInfo(Handle<JSFunction> fun,
+ int length,
+ int function_token_position,
+ int start_position,
+ int end_position,
+ bool is_expression,
+ bool is_toplevel,
+ Handle<Script> script,
+ Handle<String> inferred_name);
+
+ // Accessors
+ MacroAssembler* masm() { return masm_; }
+
+ VirtualFrame* frame() const { return frame_; }
+
+ bool has_valid_frame() const { return frame_ != NULL; }
+
+ // Set the virtual frame to be new_frame, with non-frame register
+ // reference counts given by non_frame_registers. The non-frame
+ // register reference counts of the old frame are returned in
+ // non_frame_registers.
+ void SetFrame(VirtualFrame* new_frame, RegisterFile* non_frame_registers);
+
+ void DeleteFrame();
+
+ RegisterAllocator* allocator() const { return allocator_; }
+
+ CodeGenState* state() { return state_; }
+ void set_state(CodeGenState* state) { state_ = state; }
+
+ void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
+
+ bool in_spilled_code() const { return in_spilled_code_; }
+ void set_in_spilled_code(bool flag) { in_spilled_code_ = flag; }
+
+ private:
+ // Construction/Destruction
+ CodeGenerator(int buffer_size, Handle<Script> script, bool is_eval);
+ virtual ~CodeGenerator() { delete masm_; }
+
+ // Accessors
+ Scope* scope() const { return scope_; }
+
+ // Clearing and generating deferred code.
+ void ClearDeferred();
+ void ProcessDeferred();
+
+ bool is_eval() { return is_eval_; }
+
+ // State
+ TypeofState typeof_state() const { return state_->typeof_state(); }
+ ControlDestination* destination() const { return state_->destination(); }
+
+ // Track loop nesting level.
+ int loop_nesting() const { return loop_nesting_; }
+ void IncrementLoopNesting() { loop_nesting_++; }
+ void DecrementLoopNesting() { loop_nesting_--; }
+
+
+ // Node visitors.
+ void VisitStatements(ZoneList<Statement*>* statements);
+
+#define DEF_VISIT(type) \
+ void Visit##type(type* node);
+ NODE_LIST(DEF_VISIT)
+#undef DEF_VISIT
+
+ // Visit a statement and then spill the virtual frame if control flow can
+ // reach the end of the statement (ie, it does not exit via break,
+ // continue, return, or throw). This function is used temporarily while
+ // the code generator is being transformed.
+ void VisitAndSpill(Statement* statement);
+
+ // Visit a list of statements and then spill the virtual frame if control
+ // flow can reach the end of the list.
+ void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
+
+ // Main code generation function
+ void GenCode(FunctionLiteral* fun);
+
+ // Generate the return sequence code. Should be called no more than
+ // once per compiled function, immediately after binding the return
+ // target (which can not be done more than once).
+ void GenerateReturnSequence(Result* return_value);
+
+ // The following are used by class Reference.
+ void LoadReference(Reference* ref);
+ void UnloadReference(Reference* ref);
+
+ Operand ContextOperand(Register context, int index) const {
+ return Operand(context, Context::SlotOffset(index));
+ }
+
+ Operand SlotOperand(Slot* slot, Register tmp);
+
+ Operand ContextSlotOperandCheckExtensions(Slot* slot,
+ Result tmp,
+ JumpTarget* slow);
+
+ // Expressions
+ Operand GlobalObject() const {
+ return ContextOperand(esi, Context::GLOBAL_INDEX);
+ }
+
+ void LoadCondition(Expression* x,
+ TypeofState typeof_state,
+ ControlDestination* destination,
+ bool force_control);
+ void Load(Expression* x, TypeofState typeof_state = NOT_INSIDE_TYPEOF);
+ void LoadGlobal();
+ void LoadGlobalReceiver();
+
+ // Generate code to push the value of an expression on top of the frame
+ // and then spill the frame fully to memory. This function is used
+ // temporarily while the code generator is being transformed.
+ void LoadAndSpill(Expression* expression,
+ TypeofState typeof_state = NOT_INSIDE_TYPEOF);
+
+ // Read a value from a slot and leave it on top of the expression stack.
+ void LoadFromSlot(Slot* slot, TypeofState typeof_state);
+ Result LoadFromGlobalSlotCheckExtensions(Slot* slot,
+ TypeofState typeof_state,
+ JumpTarget* slow);
+
+ // Store the value on top of the expression stack into a slot, leaving the
+ // value in place.
+ void StoreToSlot(Slot* slot, InitState init_state);
+
+ // Special code for typeof expressions: Unfortunately, we must
+ // be careful when loading the expression in 'typeof'
+ // expressions. We are not allowed to throw reference errors for
+ // non-existing properties of the global object, so we must make it
+ // look like an explicit property access, instead of an access
+ // through the context chain.
+ void LoadTypeofExpression(Expression* x);
+
+ // Translate the value on top of the frame into control flow to the
+ // control destination.
+ void ToBoolean(ControlDestination* destination);
+
+ void GenericBinaryOperation(
+ Token::Value op,
+ SmiAnalysis* type,
+ OverwriteMode overwrite_mode);
+
+ // If possible, combine two constant smi values using op to produce
+ // a smi result, and push it on the virtual frame, all at compile time.
+ // Returns true if it succeeds. Otherwise it has no effect.
+ bool FoldConstantSmis(Token::Value op, int left, int right);
+
+ // Emit code to perform a binary operation on a constant
+ // smi and a likely smi. Consumes the Result *operand.
+ void ConstantSmiBinaryOperation(Token::Value op,
+ Result* operand,
+ Handle<Object> constant_operand,
+ SmiAnalysis* type,
+ bool reversed,
+ OverwriteMode overwrite_mode);
+
+ // Emit code to perform a binary operation on two likely smis.
+ // The code to handle smi arguments is produced inline.
+ // Consumes the Results *left and *right.
+ void LikelySmiBinaryOperation(Token::Value op,
+ Result* left,
+ Result* right,
+ OverwriteMode overwrite_mode);
+
+ void Comparison(Condition cc,
+ bool strict,
+ ControlDestination* destination);
+
+ // To prevent long attacker-controlled byte sequences, integer constants
+ // from the JavaScript source are loaded in two parts if they are larger
+ // than 16 bits.
+ static const int kMaxSmiInlinedBits = 16;
+ bool IsUnsafeSmi(Handle<Object> value);
+ // Load an integer constant x into a register target using
+ // at most 16 bits of user-controlled data per assembly operation.
+ void LoadUnsafeSmi(Register target, Handle<Object> value);
+
+ void CallWithArguments(ZoneList<Expression*>* arguments, int position);
+
+ void CheckStack();
+
+ struct InlineRuntimeLUT {
+ void (CodeGenerator::*method)(ZoneList<Expression*>*);
+ const char* name;
+ };
+
+ static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
+ bool CheckForInlineRuntimeCall(CallRuntime* node);
+ static bool PatchInlineRuntimeEntry(Handle<String> name,
+ const InlineRuntimeLUT& new_entry,
+ InlineRuntimeLUT* old_entry);
+
+ Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node);
+ void ProcessDeclarations(ZoneList<Declaration*>* declarations);
+
+ Handle<Code> ComputeCallInitialize(int argc);
+ Handle<Code> ComputeCallInitializeInLoop(int argc);
+
+ // Declare global variables and functions in the given array of
+ // name/value pairs.
+ void DeclareGlobals(Handle<FixedArray> pairs);
+
+ // Instantiate the function boilerplate.
+ void InstantiateBoilerplate(Handle<JSFunction> boilerplate);
+
+ // Support for type checks.
+ void GenerateIsSmi(ZoneList<Expression*>* args);
+ void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
+ void GenerateIsArray(ZoneList<Expression*>* args);
+
+ // Support for arguments.length and arguments[?].
+ void GenerateArgumentsLength(ZoneList<Expression*>* args);
+ void GenerateArgumentsAccess(ZoneList<Expression*>* args);
+
+ // Support for accessing the value field of an object (used by Date).
+ void GenerateValueOf(ZoneList<Expression*>* args);
+ void GenerateSetValueOf(ZoneList<Expression*>* args);
+
+ // Fast support for charCodeAt(n).
+ void GenerateFastCharCodeAt(ZoneList<Expression*>* args);
+
+ // Fast support for object equality testing.
+ void GenerateObjectEquals(ZoneList<Expression*>* args);
+
+ void GenerateLog(ZoneList<Expression*>* args);
+
+ void GenerateGetFramePointer(ZoneList<Expression*>* args);
+
+ // Methods and constants for fast case switch statement support.
+ //
+ // Only allow fast-case switch if the range of labels is at most
+ // this factor times the number of case labels.
+ // Value is derived from comparing the size of code generated by the normal
+ // switch code for Smi-labels to the size of a single pointer. If code
+ // quality increases this number should be decreased to match.
+ static const int kFastSwitchMaxOverheadFactor = 5;
+
+ // Minimal number of switch cases required before we allow jump-table
+ // optimization.
+ static const int kFastSwitchMinCaseCount = 5;
+
+ // The limit of the range of a fast-case switch, as a factor of the number
+ // of cases of the switch. Each platform should return a value that
+ // is optimal compared to the default code generated for a switch statement
+ // on that platform.
+ int FastCaseSwitchMaxOverheadFactor();
+
+ // The minimal number of cases in a switch before the fast-case switch
+ // optimization is enabled. Each platform should return a value that
+ // is optimal compared to the default code generated for a switch statement
+ // on that platform.
+ int FastCaseSwitchMinCaseCount();
+
+ // Allocate a jump table and create code to jump through it.
+ // Should call GenerateFastCaseSwitchCases to generate the code for
+ // all the cases at the appropriate point.
+ void GenerateFastCaseSwitchJumpTable(SwitchStatement* node,
+ int min_index,
+ int range,
+ Label* fail_label,
+ Vector<Label*> case_targets,
+ Vector<Label> case_labels);
+
+ // Generate the code for cases for the fast case switch.
+ // Called by GenerateFastCaseSwitchJumpTable.
+ void GenerateFastCaseSwitchCases(SwitchStatement* node,
+ Vector<Label> case_labels,
+ VirtualFrame* start_frame);
+
+ // Fast support for constant-Smi switches.
+ void GenerateFastCaseSwitchStatement(SwitchStatement* node,
+ int min_index,
+ int range,
+ int default_index);
+
+ // Fast support for constant-Smi switches. Tests whether switch statement
+ // permits optimization and calls GenerateFastCaseSwitch if it does.
+ // Returns true if the fast-case switch was generated, and false if not.
+ bool TryGenerateFastCaseSwitchStatement(SwitchStatement* node);
+
+ // Methods used to indicate which source code is generated for. Source
+ // positions are collected by the assembler and emitted with the relocation
+ // information.
+ void CodeForFunctionPosition(FunctionLiteral* fun);
+ void CodeForReturnPosition(FunctionLiteral* fun);
+ void CodeForStatementPosition(Node* node);
+ void CodeForSourcePosition(int pos);
+
+#ifdef DEBUG
+ // True if the registers are valid for entry to a block. There should be
+ // no frame-external references to eax, ebx, ecx, edx, or edi.
+ bool HasValidEntryRegisters();
+#endif
+
+ bool is_eval_; // Tells whether code is generated for eval.
+ Handle<Script> script_;
+ List<DeferredCode*> deferred_;
+
+ // Assembler
+ MacroAssembler* masm_; // to generate code
+
+ // Code generation state
+ Scope* scope_;
+ VirtualFrame* frame_;
+ RegisterAllocator* allocator_;
+ CodeGenState* state_;
+ int loop_nesting_;
+
+ // Jump targets.
+ // The target of the return from the function.
+ BreakTarget function_return_;
+
+ // True if the function return is shadowed (ie, jumping to the target
+ // function_return_ does not jump to the true function return, but rather
+ // to some unlinking code).
+ bool function_return_is_shadowed_;
+
+ // True when we are in code that expects the virtual frame to be fully
+ // spilled. Some virtual frame function are disabled in DEBUG builds when
+ // called from spilled code, because they do not leave the virtual frame
+ // in a spilled state.
+ bool in_spilled_code_;
+
+ static InlineRuntimeLUT kInlineRuntimeLUT[];
+
+ friend class VirtualFrame;
+ friend class JumpTarget;
+ friend class Reference;
+ friend class Result;
+
+ friend class CodeGeneratorPatcher; // Used in test-log-ia32.cc
+
+ DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
+};
+
+
+} } // namespace v8::internal
+
+#endif // V8_IA32_CODEGEN_IA32_H_
diff --git a/deps/v8/src/cpu-ia32.cc b/deps/v8/src/ia32/cpu-ia32.cc
index 9cd6b10bd..9cd6b10bd 100644
--- a/deps/v8/src/cpu-ia32.cc
+++ b/deps/v8/src/ia32/cpu-ia32.cc
diff --git a/deps/v8/src/debug-ia32.cc b/deps/v8/src/ia32/debug-ia32.cc
index 6d59889aa..9503cfca7 100644
--- a/deps/v8/src/debug-ia32.cc
+++ b/deps/v8/src/ia32/debug-ia32.cc
@@ -33,6 +33,7 @@
namespace v8 { namespace internal {
+#ifdef ENABLE_DEBUGGER_SUPPORT
// A debug break in the frame exit code is identified by a call instruction.
bool BreakLocationIterator::IsDebugBreakAtReturn() {
@@ -67,7 +68,7 @@ bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
}
-#define __ masm->
+#define __ ACCESS_MASM(masm)
static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
@@ -214,5 +215,6 @@ void Debug::GenerateStubNoRegistersDebugBreak(MacroAssembler* masm) {
#undef __
+#endif // ENABLE_DEBUGGER_SUPPORT
} } // namespace v8::internal
diff --git a/deps/v8/src/disasm-ia32.cc b/deps/v8/src/ia32/disasm-ia32.cc
index 458844e05..458844e05 100644
--- a/deps/v8/src/disasm-ia32.cc
+++ b/deps/v8/src/ia32/disasm-ia32.cc
diff --git a/deps/v8/src/frames-ia32.cc b/deps/v8/src/ia32/frames-ia32.cc
index 1bc62ec22..1bc62ec22 100644
--- a/deps/v8/src/frames-ia32.cc
+++ b/deps/v8/src/ia32/frames-ia32.cc
diff --git a/deps/v8/src/frames-ia32.h b/deps/v8/src/ia32/frames-ia32.h
index 518b1ca55..f86dbe4c1 100644
--- a/deps/v8/src/frames-ia32.h
+++ b/deps/v8/src/ia32/frames-ia32.h
@@ -25,8 +25,8 @@
// (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_FRAMES_IA32_H_
-#define V8_FRAMES_IA32_H_
+#ifndef V8_IA32_FRAMES_IA32_H_
+#define V8_IA32_FRAMES_IA32_H_
namespace v8 { namespace internal {
@@ -288,4 +288,4 @@ inline Object* JavaScriptFrame::function_slot_object() const {
} } // namespace v8::internal
-#endif // V8_FRAMES_IA32_H_
+#endif // V8_IA32_FRAMES_IA32_H_
diff --git a/deps/v8/src/ic-ia32.cc b/deps/v8/src/ia32/ic-ia32.cc
index 9060f2de9..4231bfae7 100644
--- a/deps/v8/src/ic-ia32.cc
+++ b/deps/v8/src/ia32/ic-ia32.cc
@@ -38,7 +38,7 @@ namespace v8 { namespace internal {
// Static IC stub generators.
//
-#define __ masm->
+#define __ ACCESS_MASM(masm)
// Helper function used to load a property from a dictionary backing storage.
@@ -91,7 +91,9 @@ static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label,
// Compute the masked index: (hash + i + i * i) & mask.
__ mov(r1, FieldOperand(name, String::kLengthOffset));
__ shr(r1, String::kHashShift);
- if (i > 0) __ add(Operand(r1), Immediate(Dictionary::GetProbeOffset(i)));
+ if (i > 0) {
+ __ add(Operand(r1), Immediate(Dictionary::GetProbeOffset(i)));
+ }
__ and_(r1, Operand(r2));
// Scale the index by multiplying by the element size.
@@ -121,23 +123,19 @@ static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label,
}
-// Helper function used to check that a value is either not a function
-// or is loaded if it is a function.
-static void GenerateCheckNonFunctionOrLoaded(MacroAssembler* masm, Label* miss,
- Register value, Register scratch) {
+// Helper function used to check that a value is either not an object
+// or is loaded if it is an object.
+static void GenerateCheckNonObjectOrLoaded(MacroAssembler* masm, Label* miss,
+ Register value, Register scratch) {
Label done;
// Check if the value is a Smi.
__ test(value, Immediate(kSmiTagMask));
__ j(zero, &done, not_taken);
- // Check if the value is a function.
- __ CmpObjectType(value, JS_FUNCTION_TYPE, scratch);
- __ j(not_equal, &done, taken);
- // Check if the function has been loaded.
- __ mov(scratch, FieldOperand(value, JSFunction::kSharedFunctionInfoOffset));
- __ mov(scratch,
- FieldOperand(scratch, SharedFunctionInfo::kLazyLoadDataOffset));
- __ cmp(scratch, Factory::undefined_value());
- __ j(not_equal, miss, not_taken);
+ // Check if the object has been loaded.
+ __ mov(scratch, FieldOperand(value, JSFunction::kMapOffset));
+ __ mov(scratch, FieldOperand(scratch, Map::kBitField2Offset));
+ __ test(scratch, Immediate(1 << Map::kNeedsLoading));
+ __ j(not_zero, miss, not_taken);
__ bind(&done);
}
@@ -266,7 +264,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ j(not_zero, &slow, not_taken);
// Probe the dictionary leaving result in ecx.
GenerateDictionaryLoad(masm, &slow, ebx, ecx, edx, eax);
- GenerateCheckNonFunctionOrLoaded(masm, &slow, ecx, edx);
+ GenerateCheckNonObjectOrLoaded(masm, &slow, ecx, edx);
__ mov(eax, Operand(ecx));
__ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
__ ret(0);
@@ -491,10 +489,10 @@ static void GenerateNormalHelper(MacroAssembler* masm,
__ j(not_equal, miss, not_taken);
// Check that the function has been loaded.
- __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
- __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kLazyLoadDataOffset));
- __ cmp(edx, Factory::undefined_value());
- __ j(not_equal, miss, not_taken);
+ __ mov(edx, FieldOperand(edi, JSFunction::kMapOffset));
+ __ mov(edx, FieldOperand(edx, Map::kBitField2Offset));
+ __ test(edx, Immediate(1 << Map::kNeedsLoading));
+ __ j(not_zero, miss, not_taken);
// Patch the receiver with the global proxy if necessary.
if (is_global_object) {
@@ -681,7 +679,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
// Search the dictionary placing the result in eax.
__ bind(&probe);
GenerateDictionaryLoad(masm, &miss, edx, eax, ebx, ecx);
- GenerateCheckNonFunctionOrLoaded(masm, &miss, eax, edx);
+ GenerateCheckNonObjectOrLoaded(masm, &miss, eax, edx);
__ ret(0);
// Global object access: Check access rights.
@@ -727,24 +725,70 @@ void LoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
}
-void KeyedLoadIC::PatchInlinedMapCheck(Address address, Object* value) {
- static const byte kTestEaxByte = 0xA9;
+// One byte opcode for test eax,0xXXXXXXXX.
+static const byte kTestEaxByte = 0xA9;
+
+
+void LoadIC::ClearInlinedVersion(Address address) {
+ // Reset the map check of the inlined inobject property load (if
+ // present) to guarantee failure by holding an invalid map (the null
+ // value). The offset can be patched to anything.
+ PatchInlinedLoad(address, Heap::null_value(), kMaxInt);
+}
+
+
+void KeyedLoadIC::ClearInlinedVersion(Address address) {
+ // Insert null as the map to check for to make sure the map check fails
+ // sending control flow to the IC instead of the inlined version.
+ PatchInlinedLoad(address, Heap::null_value());
+}
+
+
+bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) {
+ // The address of the instruction following the call.
+ Address test_instruction_address = address + 4;
+ // If the instruction following the call is not a test eax, nothing
+ // was inlined.
+ if (*test_instruction_address != kTestEaxByte) return false;
+
+ Address delta_address = test_instruction_address + 1;
+ // The delta to the start of the map check instruction.
+ int delta = *reinterpret_cast<int*>(delta_address);
+
+ // The map address is the last 4 bytes of the 7-byte
+ // operand-immediate compare instruction, so we add 3 to get the
+ // offset to the last 4 bytes.
+ Address map_address = test_instruction_address + delta + 3;
+ *(reinterpret_cast<Object**>(map_address)) = map;
+
+ // The offset is in the last 4 bytes of a six byte
+ // memory-to-register move instruction, so we add 2 to get the
+ // offset to the last 4 bytes.
+ Address offset_address =
+ test_instruction_address + delta + kOffsetToLoadInstruction + 2;
+ *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag;
+ return true;
+}
+
+
+bool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) {
Address test_instruction_address = address + 4; // 4 = stub address
// The keyed load has a fast inlined case if the IC call instruction
// is immediately followed by a test instruction.
- if (*test_instruction_address == kTestEaxByte) {
- // Fetch the offset from the test instruction to the map cmp
- // instruction. This offset is stored in the last 4 bytes of the
- // 5 byte test instruction.
- Address offset_address = test_instruction_address + 1;
- int offset_value = *(reinterpret_cast<int*>(offset_address));
- // Compute the map address. The map address is in the last 4
- // bytes of the 7-byte operand-immediate compare instruction, so
- // we add 3 to the offset to get the map address.
- Address map_address = test_instruction_address + offset_value + 3;
- // patch the map check.
- (*(reinterpret_cast<Object**>(map_address))) = value;
- }
+ if (*test_instruction_address != kTestEaxByte) return false;
+
+ // Fetch the offset from the test instruction to the map cmp
+ // instruction. This offset is stored in the last 4 bytes of the 5
+ // byte test instruction.
+ Address delta_address = test_instruction_address + 1;
+ int delta = *reinterpret_cast<int*>(delta_address);
+ // Compute the map address. The map address is in the last 4 bytes
+ // of the 7-byte operand-immediate compare instruction, so we add 3
+ // to the offset to get the map address.
+ Address map_address = test_instruction_address + delta + 3;
+ // Patch the map check.
+ *(reinterpret_cast<Object**>(map_address)) = map;
+ return true;
}
diff --git a/deps/v8/src/jump-target-ia32.cc b/deps/v8/src/ia32/jump-target-ia32.cc
index 8afb0a8ad..6c7d6e35b 100644
--- a/deps/v8/src/jump-target-ia32.cc
+++ b/deps/v8/src/ia32/jump-target-ia32.cc
@@ -35,7 +35,7 @@ namespace v8 { namespace internal {
// -------------------------------------------------------------------------
// JumpTarget implementation.
-#define __ masm_->
+#define __ ACCESS_MASM(masm_)
void JumpTarget::DoJump() {
ASSERT(cgen_ != NULL);
@@ -115,11 +115,13 @@ void JumpTarget::DoBranch(Condition cc, Hint hint) {
__ bind(&original_fall_through);
} else {
- // Forward branch. A copy of the current frame is added to the end
- // of the list of frames reaching the target block and a branch to
- // the merge code is emitted.
+ // Forward branch. A copy of the current frame is added to the end of the
+ // list of frames reaching the target block and a branch to the merge code
+ // is emitted. Use masm_-> instead of __ as forward branches are expected
+ // to be a fixed size (no inserted coverage-checking instructions please).
+ // This is used in Reference::GetValue.
AddReachingFrame(new VirtualFrame(cgen_->frame()));
- __ j(cc, &merge_labels_.last(), hint);
+ masm_->j(cc, &merge_labels_.last(), hint);
is_linked_ = true;
}
}
diff --git a/deps/v8/src/macro-assembler-ia32.cc b/deps/v8/src/ia32/macro-assembler-ia32.cc
index 4fad3be67..d6d5800fe 100644
--- a/deps/v8/src/macro-assembler-ia32.cc
+++ b/deps/v8/src/ia32/macro-assembler-ia32.cc
@@ -216,6 +216,7 @@ void MacroAssembler::RecordWrite(Register object, int offset,
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
void MacroAssembler::SaveRegistersToMemory(RegList regs) {
ASSERT((regs & ~kJSCallerSaved) == 0);
// Copy the content of registers to memory location.
@@ -290,7 +291,7 @@ void MacroAssembler::CopyRegistersFromStackToMemory(Register base,
}
}
}
-
+#endif
void MacroAssembler::Set(Register dst, const Immediate& x) {
if (x.is_zero()) {
@@ -378,6 +379,7 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
mov(edi, Operand(eax));
lea(esi, Operand(ebp, eax, times_4, offset));
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Save the state of all registers to the stack from the memory
// location. This is needed to allow nested break points.
if (type == StackFrame::EXIT_DEBUG) {
@@ -389,6 +391,7 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
// associated with this issue).
PushRegistersFromMemory(kJSCallerSaved);
}
+#endif
// Reserve space for two arguments: argc and argv.
sub(Operand(esp), Immediate(2 * kPointerSize));
@@ -406,6 +409,7 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Restore the memory copy of the registers by digging them out from
// the stack. This is needed to allow nested break points.
if (type == StackFrame::EXIT_DEBUG) {
@@ -416,6 +420,7 @@ void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
lea(ebx, Operand(ebp, kOffset));
CopyRegistersFromStackToMemory(ebx, ecx, kJSCallerSaved);
}
+#endif
// Get the return address from the stack and restore the frame pointer.
mov(ecx, Operand(ebp, 1 * kPointerSize));
@@ -427,9 +432,9 @@ void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
// Restore current context from top and clear it in debug mode.
ExternalReference context_address(Top::k_context_address);
mov(esi, Operand::StaticVariable(context_address));
- if (kDebug) {
- mov(Operand::StaticVariable(context_address), Immediate(0));
- }
+#ifdef DEBUG
+ mov(Operand::StaticVariable(context_address), Immediate(0));
+#endif
// Push the return address to get ready to return.
push(ecx);
diff --git a/deps/v8/src/ia32/macro-assembler-ia32.h b/deps/v8/src/ia32/macro-assembler-ia32.h
new file mode 100644
index 000000000..cd7a23391
--- /dev/null
+++ b/deps/v8/src/ia32/macro-assembler-ia32.h
@@ -0,0 +1,371 @@
+// Copyright 2006-2008 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_IA32_MACRO_ASSEMBLER_IA32_H_
+#define V8_IA32_MACRO_ASSEMBLER_IA32_H_
+
+#include "assembler.h"
+
+namespace v8 { namespace internal {
+
+// Forward declaration.
+class JumpTarget;
+
+
+// Helper types to make flags easier to read at call sites.
+enum InvokeFlag {
+ CALL_FUNCTION,
+ JUMP_FUNCTION
+};
+
+enum CodeLocation {
+ IN_JAVASCRIPT,
+ IN_JS_ENTRY,
+ IN_C_ENTRY
+};
+
+enum HandlerType {
+ TRY_CATCH_HANDLER,
+ TRY_FINALLY_HANDLER,
+ JS_ENTRY_HANDLER
+};
+
+
+// MacroAssembler implements a collection of frequently used macros.
+class MacroAssembler: public Assembler {
+ public:
+ MacroAssembler(void* buffer, int size);
+
+ // ---------------------------------------------------------------------------
+ // GC Support
+
+ // Set the remembered set bit for [object+offset].
+ // object is the object being stored into, value is the object being stored.
+ // If offset is zero, then the scratch register contains the array index into
+ // the elements array represented as a Smi.
+ // All registers are clobbered by the operation.
+ void RecordWrite(Register object,
+ int offset,
+ Register value,
+ Register scratch);
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+ // ---------------------------------------------------------------------------
+ // Debugger Support
+
+ void SaveRegistersToMemory(RegList regs);
+ void RestoreRegistersFromMemory(RegList regs);
+ void PushRegistersFromMemory(RegList regs);
+ void PopRegistersToMemory(RegList regs);
+ void CopyRegistersFromStackToMemory(Register base,
+ Register scratch,
+ RegList regs);
+#endif
+
+ // ---------------------------------------------------------------------------
+ // Activation frames
+
+ void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }
+ void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); }
+
+ void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
+ void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
+
+ // Enter specific kind of exit frame; either EXIT or
+ // EXIT_DEBUG. Expects the number of arguments in register eax and
+ // sets up the number of arguments in register edi and the pointer
+ // to the first argument in register esi.
+ void EnterExitFrame(StackFrame::Type type);
+
+ // Leave the current exit frame. Expects the return value in
+ // register eax:edx (untouched) and the pointer to the first
+ // argument in register esi.
+ void LeaveExitFrame(StackFrame::Type type);
+
+
+ // ---------------------------------------------------------------------------
+ // JavaScript invokes
+
+ // Invoke the JavaScript function code by either calling or jumping.
+ void InvokeCode(const Operand& code,
+ const ParameterCount& expected,
+ const ParameterCount& actual,
+ InvokeFlag flag);
+
+ void InvokeCode(Handle<Code> code,
+ const ParameterCount& expected,
+ const ParameterCount& actual,
+ RelocInfo::Mode rmode,
+ InvokeFlag flag);
+
+ // Invoke the JavaScript function in the given register. Changes the
+ // current context to the context in the function before invoking.
+ void InvokeFunction(Register function,
+ const ParameterCount& actual,
+ InvokeFlag flag);
+
+ // Invoke specified builtin JavaScript function. Adds an entry to
+ // the unresolved list if the name does not resolve.
+ void InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag);
+
+ // Store the code object for the given builtin in the target register.
+ void GetBuiltinEntry(Register target, Builtins::JavaScript id);
+
+ // Expression support
+ void Set(Register dst, const Immediate& x);
+ void Set(const Operand& dst, const Immediate& x);
+
+ // Compare object type for heap object.
+ // Incoming register is heap_object and outgoing register is map.
+ void CmpObjectType(Register heap_object, InstanceType type, Register map);
+
+ // Compare instance type for map.
+ void CmpInstanceType(Register map, InstanceType type);
+
+ // FCmp is similar to integer cmp, but requires unsigned
+ // jcc instructions (je, ja, jae, jb, jbe, je, and jz).
+ void FCmp();
+
+ // ---------------------------------------------------------------------------
+ // Exception handling
+
+ // Push a new try handler and link into try handler chain.
+ // The return address must be pushed before calling this helper.
+ // On exit, eax contains TOS (next_sp).
+ void PushTryHandler(CodeLocation try_location, HandlerType type);
+
+
+ // ---------------------------------------------------------------------------
+ // Inline caching support
+
+ // Generates code that verifies that the maps of objects in the
+ // prototype chain of object hasn't changed since the code was
+ // generated and branches to the miss label if any map has. If
+ // necessary the function also generates code for security check
+ // in case of global object holders. The scratch and holder
+ // registers are always clobbered, but the object register is only
+ // clobbered if it the same as the holder register. The function
+ // returns a register containing the holder - either object_reg or
+ // holder_reg.
+ Register CheckMaps(JSObject* object, Register object_reg,
+ JSObject* holder, Register holder_reg,
+ Register scratch, Label* miss);
+
+ // Generate code for checking access rights - used for security checks
+ // on access to global objects across environments. The holder register
+ // is left untouched, but the scratch register is clobbered.
+ void CheckAccessGlobalProxy(Register holder_reg,
+ Register scratch,
+ Label* miss);
+
+
+ // ---------------------------------------------------------------------------
+ // Support functions.
+
+ // Check if result is zero and op is negative.
+ void NegativeZeroTest(Register result, Register op, Label* then_label);
+
+ // Check if result is zero and op is negative in code using jump targets.
+ void NegativeZeroTest(CodeGenerator* cgen,
+ Register result,
+ Register op,
+ JumpTarget* then_target);
+
+ // Check if result is zero and any of op1 and op2 are negative.
+ // Register scratch is destroyed, and it must be different from op2.
+ void NegativeZeroTest(Register result, Register op1, Register op2,
+ Register scratch, Label* then_label);
+
+ // Try to get function prototype of a function and puts the value in
+ // the result register. Checks that the function really is a
+ // function and jumps to the miss label if the fast checks fail. The
+ // function register will be untouched; the other registers may be
+ // clobbered.
+ void TryGetFunctionPrototype(Register function,
+ Register result,
+ Register scratch,
+ Label* miss);
+
+ // Generates code for reporting that an illegal operation has
+ // occurred.
+ void IllegalOperation(int num_arguments);
+
+ // ---------------------------------------------------------------------------
+ // Runtime calls
+
+ // Call a code stub.
+ void CallStub(CodeStub* stub);
+
+ // Return from a code stub after popping its arguments.
+ void StubReturn(int argc);
+
+ // Call a runtime routine.
+ // Eventually this should be used for all C calls.
+ void CallRuntime(Runtime::Function* f, int num_arguments);
+
+ // Convenience function: Same as above, but takes the fid instead.
+ void CallRuntime(Runtime::FunctionId id, int num_arguments);
+
+ // Tail call of a runtime routine (jump).
+ // Like JumpToBuiltin, but also takes care of passing the number
+ // of arguments.
+ void TailCallRuntime(const ExternalReference& ext, int num_arguments);
+
+ // Jump to the builtin routine.
+ void JumpToBuiltin(const ExternalReference& ext);
+
+
+ // ---------------------------------------------------------------------------
+ // Utilities
+
+ void Ret();
+
+ struct Unresolved {
+ int pc;
+ uint32_t flags; // see Bootstrapper::FixupFlags decoders/encoders.
+ const char* name;
+ };
+ List<Unresolved>* unresolved() { return &unresolved_; }
+
+ Handle<Object> CodeObject() { return code_object_; }
+
+
+ // ---------------------------------------------------------------------------
+ // StatsCounter support
+
+ void SetCounter(StatsCounter* counter, int value);
+ void IncrementCounter(StatsCounter* counter, int value);
+ void DecrementCounter(StatsCounter* counter, int value);
+
+
+ // ---------------------------------------------------------------------------
+ // Debugging
+
+ // Calls Abort(msg) if the condition cc is not satisfied.
+ // Use --debug_code to enable.
+ void Assert(Condition cc, const char* msg);
+
+ // Like Assert(), but always enabled.
+ void Check(Condition cc, const char* msg);
+
+ // Print a message to stdout and abort execution.
+ void Abort(const char* msg);
+
+ // Verify restrictions about code generated in stubs.
+ void set_generating_stub(bool value) { generating_stub_ = value; }
+ bool generating_stub() { return generating_stub_; }
+ void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
+ bool allow_stub_calls() { return allow_stub_calls_; }
+
+ private:
+ List<Unresolved> unresolved_;
+ bool generating_stub_;
+ bool allow_stub_calls_;
+ Handle<Object> code_object_; // This handle will be patched with the code
+ // code object on installation.
+
+ // Helper functions for generating invokes.
+ void InvokePrologue(const ParameterCount& expected,
+ const ParameterCount& actual,
+ Handle<Code> code_constant,
+ const Operand& code_operand,
+ Label* done,
+ InvokeFlag flag);
+
+ // Get the code for the given builtin. Returns if able to resolve
+ // the function in the 'resolved' flag.
+ Handle<Code> ResolveBuiltin(Builtins::JavaScript id, bool* resolved);
+
+ // Activation support.
+ void EnterFrame(StackFrame::Type type);
+ void LeaveFrame(StackFrame::Type type);
+};
+
+
+// The code patcher is used to patch (typically) small parts of code e.g. for
+// debugging and other types of instrumentation. When using the code patcher
+// the exact number of bytes specified must be emitted. Is not legal to emit
+// relocation information. If any of these constraints are violated it causes
+// an assertion.
+class CodePatcher {
+ public:
+ CodePatcher(byte* address, int size);
+ virtual ~CodePatcher();
+
+ // Macro assembler to emit code.
+ MacroAssembler* masm() { return &masm_; }
+
+ private:
+ byte* address_; // The address of the code being patched.
+ int size_; // Number of bytes of the expected patch size.
+ MacroAssembler masm_; // Macro assembler used to generate the code.
+};
+
+
+// -----------------------------------------------------------------------------
+// Static helper functions.
+
+// Generate an Operand for loading a field from an object.
+static inline Operand FieldOperand(Register object, int offset) {
+ return Operand(object, offset - kHeapObjectTag);
+}
+
+
+// Generate an Operand for loading an indexed field from an object.
+static inline Operand FieldOperand(Register object,
+ Register index,
+ ScaleFactor scale,
+ int offset) {
+ return Operand(object, index, scale, offset - kHeapObjectTag);
+}
+
+
+#ifdef GENERATED_CODE_COVERAGE
+extern void LogGeneratedCodeCoverage(const char* file_line);
+#define CODE_COVERAGE_STRINGIFY(x) #x
+#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
+#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
+#define ACCESS_MASM(masm) { \
+ byte* ia32_coverage_function = \
+ reinterpret_cast<byte*>(FUNCTION_ADDR(LogGeneratedCodeCoverage)); \
+ masm->pushfd(); \
+ masm->pushad(); \
+ masm->push(Immediate(reinterpret_cast<int>(&__FILE_LINE__))); \
+ masm->call(ia32_coverage_function, RelocInfo::RUNTIME_ENTRY); \
+ masm->pop(eax); \
+ masm->popad(); \
+ masm->popfd(); \
+ } \
+ masm->
+#else
+#define ACCESS_MASM(masm) masm->
+#endif
+
+
+} } // namespace v8::internal
+
+#endif // V8_IA32_MACRO_ASSEMBLER_IA32_H_
diff --git a/deps/v8/src/regexp-macro-assembler-ia32.cc b/deps/v8/src/ia32/regexp-macro-assembler-ia32.cc
index c2f76b4de..2a0cefd77 100644
--- a/deps/v8/src/regexp-macro-assembler-ia32.cc
+++ b/deps/v8/src/ia32/regexp-macro-assembler-ia32.cc
@@ -32,8 +32,8 @@
#include "regexp-stack.h"
#include "macro-assembler.h"
#include "regexp-macro-assembler.h"
-#include "macro-assembler-ia32.h"
-#include "regexp-macro-assembler-ia32.h"
+#include "ia32/macro-assembler-ia32.h"
+#include "ia32/regexp-macro-assembler-ia32.h"
namespace v8 { namespace internal {
@@ -86,7 +86,7 @@ namespace v8 { namespace internal {
* byte* stack_area_top)
*/
-#define __ masm_->
+#define __ ACCESS_MASM(masm_)
RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32(
Mode mode,
@@ -974,7 +974,7 @@ RegExpMacroAssemblerIA32::Result RegExpMacroAssemblerIA32::Match(
int start_offset = previous_index;
int end_offset = subject_ptr->length();
- bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
+ bool is_ascii = subject->IsAsciiRepresentation();
if (StringShape(subject_ptr).IsCons()) {
subject_ptr = ConsString::cast(subject_ptr)->first();
@@ -985,7 +985,7 @@ RegExpMacroAssemblerIA32::Result RegExpMacroAssemblerIA32::Match(
subject_ptr = slice->buffer();
}
// Ensure that an underlying string has the same ascii-ness.
- ASSERT(StringShape(subject_ptr).IsAsciiRepresentation() == is_ascii);
+ ASSERT(subject_ptr->IsAsciiRepresentation() == is_ascii);
ASSERT(subject_ptr->IsExternalString() || subject_ptr->IsSeqString());
// String is now either Sequential or External
int char_size_shift = is_ascii ? 0 : 1;
@@ -1112,7 +1112,7 @@ const byte* RegExpMacroAssemblerIA32::StringCharacterPosition(String* subject,
ASSERT(subject->IsExternalString() || subject->IsSeqString());
ASSERT(start_index >= 0);
ASSERT(start_index <= subject->length());
- if (StringShape(subject).IsAsciiRepresentation()) {
+ if (subject->IsAsciiRepresentation()) {
const byte* address;
if (StringShape(subject).IsExternal()) {
const char* data = ExternalAsciiString::cast(subject)->resource()->data();
@@ -1152,7 +1152,7 @@ int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address,
Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
// Current string.
- bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
+ bool is_ascii = subject->IsAsciiRepresentation();
ASSERT(re_code->instruction_start() <= *return_address);
ASSERT(*return_address <=
@@ -1171,7 +1171,7 @@ int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address,
}
// String might have changed.
- if (StringShape(*subject).IsAsciiRepresentation() != is_ascii) {
+ if (subject->IsAsciiRepresentation() != is_ascii) {
// If we changed between an ASCII and an UC16 string, the specialized
// code cannot be used, and we need to restart regexp matching from
// scratch (including, potentially, compiling a new version of the code).
diff --git a/deps/v8/src/regexp-macro-assembler-ia32.h b/deps/v8/src/ia32/regexp-macro-assembler-ia32.h
index 0309f2004..8c5dd24cc 100644
--- a/deps/v8/src/regexp-macro-assembler-ia32.h
+++ b/deps/v8/src/ia32/regexp-macro-assembler-ia32.h
@@ -25,8 +25,8 @@
// (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 REGEXP_MACRO_ASSEMBLER_IA32_H_
-#define REGEXP_MACRO_ASSEMBLER_IA32_H_
+#ifndef V8_IA32_REGEXP_MACRO_ASSEMBLER_IA32_H_
+#define V8_IA32_REGEXP_MACRO_ASSEMBLER_IA32_H_
namespace v8 { namespace internal {
@@ -282,4 +282,4 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
}} // namespace v8::internal
-#endif /* REGEXP_MACRO_ASSEMBLER_IA32_H_ */
+#endif // V8_IA32_REGEXP_MACRO_ASSEMBLER_IA32_H_
diff --git a/deps/v8/src/register-allocator-ia32.cc b/deps/v8/src/ia32/register-allocator-ia32.cc
index a89882748..b72d76556 100644
--- a/deps/v8/src/register-allocator-ia32.cc
+++ b/deps/v8/src/ia32/register-allocator-ia32.cc
@@ -97,6 +97,12 @@ void RegisterAllocator::UnuseReserved(RegisterFile* register_file) {
}
+bool RegisterAllocator::IsReserved(int reg_code) {
+ // Test below relies on the order of register codes.
+ return reg_code >= esp.code() && reg_code <= esi.code();
+}
+
+
void RegisterAllocator::Initialize() {
Reset();
// The following register is live on function entry, saved in the
diff --git a/deps/v8/src/simulator-ia32.cc b/deps/v8/src/ia32/simulator-ia32.cc
index ab8169375..ab8169375 100644
--- a/deps/v8/src/simulator-ia32.cc
+++ b/deps/v8/src/ia32/simulator-ia32.cc
diff --git a/deps/v8/src/simulator-ia32.h b/deps/v8/src/ia32/simulator-ia32.h
index 2267721cf..4d02c03ab 100644
--- a/deps/v8/src/simulator-ia32.h
+++ b/deps/v8/src/ia32/simulator-ia32.h
@@ -25,8 +25,8 @@
// (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_SIMULATOR_IA32_H_
-#define V8_SIMULATOR_IA32_H_
+#ifndef V8_IA32_SIMULATOR_IA32_H_
+#define V8_IA32_SIMULATOR_IA32_H_
// Since there is no simulator for the ia32 architecture the only thing we can
@@ -44,4 +44,4 @@
(reinterpret_cast<uintptr_t>(this) >= limit ? \
reinterpret_cast<uintptr_t>(this) - limit : 0)
-#endif // V8_SIMULATOR_IA32_H_
+#endif // V8_IA32_SIMULATOR_IA32_H_
diff --git a/deps/v8/src/stub-cache-ia32.cc b/deps/v8/src/ia32/stub-cache-ia32.cc
index 19777e6a7..bdfc3d6c3 100644
--- a/deps/v8/src/stub-cache-ia32.cc
+++ b/deps/v8/src/ia32/stub-cache-ia32.cc
@@ -33,7 +33,7 @@
namespace v8 { namespace internal {
-#define __ masm->
+#define __ ACCESS_MASM(masm)
static void ProbeTable(MacroAssembler* masm,
@@ -256,7 +256,7 @@ void StubCompiler::GenerateLoadField(MacroAssembler* masm,
// Check that the maps haven't changed.
Register reg =
- __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+ masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
// Get the value from the properties.
GenerateFastPropertyLoad(masm, eax, reg, holder, index);
@@ -279,7 +279,7 @@ void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
// Check that the maps haven't changed.
Register reg =
- __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+ masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
// Push the arguments on the JS stack of the caller.
__ pop(scratch2); // remove return address
@@ -310,7 +310,7 @@ void StubCompiler::GenerateLoadConstant(MacroAssembler* masm,
// Check that the maps haven't changed.
Register reg =
- __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+ masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
// Return the constant value.
__ mov(eax, Handle<Object>(value));
@@ -332,7 +332,7 @@ void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
// Check that the maps haven't changed.
Register reg =
- __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
+ masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
// Push the arguments on the JS stack of the caller.
__ pop(scratch2); // remove return address
@@ -440,7 +440,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
#undef __
-#define __ masm()->
+#define __ ACCESS_MASM(masm())
// TODO(1241006): Avoid having lazy compile stubs specialized by the
@@ -485,7 +485,7 @@ Object* CallStubCompiler::CompileCallField(Object* object,
// Do the right check and compute the holder register.
Register reg =
- __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
+ masm()->CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
GenerateFastPropertyLoad(masm(), edi, reg, holder, index);
@@ -656,7 +656,7 @@ Object* CallStubCompiler::CompileCallInterceptor(Object* object,
// Check that maps have not changed and compute the holder register.
Register reg =
- __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
+ masm()->CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
// Enter an internal frame.
__ EnterInternalFrame();
diff --git a/deps/v8/src/virtual-frame-ia32.cc b/deps/v8/src/ia32/virtual-frame-ia32.cc
index eb3befca3..ff9f60cdf 100644
--- a/deps/v8/src/virtual-frame-ia32.cc
+++ b/deps/v8/src/ia32/virtual-frame-ia32.cc
@@ -33,7 +33,7 @@
namespace v8 { namespace internal {
-#define __ masm_->
+#define __ ACCESS_MASM(masm_)
// -------------------------------------------------------------------------
// VirtualFrame implementation.
@@ -158,6 +158,28 @@ void VirtualFrame::SyncElementByPushing(int index) {
}
+// Clear the dirty bits for the range of elements in
+// [min(stack_pointer_ + 1,begin), end].
+void VirtualFrame::SyncRange(int begin, int end) {
+ ASSERT(begin >= 0);
+ ASSERT(end < elements_.length());
+ // Sync elements below the range if they have not been materialized
+ // on the stack.
+ int start = Min(begin, stack_pointer_ + 1);
+
+ // If positive we have to adjust the stack pointer.
+ int delta = end - stack_pointer_;
+ if (delta > 0) {
+ stack_pointer_ = end;
+ __ sub(Operand(esp), Immediate(delta * kPointerSize));
+ }
+
+ for (int i = start; i <= end; i++) {
+ if (!elements_[i].is_synced()) SyncElementBelowStackPointer(i);
+ }
+}
+
+
void VirtualFrame::MergeTo(VirtualFrame* expected) {
Comment cmnt(masm_, "[ Merge frame");
// We should always be merging the code generator's current frame to an
@@ -288,64 +310,33 @@ void VirtualFrame::MergeMoveRegistersToRegisters(VirtualFrame* expected) {
// We have already done X-to-memory moves.
ASSERT(stack_pointer_ >= expected->stack_pointer_);
- // Perform register-to-register moves.
- int start = 0;
- int end = elements_.length() - 1;
- bool any_moves_blocked; // Did we fail to make some moves this iteration?
- bool should_break_cycles = false;
- bool any_moves_made; // Did we make any progress this iteration?
- do {
- any_moves_blocked = false;
- any_moves_made = false;
- int first_move_blocked = kIllegalIndex;
- int last_move_blocked = kIllegalIndex;
- for (int i = start; i <= end; i++) {
- FrameElement source = elements_[i];
- FrameElement target = expected->elements_[i];
- if (source.is_register() && target.is_register()) {
- if (target.reg().is(source.reg())) {
- if (target.is_synced() && !source.is_synced()) {
- __ mov(Operand(ebp, fp_relative(i)), source.reg());
- }
- elements_[i] = target;
- } else {
- // We need to move source to target.
- if (is_used(target.reg())) {
- // The move is blocked because the target contains valid data.
- // If we are stuck with only cycles remaining, then we spill source.
- // Otherwise, we just need more iterations.
- if (should_break_cycles) {
- SpillElementAt(i);
- should_break_cycles = false;
- } else { // Record a blocked move.
- if (!any_moves_blocked) {
- first_move_blocked = i;
- }
- last_move_blocked = i;
- any_moves_blocked = true;
- }
- } else {
- // The move is not blocked. This frame element can be moved from
- // its source register to its target register.
- if (target.is_synced() && !source.is_synced()) {
- SyncElementAt(i);
- }
- Use(target.reg(), i);
- Unuse(source.reg());
- elements_[i] = target;
- __ mov(target.reg(), source.reg());
- any_moves_made = true;
- }
- }
+ for (int i = 0; i < kNumRegisters; i++) {
+ // Move the right value into register i if it is currently in a register.
+ int index = expected->register_locations_[i];
+ int use_index = register_locations_[i];
+ // Fast check if register is unused in target or already correct
+ if (index != kIllegalIndex
+ && index != use_index
+ && elements_[index].is_register()) {
+ Register source = elements_[index].reg();
+ Register target = { i };
+ if (use_index == kIllegalIndex) { // Target is currently unused.
+ // Copy contents of source from source to target.
+ // Set frame element register to target.
+ elements_[index].set_reg(target);
+ Use(target, index);
+ Unuse(source);
+ __ mov(target, source);
+ } else {
+ // Exchange contents of registers source and target.
+ elements_[use_index].set_reg(source);
+ elements_[index].set_reg(target);
+ register_locations_[target.code()] = index;
+ register_locations_[source.code()] = use_index;
+ __ xchg(source, target);
}
}
- // Update control flags for next iteration.
- should_break_cycles = (any_moves_blocked && !any_moves_made);
- if (any_moves_blocked) {
- start = first_move_blocked;
- end = last_move_blocked;
- }
- } while (any_moves_blocked);
+ }
}
@@ -354,19 +345,22 @@ void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame *expected) {
// final step and is done from the bottom up so that the backing
// elements of copies are in their correct locations when we
// encounter the copies.
- for (int i = 0; i < elements_.length(); i++) {
- FrameElement source = elements_[i];
- FrameElement target = expected->elements_[i];
- if (target.is_register() && !source.is_register()) {
+ for (int i = 0; i < kNumRegisters; i++) {
+ int index = expected->register_locations_[i];
+ if (index != kIllegalIndex) {
+ FrameElement source = elements_[index];
+ FrameElement target = expected->elements_[index];
switch (source.type()) {
case FrameElement::INVALID: // Fall through.
- case FrameElement::REGISTER:
UNREACHABLE();
break;
-
+ case FrameElement::REGISTER:
+ ASSERT(source.reg().is(target.reg()));
+ continue; // Go to next iteration. Skips Use(target.reg()) below.
+ break;
case FrameElement::MEMORY:
- ASSERT(i <= stack_pointer_);
- __ mov(target.reg(), Operand(ebp, fp_relative(i)));
+ ASSERT(index <= stack_pointer_);
+ __ mov(target.reg(), Operand(ebp, fp_relative(index)));
break;
case FrameElement::CONSTANT:
@@ -378,11 +372,25 @@ void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame *expected) {
break;
case FrameElement::COPY: {
- FrameElement backing = elements_[source.index()];
+ int backing_index = source.index();
+ FrameElement backing = elements_[backing_index];
ASSERT(backing.is_memory() || backing.is_register());
if (backing.is_memory()) {
- ASSERT(source.index() <= stack_pointer_);
- __ mov(target.reg(), Operand(ebp, fp_relative(source.index())));
+ ASSERT(backing_index <= stack_pointer_);
+ // Code optimization if backing store should also move
+ // to a register: move backing store to its register first.
+ if (expected->elements_[backing_index].is_register()) {
+ FrameElement new_backing = expected->elements_[backing_index];
+ Register new_backing_reg = new_backing.reg();
+ ASSERT(!is_used(new_backing_reg));
+ elements_[backing_index] = new_backing;
+ Use(new_backing_reg, backing_index);
+ __ mov(new_backing_reg,
+ Operand(ebp, fp_relative(backing_index)));
+ __ mov(target.reg(), new_backing_reg);
+ } else {
+ __ mov(target.reg(), Operand(ebp, fp_relative(backing_index)));
+ }
} else {
__ mov(target.reg(), backing.reg());
}
@@ -390,11 +398,11 @@ void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame *expected) {
}
// Ensure the proper sync state. If the source was memory no
// code needs to be emitted.
- if (target.is_synced() && !source.is_memory()) {
- SyncElementAt(i);
+ if (target.is_synced() && !source.is_synced()) {
+ __ mov(Operand(ebp, fp_relative(index)), target.reg());
}
- Use(target.reg(), i);
- elements_[i] = target;
+ Use(target.reg(), index);
+ elements_[index] = target;
}
}
}
@@ -467,7 +475,7 @@ void VirtualFrame::AllocateStackSlots(int count) {
// we sync them with the actual frame to allocate space for spilling
// them later. First sync everything above the stack pointer so we can
// use pushes to allocate and initialize the locals.
- SyncRange(stack_pointer_ + 1, elements_.length());
+ SyncRange(stack_pointer_ + 1, elements_.length() - 1);
Handle<Object> undefined = Factory::undefined_value();
FrameElement initial_value =
FrameElement::ConstantElement(undefined, FrameElement::SYNCED);
@@ -615,6 +623,12 @@ void VirtualFrame::StoreToFrameSlotAt(int index) {
InvalidateFrameSlotAt(index);
+ // InvalidateFrameSlotAt can potentially change any frame element, due
+ // to spilling registers to allocate temporaries in order to preserve
+ // the copy-on-write semantics of aliased elements. Reload top from
+ // the frame.
+ top = elements_[top_index];
+
if (top.is_copy()) {
// There are two cases based on the relative positions of the
// stored-to slot and the backing slot of the top element.
diff --git a/deps/v8/src/virtual-frame-ia32.h b/deps/v8/src/ia32/virtual-frame-ia32.h
index 113ccc692..298eda21d 100644
--- a/deps/v8/src/virtual-frame-ia32.h
+++ b/deps/v8/src/ia32/virtual-frame-ia32.h
@@ -25,8 +25,8 @@
// (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_VIRTUAL_FRAME_IA32_H_
-#define V8_VIRTUAL_FRAME_IA32_H_
+#ifndef V8_IA32_VIRTUAL_FRAME_IA32_H_
+#define V8_IA32_VIRTUAL_FRAME_IA32_H_
#include "register-allocator.h"
@@ -490,4 +490,4 @@ class VirtualFrame : public Malloced {
} } // namespace v8::internal
-#endif // V8_VIRTUAL_FRAME_IA32_H_
+#endif // V8_IA32_VIRTUAL_FRAME_IA32_H_
diff --git a/deps/v8/src/ic-inl.h b/deps/v8/src/ic-inl.h
index f5ce0adf1..bb5696281 100644
--- a/deps/v8/src/ic-inl.h
+++ b/deps/v8/src/ic-inl.h
@@ -39,6 +39,7 @@ Address IC::address() {
// Get the address of the call.
Address result = pc() - Assembler::kTargetAddrToReturnAddrDist;
+#ifdef ENABLE_DEBUGGER_SUPPORT
// First check if any break points are active if not just return the address
// of the call.
if (!Debug::has_break_points()) return result;
@@ -55,6 +56,9 @@ Address IC::address() {
// No break point here just return the address of the call.
return result;
}
+#else
+ return result;
+#endif
}
diff --git a/deps/v8/src/ic.cc b/deps/v8/src/ic.cc
index d7bd76440..ccdf3cab4 100644
--- a/deps/v8/src/ic.cc
+++ b/deps/v8/src/ic.cc
@@ -42,7 +42,7 @@ static char TransitionMarkFromState(IC::State state) {
switch (state) {
case UNINITIALIZED: return '0';
case UNINITIALIZED_IN_LOOP: return 'L';
- case PREMONOMORPHIC: return '0';
+ case PREMONOMORPHIC: return 'P';
case MONOMORPHIC: return '1';
case MONOMORPHIC_PROTOTYPE_FAILURE: return '^';
case MEGAMORPHIC: return 'N';
@@ -100,6 +100,7 @@ IC::IC(FrameDepth depth) {
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
Address IC::OriginalCodeAddress() {
HandleScope scope;
// Compute the JavaScript frame for the frame pointer of this IC
@@ -126,7 +127,7 @@ Address IC::OriginalCodeAddress() {
int delta = original_code->instruction_start() - code->instruction_start();
return addr + delta;
}
-
+#endif
IC::State IC::StateFrom(Code* target, Object* receiver) {
IC::State state = target->ic_state();
@@ -236,13 +237,14 @@ void KeyedLoadIC::Clear(Address address, Code* target) {
// Make sure to also clear the map used in inline fast cases. If we
// do not clear these maps, cached code can keep objects alive
// through the embedded maps.
- PatchInlinedMapCheck(address, Heap::null_value());
+ ClearInlinedVersion(address);
SetTargetAtAddress(address, initialize_stub());
}
void LoadIC::Clear(Address address, Code* target) {
if (target->ic_state() == UNINITIALIZED) return;
+ ClearInlinedVersion(address);
SetTargetAtAddress(address, initialize_stub());
}
@@ -356,6 +358,7 @@ Object* CallIC::LoadFunction(State state,
if (opt->IsJSFunction()) return opt;
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Handle stepping into a function if step into is active.
if (Debug::StepInActive()) {
// Protect the result in a handle as the debugger can allocate and might
@@ -365,6 +368,7 @@ Object* CallIC::LoadFunction(State state,
Debug::HandleStepIn(function, fp(), false);
return *function;
}
+#endif
return result;
}
@@ -520,6 +524,31 @@ Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) {
LOG(SuspectReadEvent(*name, *object));
}
+ bool can_be_inlined =
+ FLAG_use_ic &&
+ state == PREMONOMORPHIC &&
+ lookup.IsValid() &&
+ lookup.IsLoaded() &&
+ lookup.IsCacheable() &&
+ lookup.holder() == *object &&
+ lookup.type() == FIELD &&
+ !object->IsAccessCheckNeeded();
+
+ if (can_be_inlined) {
+ Map* map = lookup.holder()->map();
+ // Property's index in the properties array. If negative we have
+ // an inobject property.
+ int index = lookup.GetFieldIndex() - map->inobject_properties();
+ if (index < 0) {
+ // Index is an offset from the end of the object.
+ int offset = map->instance_size() + (index * kPointerSize);
+ if (PatchInlinedLoad(address(), map, offset)) {
+ set_target(megamorphic_stub());
+ return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex());
+ }
+ }
+ }
+
// Update inline cache and stub cache.
if (FLAG_use_ic && lookup.IsLoaded()) {
UpdateCaches(&lookup, state, object, name);
@@ -731,7 +760,7 @@ Object* KeyedLoadIC::Load(State state,
!object->IsJSValue() &&
!JSObject::cast(*object)->HasIndexedInterceptor()) {
Map* map = JSObject::cast(*object)->map();
- PatchInlinedMapCheck(address(), map);
+ PatchInlinedLoad(address(), map);
}
}
diff --git a/deps/v8/src/ic.h b/deps/v8/src/ic.h
index bbe1f6ddd..11fd60454 100644
--- a/deps/v8/src/ic.h
+++ b/deps/v8/src/ic.h
@@ -107,9 +107,11 @@ class IC {
Address fp() const { return fp_; }
Address pc() const { return *pc_address_; }
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Computes the address in the original code when the code running is
// containing break points (calls to DebugBreakXXX builtins).
Address OriginalCodeAddress();
+#endif
// Set the call-site target.
void set_target(Code* code) { SetTargetAtAddress(address(), code); }
@@ -214,6 +216,11 @@ class LoadIC: public IC {
static void GenerateStringLength(MacroAssembler* masm);
static void GenerateFunctionPrototype(MacroAssembler* masm);
+ // The offset from the inlined patch site to the start of the
+ // inlined load instruction. It is 7 bytes (test eax, imm) plus
+ // 6 bytes (jne slow_label).
+ static const int kOffsetToLoadInstruction = 13;
+
private:
static void Generate(MacroAssembler* masm, const ExternalReference& f);
@@ -236,6 +243,12 @@ class LoadIC: public IC {
}
static void Clear(Address address, Code* target);
+
+ // Clear the use of the inlined version.
+ static void ClearInlinedVersion(Address address);
+
+ static bool PatchInlinedLoad(Address address, Object* map, int index);
+
friend class IC;
};
@@ -252,6 +265,9 @@ class KeyedLoadIC: public IC {
static void GeneratePreMonomorphic(MacroAssembler* masm);
static void GenerateGeneric(MacroAssembler* masm);
+ // Clear the use of the inlined version.
+ static void ClearInlinedVersion(Address address);
+
private:
static void Generate(MacroAssembler* masm, const ExternalReference& f);
@@ -279,7 +295,7 @@ class KeyedLoadIC: public IC {
// Support for patching the map that is checked in an inlined
// version of keyed load.
- static void PatchInlinedMapCheck(Address address, Object* map);
+ static bool PatchInlinedLoad(Address address, Object* map);
friend class IC;
};
diff --git a/deps/v8/src/interpreter-irregexp.cc b/deps/v8/src/interpreter-irregexp.cc
index 1cc5c5a1d..77bcc9074 100644
--- a/deps/v8/src/interpreter-irregexp.cc
+++ b/deps/v8/src/interpreter-irregexp.cc
@@ -130,13 +130,13 @@ static void TraceInterpreter(const byte* code_base,
static int32_t Load32Aligned(const byte* pc) {
- ASSERT((reinterpret_cast<int>(pc) & 3) == 0);
+ ASSERT((reinterpret_cast<intptr_t>(pc) & 3) == 0);
return *reinterpret_cast<const int32_t *>(pc);
}
static int32_t Load16Aligned(const byte* pc) {
- ASSERT((reinterpret_cast<int>(pc) & 1) == 0);
+ ASSERT((reinterpret_cast<intptr_t>(pc) & 1) == 0);
return *reinterpret_cast<const uint16_t *>(pc);
}
@@ -574,7 +574,7 @@ bool IrregexpInterpreter::Match(Handle<ByteArray> code_array,
AssertNoAllocation a;
const byte* code_base = code_array->GetDataStartAddress();
uc16 previous_char = '\n';
- if (StringShape(*subject).IsAsciiRepresentation()) {
+ if (subject->IsAsciiRepresentation()) {
Vector<const char> subject_vector = subject->ToAsciiVector();
if (start_position != 0) previous_char = subject_vector[start_position - 1];
return RawMatch(code_base,
diff --git a/deps/v8/src/json-delay.js b/deps/v8/src/json-delay.js
new file mode 100644
index 000000000..90150c6f1
--- /dev/null
+++ b/deps/v8/src/json-delay.js
@@ -0,0 +1,254 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+var $JSON = global.JSON;
+
+function ParseJSONUnfiltered(text) {
+ var s = $String(text);
+ var f = %CompileString("(" + text + ")", -1, true);
+ return f();
+}
+
+function Revive(holder, name, reviver) {
+ var val = holder[name];
+ if (IS_OBJECT(val)) {
+ if (IS_ARRAY(val)) {
+ var length = val.length;
+ for (var i = 0; i < length; i++) {
+ var newElement = Revive(val, $String(i), reviver);
+ val[i] = newElement;
+ }
+ } else {
+ for (var p in val) {
+ if (ObjectHasOwnProperty.call(val, p)) {
+ var newElement = Revive(val, p, reviver);
+ if (IS_UNDEFINED(newElement)) {
+ delete val[p];
+ } else {
+ val[p] = newElement;
+ }
+ }
+ }
+ }
+ }
+ return reviver.call(holder, name, val);
+}
+
+function JSONParse(text, reviver) {
+ var unfiltered = ParseJSONUnfiltered(text);
+ if (IS_FUNCTION(reviver)) {
+ return Revive({'': unfiltered}, '', reviver);
+ } else {
+ return unfiltered;
+ }
+}
+
+var characterQuoteCache = {
+ '\"': '\\"',
+ '\\': '\\\\',
+ '/': '\\/',
+ '\b': '\\b',
+ '\f': '\\f',
+ '\n': '\\n',
+ '\r': '\\r',
+ '\t': '\\t',
+ '\x0B': '\\u000b'
+};
+
+function QuoteSingleJSONCharacter(c) {
+ if (c in characterQuoteCache)
+ return characterQuoteCache[c];
+ var charCode = c.charCodeAt(0);
+ var result;
+ if (charCode < 16) result = '\\u000';
+ else if (charCode < 256) result = '\\u00';
+ else if (charCode < 4096) result = '\\u0';
+ else result = '\\u';
+ result += charCode.toString(16);
+ characterQuoteCache[c] = result;
+ return result;
+}
+
+function QuoteJSONString(str) {
+ var quotable = /[\\\"\x00-\x1f\x80-\uffff]/g;
+ return '"' + str.replace(quotable, QuoteSingleJSONCharacter) + '"';
+}
+
+function StackContains(stack, val) {
+ var length = stack.length;
+ for (var i = 0; i < length; i++) {
+ if (stack[i] === val)
+ return true;
+ }
+ return false;
+}
+
+function SerializeArray(value, replacer, stack, indent, gap) {
+ if (StackContains(stack, value))
+ throw MakeTypeError('circular_structure', []);
+ stack.push(value);
+ var stepback = indent;
+ indent += gap;
+ var partial = [];
+ var len = value.length;
+ for (var i = 0; i < len; i++) {
+ var strP = JSONSerialize($String(i), value, replacer, stack,
+ indent, gap);
+ if (IS_UNDEFINED(strP))
+ strP = "null";
+ partial.push(strP);
+ }
+ var final;
+ if (gap == "") {
+ final = "[" + partial.join(",") + "]";
+ } else if (partial.length > 0) {
+ var separator = ",\n" + indent;
+ final = "[\n" + indent + partial.join(separator) + "\n" +
+ stepback + "]";
+ } else {
+ final = "[]";
+ }
+ stack.pop();
+ return final;
+}
+
+function SerializeObject(value, replacer, stack, indent, gap) {
+ if (StackContains(stack, value))
+ throw MakeTypeError('circular_structure', []);
+ stack.push(value);
+ var stepback = indent;
+ indent += gap;
+ var partial = [];
+ if (IS_ARRAY(replacer)) {
+ var length = replacer.length;
+ for (var i = 0; i < length; i++) {
+ if (ObjectHasOwnProperty.call(replacer, i)) {
+ var p = replacer[i];
+ var strP = JSONSerialize(p, value, replacer, stack, indent, gap);
+ if (!IS_UNDEFINED(strP)) {
+ var member = QuoteJSONString(p) + ":";
+ if (gap != "") member += " ";
+ member += strP;
+ partial.push(member);
+ }
+ }
+ }
+ } else {
+ for (var p in value) {
+ if (ObjectHasOwnProperty.call(value, p)) {
+ var strP = JSONSerialize(p, value, replacer, stack, indent, gap);
+ if (!IS_UNDEFINED(strP)) {
+ var member = QuoteJSONString(p) + ":";
+ if (gap != "") member += " ";
+ member += strP;
+ partial.push(member);
+ }
+ }
+ }
+ }
+ var final;
+ if (gap == "") {
+ final = "{" + partial.join(",") + "}";
+ } else if (partial.length > 0) {
+ var separator = ",\n" + indent;
+ final = "{\n" + indent + partial.join(separator) + "\n" +
+ stepback + "}";
+ } else {
+ final = "{}";
+ }
+ stack.pop();
+ return final;
+}
+
+function JSONSerialize(key, holder, replacer, stack, indent, gap) {
+ var value = holder[key];
+ if (IS_OBJECT(value) && value) {
+ var toJSON = value.toJSON;
+ if (IS_FUNCTION(toJSON))
+ value = toJSON.call(value, key);
+ }
+ if (IS_FUNCTION(replacer))
+ value = replacer.call(holder, key, value);
+ // Unwrap value if necessary
+ if (IS_OBJECT(value)) {
+ if (IS_NUMBER_WRAPPER(value)) {
+ value = $Number(value);
+ } else if (IS_STRING_WRAPPER(value)) {
+ value = $String(value);
+ }
+ }
+ switch (typeof value) {
+ case "string":
+ return QuoteJSONString(value);
+ case "object":
+ if (!value) {
+ return "null";
+ } else if (IS_ARRAY(value)) {
+ return SerializeArray(value, replacer, stack, indent, gap);
+ } else {
+ return SerializeObject(value, replacer, stack, indent, gap);
+ }
+ case "number":
+ return $isFinite(value) ? $String(value) : "null";
+ case "boolean":
+ return value ? "true" : "false";
+ }
+}
+
+function JSONStringify(value, replacer, space) {
+ var stack = [];
+ var indent = "";
+ if (IS_OBJECT(space)) {
+ // Unwrap 'space' if it is wrapped
+ if (IS_NUMBER_WRAPPER(space)) {
+ space = $Number(space);
+ } else if (IS_STRING_WRAPPER(space)) {
+ space = $String(space);
+ }
+ }
+ var gap;
+ if (IS_NUMBER(space)) {
+ space = $Math.min(space, 100);
+ gap = "";
+ for (var i = 0; i < space; i++)
+ gap += " ";
+ } else if (IS_STRING(space)) {
+ gap = space;
+ } else {
+ gap = "";
+ }
+ return JSONSerialize('', {'': value}, replacer, stack, indent, gap);
+}
+
+function SetupJSON() {
+ InstallFunctions($JSON, DONT_ENUM, $Array(
+ "parse", JSONParse,
+ "stringify", JSONStringify
+ ));
+}
+
+SetupJSON();
diff --git a/deps/v8/src/jsregexp.cc b/deps/v8/src/jsregexp.cc
index 40241e6fd..ebaefc0d7 100644
--- a/deps/v8/src/jsregexp.cc
+++ b/deps/v8/src/jsregexp.cc
@@ -42,11 +42,14 @@
#include "regexp-macro-assembler-irregexp.h"
#include "regexp-stack.h"
-#ifdef ARM
-#include "regexp-macro-assembler-arm.h"
-#else // IA32
-#include "macro-assembler-ia32.h"
-#include "regexp-macro-assembler-ia32.h"
+#ifdef V8_TARGET_ARCH_IA32
+#include "ia32/macro-assembler-ia32.h"
+#include "ia32/regexp-macro-assembler-ia32.h"
+#elif V8_TARGET_ARCH_X64
+#include "x64/macro-assembler-x64.h"
+#include "x64/regexp-macro-assembler-x64.h"
+#elif V8_TARGET_ARCH_ARM
+#include "arm/regexp-macro-assembler-arm.h"
#endif
#include "interpreter-irregexp.h"
@@ -424,12 +427,10 @@ Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> jsregexp,
Handle<String> original_subject = subject;
Handle<FixedArray> regexp(FixedArray::cast(jsregexp->data()));
if (UseNativeRegexp()) {
-#ifdef ARM
- UNREACHABLE();
-#else
+#if V8_TARGET_ARCH_IA32
RegExpMacroAssemblerIA32::Result res;
do {
- bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
+ bool is_ascii = subject->IsAsciiRepresentation();
if (!EnsureCompiledIrregexp(jsregexp, is_ascii)) {
return Handle<Object>::null();
}
@@ -450,9 +451,11 @@ Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> jsregexp,
|| res == RegExpMacroAssemblerIA32::FAILURE);
rc = (res == RegExpMacroAssemblerIA32::SUCCESS);
+#else
+ UNREACHABLE();
#endif
} else {
- bool is_ascii = StringShape(*subject).IsAsciiRepresentation();
+ bool is_ascii = subject->IsAsciiRepresentation();
if (!EnsureCompiledIrregexp(jsregexp, is_ascii)) {
return Handle<Object>::null();
}
@@ -2510,7 +2513,7 @@ void LoopChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
int ChoiceNode::CalculatePreloadCharacters(RegExpCompiler* compiler) {
int preload_characters = EatsAtLeast(4, 0);
-#ifdef CAN_READ_UNALIGNED
+#ifdef V8_HOST_CAN_READ_UNALIGNED
bool ascii = compiler->ascii();
if (ascii) {
if (preload_characters > 4) preload_characters = 4;
@@ -4434,9 +4437,13 @@ RegExpEngine::CompilationResult RegExpEngine::Compile(RegExpCompileData* data,
NodeInfo info = *node->info();
if (RegExpImpl::UseNativeRegexp()) {
-#ifdef ARM
+#ifdef V8_TARGET_ARCH_ARM
UNREACHABLE();
-#else // IA32
+#endif
+#ifdef V8_TARGET_ARCH_X64
+ UNREACHABLE();
+#endif
+#ifdef V8_TARGET_ARCH_IA32
RegExpMacroAssemblerIA32::Mode mode;
if (is_ascii) {
mode = RegExpMacroAssemblerIA32::ASCII;
diff --git a/deps/v8/src/jsregexp.h b/deps/v8/src/jsregexp.h
index e8249749f..9fa0ecef0 100644
--- a/deps/v8/src/jsregexp.h
+++ b/deps/v8/src/jsregexp.h
@@ -37,10 +37,10 @@ class RegExpMacroAssembler;
class RegExpImpl {
public:
static inline bool UseNativeRegexp() {
-#ifdef ARM
- return false;
-#else
+#ifdef V8_TARGET_ARCH_IA32
return FLAG_regexp_native;
+#else
+ return false;
#endif
}
// Creates a regular expression literal in the old space.
@@ -1003,14 +1003,14 @@ class ChoiceNode: public RegExpNode {
virtual bool try_to_emit_quick_check_for_alternative(int i) { return true; }
protected:
- int GreedyLoopTextLength(GuardedAlternative *alternative);
+ int GreedyLoopTextLength(GuardedAlternative* alternative);
ZoneList<GuardedAlternative>* alternatives_;
private:
friend class DispatchTableConstructor;
friend class Analysis;
void GenerateGuard(RegExpMacroAssembler* macro_assembler,
- Guard *guard,
+ Guard* guard,
Trace* trace);
int CalculatePreloadCharacters(RegExpCompiler* compiler);
void EmitOutOfLineContinuation(RegExpCompiler* compiler,
@@ -1288,7 +1288,7 @@ FOR_EACH_NODE_TYPE(DECLARE_VISIT)
void set_choice_index(int value) { choice_index_ = value; }
protected:
- DispatchTable *table_;
+ DispatchTable* table_;
int choice_index_;
bool ignore_case_;
};
diff --git a/deps/v8/src/jump-target.cc b/deps/v8/src/jump-target.cc
index 047588bdb..6e41270ee 100644
--- a/deps/v8/src/jump-target.cc
+++ b/deps/v8/src/jump-target.cc
@@ -189,28 +189,44 @@ void JumpTarget::ComputeEntryFrame(int mergable_elements) {
}
}
- // Compute the registers already reserved by values in the frame.
- // Count the reserved registers to avoid using them.
- RegisterFile frame_registers = RegisterAllocator::Reserved();
- for (int i = 0; i < length; i++) {
- FrameElement* element = elements[i];
- if (element != NULL && element->is_register()) {
- frame_registers.Use(element->reg());
+ // Build the new frame. A freshly allocated frame has memory elements
+ // for the parameters and some platform-dependent elements (e.g.,
+ // return address). Replace those first.
+ entry_frame_ = new VirtualFrame(cgen_);
+ int index = 0;
+ for (; index < entry_frame_->elements_.length(); index++) {
+ // If the element is determined, set it now. Count registers. Mark
+ // elements as copied exactly when they have a copy. Undetermined
+ // elements are initially recorded as if in memory.
+ if (elements[index] != NULL) {
+ entry_frame_->elements_[index] = *elements[index];
+ entry_frame_->elements_[index].clear_copied();
+ if (elements[index]->is_register()) {
+ entry_frame_->register_locations_[elements[index]->reg().code()] =
+ index;
+ } else if (elements[index]->is_copy()) {
+ entry_frame_->elements_[elements[index]->index()].set_copied();
+ }
}
}
-
- // Build the new frame. The frame already has memory elements for
- // the parameters (including the receiver) and the return address.
- // We will fill it up with memory elements.
- entry_frame_ = new VirtualFrame(cgen_);
- while (entry_frame_->elements_.length() < length) {
- entry_frame_->elements_.Add(FrameElement::MemoryElement());
+ // Then fill in the rest of the frame with new elements.
+ for (; index < length; index++) {
+ if (elements[index] == NULL) {
+ entry_frame_->elements_.Add(FrameElement::MemoryElement());
+ } else {
+ entry_frame_->elements_.Add(*elements[index]);
+ entry_frame_->elements_[index].clear_copied();
+ if (elements[index]->is_register()) {
+ entry_frame_->register_locations_[elements[index]->reg().code()] =
+ index;
+ } else if (elements[index]->is_copy()) {
+ entry_frame_->elements_[elements[index]->index()].set_copied();
+ }
+ }
}
-
- // Copy the already-determined frame elements to the entry frame,
- // and allocate any still-undetermined frame elements to registers
- // or memory, from the top down.
+ // Allocate any still-undetermined frame elements to registers or
+ // memory, from the top down.
for (int i = length - 1; i >= 0; i--) {
if (elements[i] == NULL) {
// If the value is synced on all frames, put it in memory. This
@@ -234,7 +250,7 @@ void JumpTarget::ComputeEntryFrame(int mergable_elements) {
for (int j = 0; j < reaching_frames_.length(); j++) {
FrameElement element = reaching_frames_[j]->elements_[i];
if (element.is_register() &&
- !frame_registers.is_used(element.reg())) {
+ !entry_frame_->is_used(element.reg())) {
candidate_registers.Use(element.reg());
if (candidate_registers.count(element.reg()) > max_count) {
max_count = candidate_registers.count(element.reg());
@@ -245,40 +261,32 @@ void JumpTarget::ComputeEntryFrame(int mergable_elements) {
// If there was no preferred choice consider any free register.
if (best_reg_code == no_reg.code_) {
for (int j = 0; j < kNumRegisters; j++) {
- if (!frame_registers.is_used(j)) {
+ if (!entry_frame_->is_used(j) && !RegisterAllocator::IsReserved(j)) {
best_reg_code = j;
break;
}
}
}
- // If there was a register choice, use it. If not do nothing
- // (the element is already recorded as in memory)
if (best_reg_code != no_reg.code_) {
+ // If there was a register choice, use it. Preserve the copied
+ // flag on the element.
+ bool is_copied = entry_frame_->elements_[i].is_copied();
Register reg = { best_reg_code };
- frame_registers.Use(reg);
entry_frame_->elements_[i] =
FrameElement::RegisterElement(reg,
FrameElement::NOT_SYNCED);
+ if (is_copied) entry_frame_->elements_[i].set_copied();
+ entry_frame_->register_locations_[best_reg_code] = i;
}
- } else {
- // The element is already determined.
- entry_frame_->elements_[i] = *elements[i];
+ // If there was no register found, the element is already
+ // recorded as in memory.
}
}
- // Set the copied flags in the frame to be exact. This assumes that
- // the backing store of copies is always lower in the frame.
- // Set the register locations to their index in the frame.
+ // Set the static type of frame elements.
for (int i = 0; i < length; i++) {
FrameElement* current = &entry_frame_->elements_[i];
- current->clear_copied();
- if (current->is_copy()) {
- entry_frame_->elements_[current->index()].set_copied();
- } else if (current->is_register()) {
- entry_frame_->register_locations_[current->reg().code()] = i;
- }
-
if (direction_ == BIDIRECTIONAL && i >= high_water_mark) {
current->set_static_type(StaticType::unknown());
} else {
diff --git a/deps/v8/src/list-inl.h b/deps/v8/src/list-inl.h
index 6dbd214d7..e3d251fba 100644
--- a/deps/v8/src/list-inl.h
+++ b/deps/v8/src/list-inl.h
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -38,21 +38,36 @@ void List<T, P>::Add(const T& element) {
if (length_ < capacity_) {
data_[length_++] = element;
} else {
- // Grow the list capacity by 50%, but make sure to let it grow
- // even when the capacity is zero (possible initial case).
- int new_capacity = 1 + capacity_ + (capacity_ >> 1);
- T* new_data = NewData(new_capacity);
- memcpy(new_data, data_, capacity_ * sizeof(T));
- // Since the element reference could be an element of the list,
- // assign it to the new backing store before deleting the old.
- new_data[length_++] = element;
- DeleteData(data_);
- data_ = new_data;
- capacity_ = new_capacity;
+ List<T, P>::ResizeAdd(element);
}
}
+// Use two layers of inlining so that the non-inlined function can
+// use the same implementation as the inlined version.
+template<typename T, class P>
+void List<T, P>::ResizeAdd(const T& element) {
+ ResizeAddInternal(element);
+}
+
+
+template<typename T, class P>
+void List<T, P>::ResizeAddInternal(const T& element) {
+ ASSERT(length_ >= capacity_);
+ // Grow the list capacity by 50%, but make sure to let it grow
+ // even when the capacity is zero (possible initial case).
+ int new_capacity = 1 + capacity_ + (capacity_ >> 1);
+ T* new_data = List<T, P>::NewData(new_capacity);
+ memcpy(new_data, data_, capacity_ * sizeof(T));
+ // Since the element reference could be an element of the list,
+ // assign it to the new backing store before deleting the old.
+ new_data[length_++] = element;
+ List<T, P>::DeleteData(data_);
+ data_ = new_data;
+ capacity_ = new_capacity;
+}
+
+
template<typename T, class P>
Vector<T> List<T, P>::AddBlock(T value, int count) {
int start = length_;
diff --git a/deps/v8/src/list.h b/deps/v8/src/list.h
index dc2f1158d..92d23ea39 100644
--- a/deps/v8/src/list.h
+++ b/deps/v8/src/list.h
@@ -118,9 +118,24 @@ class List {
INLINE(T* NewData(int n)) { return static_cast<T*>(P::New(n * sizeof(T))); }
INLINE(void DeleteData(T* data)) { P::Delete(data); }
+ // Increase the capacity of a full list, and add an element.
+ // List must be full already.
+ void ResizeAdd(const T& element);
+
+ // Inlined implementation of ResizeAdd, shared by inlined and
+ // non-inlined versions of ResizeAdd.
+ void ResizeAddInternal(const T& element);
+
DISALLOW_COPY_AND_ASSIGN(List);
};
+class FrameElement;
+
+// Add() is inlined, ResizeAdd() called by Add() is inlined except for
+// Lists of FrameElements, and ResizeAddInternal() is inlined in ResizeAdd().
+template <>
+void List<FrameElement,
+ FreeStoreAllocationPolicy>::ResizeAdd(const FrameElement& element);
} } // namespace v8::internal
diff --git a/deps/v8/src/log.cc b/deps/v8/src/log.cc
index d9e304d60..5297a302d 100644
--- a/deps/v8/src/log.cc
+++ b/deps/v8/src/log.cc
@@ -164,7 +164,7 @@ void StackTracer::Trace(TickSample* sample) {
//
class Ticker: public Sampler {
public:
- explicit Ticker(int interval, unsigned int low_stack_bound):
+ explicit Ticker(int interval, uintptr_t low_stack_bound):
Sampler(interval, FLAG_prof), window_(NULL), profiler_(NULL),
stack_tracer_(low_stack_bound) {}
@@ -285,8 +285,179 @@ void Profiler::Run() {
#ifdef ENABLE_LOGGING_AND_PROFILING
+
+// Functions and data for performing output of log messages.
+class Log : public AllStatic {
+ public:
+ // Opens stdout for logging.
+ static void OpenStdout();
+
+ // Opens file for logging.
+ static void OpenFile(const char* name);
+
+ // Opens memory buffer for logging.
+ static void OpenMemoryBuffer();
+
+ // Frees all resources acquired in Open... functions.
+ static void Close();
+
+ // See description in v8.h.
+ static int GetLogLines(int from_pos, char* dest_buf, int max_size);
+
+ static bool is_enabled() { return output_.handle != NULL; }
+
+ typedef int (*WritePtr)(const char* msg, int length);
+ private:
+ static void Init();
+
+ // Write functions assume that mutex_ is acquired by the caller.
+ static WritePtr Write;
+
+ static int WriteToFile(const char* msg, int length) {
+ ASSERT(output_.handle != NULL);
+ int rv = fwrite(msg, 1, length, output_.handle);
+ ASSERT(length == rv);
+ return rv;
+ }
+
+ static int WriteToMemory(const char* msg, int length) {
+ ASSERT(output_.buffer != NULL);
+ ASSERT(output_buffer_write_pos_ >= output_.buffer);
+ if (output_buffer_write_pos_ + length
+ <= output_.buffer + kOutputBufferSize) {
+ memcpy(output_buffer_write_pos_, msg, length);
+ output_buffer_write_pos_ += length;
+ return length;
+ } else {
+ // Memory buffer is full, ignore write.
+ return 0;
+ }
+ }
+
+ // When logging is active, output_ refers the file or memory buffer
+ // events are written to.
+ // mutex_ should be acquired before using output_.
+ union Output {
+ FILE* handle;
+ char* buffer;
+ };
+ static Output output_;
+
+ // mutex_ is a Mutex used for enforcing exclusive
+ // access to the formatting buffer and the log file or log memory buffer.
+ static Mutex* mutex_;
+
+ // Size of buffer used for memory logging.
+ static const int kOutputBufferSize = 2 * 1024 * 1024;
+
+ // Writing position in a memory buffer.
+ static char* output_buffer_write_pos_;
+
+ // Size of buffer used for formatting log messages.
+ static const int kMessageBufferSize = 2048;
+
+ // Buffer used for formatting log messages. This is a singleton buffer and
+ // mutex_ should be acquired before using it.
+ static char* message_buffer_;
+
+ friend class LogMessageBuilder;
+};
+
+
+Log::WritePtr Log::Write = NULL;
+Log::Output Log::output_ = {NULL};
+Mutex* Log::mutex_ = NULL;
+char* Log::output_buffer_write_pos_ = NULL;
+char* Log::message_buffer_ = NULL;
+
+
+void Log::Init() {
+ mutex_ = OS::CreateMutex();
+ message_buffer_ = NewArray<char>(kMessageBufferSize);
+}
+
+
+void Log::OpenStdout() {
+ ASSERT(output_.handle == NULL);
+ output_.handle = stdout;
+ Write = WriteToFile;
+ Init();
+}
+
+
+void Log::OpenFile(const char* name) {
+ ASSERT(output_.handle == NULL);
+ output_.handle = OS::FOpen(name, OS::LogFileOpenMode);
+ Write = WriteToFile;
+ Init();
+}
+
+
+void Log::OpenMemoryBuffer() {
+ ASSERT(output_.buffer == NULL);
+ output_.buffer = NewArray<char>(kOutputBufferSize);
+ output_buffer_write_pos_ = output_.buffer;
+ Write = WriteToMemory;
+ Init();
+}
+
+
+void Log::Close() {
+ if (Write == WriteToFile) {
+ fclose(output_.handle);
+ output_.handle = NULL;
+ } else if (Write == WriteToMemory) {
+ DeleteArray(output_.buffer);
+ output_.buffer = NULL;
+ } else {
+ ASSERT(Write == NULL);
+ }
+ Write = NULL;
+
+ delete mutex_;
+ mutex_ = NULL;
+
+ DeleteArray(message_buffer_);
+ message_buffer_ = NULL;
+}
+
+
+int Log::GetLogLines(int from_pos, char* dest_buf, int max_size) {
+ if (Write != WriteToMemory) return 0;
+ ASSERT(output_.buffer != NULL);
+ ASSERT(output_buffer_write_pos_ >= output_.buffer);
+ ASSERT(from_pos >= 0);
+ ASSERT(max_size >= 0);
+ int actual_size = max_size;
+ char* buffer_read_pos = output_.buffer + from_pos;
+ ScopedLock sl(mutex_);
+ if (actual_size == 0
+ || output_buffer_write_pos_ == output_.buffer
+ || buffer_read_pos >= output_buffer_write_pos_) {
+ // No data requested or can be returned.
+ return 0;
+ }
+ if (buffer_read_pos + actual_size > output_buffer_write_pos_) {
+ // Requested size overlaps with current writing position and
+ // needs to be truncated.
+ actual_size = output_buffer_write_pos_ - buffer_read_pos;
+ ASSERT(actual_size == 0 || buffer_read_pos[actual_size - 1] == '\n');
+ } else {
+ // Find previous log line boundary.
+ char* end_pos = buffer_read_pos + actual_size - 1;
+ while (end_pos >= buffer_read_pos && *end_pos != '\n') --end_pos;
+ actual_size = end_pos - buffer_read_pos + 1;
+ }
+ ASSERT(actual_size <= max_size);
+ if (actual_size > 0) {
+ memcpy(dest_buf, buffer_read_pos, actual_size);
+ }
+ return actual_size;
+}
+
+
// Utility class for formatting log messages. It fills the message into the
-// static buffer in Logger.
+// static buffer in Log.
class LogMessageBuilder BASE_EMBEDDED {
public:
explicit LogMessageBuilder();
@@ -309,45 +480,45 @@ class LogMessageBuilder BASE_EMBEDDED {
// Create a message builder starting from position 0. This acquires the mutex
// in the logger as well.
-LogMessageBuilder::LogMessageBuilder(): sl(Logger::mutex_), pos_(0) {
- ASSERT(Logger::message_buffer_ != NULL);
+LogMessageBuilder::LogMessageBuilder(): sl(Log::mutex_), pos_(0) {
+ ASSERT(Log::message_buffer_ != NULL);
}
// Append string data to the log message.
void LogMessageBuilder::Append(const char* format, ...) {
- Vector<char> buf(Logger::message_buffer_ + pos_,
- Logger::kMessageBufferSize - pos_);
+ Vector<char> buf(Log::message_buffer_ + pos_,
+ Log::kMessageBufferSize - pos_);
va_list args;
va_start(args, format);
Append(format, args);
va_end(args);
- ASSERT(pos_ <= Logger::kMessageBufferSize);
+ ASSERT(pos_ <= Log::kMessageBufferSize);
}
// Append string data to the log message.
void LogMessageBuilder::Append(const char* format, va_list args) {
- Vector<char> buf(Logger::message_buffer_ + pos_,
- Logger::kMessageBufferSize - pos_);
+ Vector<char> buf(Log::message_buffer_ + pos_,
+ Log::kMessageBufferSize - pos_);
int result = v8::internal::OS::VSNPrintF(buf, format, args);
// Result is -1 if output was truncated.
if (result >= 0) {
pos_ += result;
} else {
- pos_ = Logger::kMessageBufferSize;
+ pos_ = Log::kMessageBufferSize;
}
- ASSERT(pos_ <= Logger::kMessageBufferSize);
+ ASSERT(pos_ <= Log::kMessageBufferSize);
}
// Append a character to the log message.
void LogMessageBuilder::Append(const char c) {
- if (pos_ < Logger::kMessageBufferSize) {
- Logger::message_buffer_[pos_++] = c;
+ if (pos_ < Log::kMessageBufferSize) {
+ Log::message_buffer_[pos_++] = c;
}
- ASSERT(pos_ <= Logger::kMessageBufferSize);
+ ASSERT(pos_ <= Log::kMessageBufferSize);
}
@@ -366,7 +537,7 @@ void LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) {
if (len > 0x1000)
len = 0x1000;
if (show_impl_info) {
- Append(StringShape(str).IsAsciiRepresentation() ? 'a' : '2');
+ Append(str->IsAsciiRepresentation() ? 'a' : '2');
if (StringShape(str).IsExternal())
Append('e');
if (StringShape(str).IsSymbol())
@@ -391,18 +562,14 @@ void LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) {
// Write the log message to the log file currently opened.
void LogMessageBuilder::WriteToLogFile() {
- ASSERT(pos_ <= Logger::kMessageBufferSize);
- size_t rv = fwrite(Logger::message_buffer_, 1, pos_, Logger::logfile_);
- ASSERT(rv == static_cast<size_t>(pos_));
- USE(rv);
+ ASSERT(pos_ <= Log::kMessageBufferSize);
+ Log::Write(Log::message_buffer_, pos_);
}
// Write a null-terminated string to to the log file currently opened.
void LogMessageBuilder::WriteCStringToLogFile(const char* str) {
- size_t len = strlen(str);
- size_t rv = fwrite(str, 1, len, Logger::logfile_);
- ASSERT(rv == len);
- USE(rv);
+ int len = strlen(str);
+ Log::Write(str, len);
}
#endif
@@ -411,20 +578,22 @@ void LogMessageBuilder::WriteCStringToLogFile(const char* str) {
// Logger class implementation.
//
Ticker* Logger::ticker_ = NULL;
-char* Logger::message_buffer_ = NULL;
-FILE* Logger::logfile_ = NULL;
Profiler* Logger::profiler_ = NULL;
-Mutex* Logger::mutex_ = NULL;
VMState* Logger::current_state_ = NULL;
VMState Logger::bottom_state_(EXTERNAL);
SlidingStateWindow* Logger::sliding_state_window_ = NULL;
+
+bool Logger::is_enabled() {
+ return Log::is_enabled();
+}
+
#endif // ENABLE_LOGGING_AND_PROFILING
void Logger::Preamble(const char* content) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_code) return;
+ if (!Log::is_enabled() || !FLAG_log_code) return;
LogMessageBuilder msg;
msg.WriteCStringToLogFile(content);
#endif
@@ -440,7 +609,7 @@ void Logger::StringEvent(const char* name, const char* value) {
#ifdef ENABLE_LOGGING_AND_PROFILING
void Logger::UncheckedStringEvent(const char* name, const char* value) {
- if (logfile_ == NULL) return;
+ if (!Log::is_enabled()) return;
LogMessageBuilder msg;
msg.Append("%s,\"%s\"\n", name, value);
msg.WriteToLogFile();
@@ -450,7 +619,7 @@ void Logger::UncheckedStringEvent(const char* name, const char* value) {
void Logger::IntEvent(const char* name, int value) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log) return;
+ if (!Log::is_enabled() || !FLAG_log) return;
LogMessageBuilder msg;
msg.Append("%s,%d\n", name, value);
msg.WriteToLogFile();
@@ -460,10 +629,9 @@ void Logger::IntEvent(const char* name, int value) {
void Logger::HandleEvent(const char* name, Object** location) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_handles) return;
+ if (!Log::is_enabled() || !FLAG_log_handles) return;
LogMessageBuilder msg;
- msg.Append("%s,0x%x\n", name,
- reinterpret_cast<unsigned int>(location));
+ msg.Append("%s,0x%%"V8PRIp"\n", name, location);
msg.WriteToLogFile();
#endif
}
@@ -471,10 +639,10 @@ void Logger::HandleEvent(const char* name, Object** location) {
#ifdef ENABLE_LOGGING_AND_PROFILING
// ApiEvent is private so all the calls come from the Logger class. It is the
-// caller's responsibility to ensure that logfile_ is not NULL and that
+// caller's responsibility to ensure that log is enabled and that
// FLAG_log_api is true.
void Logger::ApiEvent(const char* format, ...) {
- ASSERT(logfile_ != NULL && FLAG_log_api);
+ ASSERT(Log::is_enabled() && FLAG_log_api);
LogMessageBuilder msg;
va_list ap;
va_start(ap, format);
@@ -487,7 +655,7 @@ void Logger::ApiEvent(const char* format, ...) {
void Logger::ApiNamedSecurityCheck(Object* key) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_api) return;
+ if (!Log::is_enabled() || !FLAG_log_api) return;
if (key->IsString()) {
SmartPointer<char> str =
String::cast(key)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
@@ -505,7 +673,7 @@ void Logger::SharedLibraryEvent(const char* library_path,
unsigned start,
unsigned end) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_prof) return;
+ if (!Log::is_enabled() || !FLAG_prof) return;
LogMessageBuilder msg;
msg.Append("shared-library,\"%s\",0x%08x,0x%08x\n", library_path,
start, end);
@@ -518,7 +686,7 @@ void Logger::SharedLibraryEvent(const wchar_t* library_path,
unsigned start,
unsigned end) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_prof) return;
+ if (!Log::is_enabled() || !FLAG_prof) return;
LogMessageBuilder msg;
msg.Append("shared-library,\"%ls\",0x%08x,0x%08x\n", library_path,
start, end);
@@ -573,7 +741,7 @@ void Logger::LogRegExpSource(Handle<JSRegExp> regexp) {
void Logger::RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_regexp) return;
+ if (!Log::is_enabled() || !FLAG_log_regexp) return;
LogMessageBuilder msg;
msg.Append("regexp-compile,");
LogRegExpSource(regexp);
@@ -585,7 +753,7 @@ void Logger::RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache) {
void Logger::LogRuntime(Vector<const char> format, JSArray* args) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_runtime) return;
+ if (!Log::is_enabled() || !FLAG_log_runtime) return;
HandleScope scope;
LogMessageBuilder msg;
for (int i = 0; i < format.length(); i++) {
@@ -626,7 +794,7 @@ void Logger::LogRuntime(Vector<const char> format, JSArray* args) {
void Logger::ApiIndexedSecurityCheck(uint32_t index) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_api) return;
+ if (!Log::is_enabled() || !FLAG_log_api) return;
ApiEvent("api,check-security,%u\n", index);
#endif
}
@@ -637,7 +805,7 @@ void Logger::ApiNamedPropertyAccess(const char* tag,
Object* name) {
#ifdef ENABLE_LOGGING_AND_PROFILING
ASSERT(name->IsString());
- if (logfile_ == NULL || !FLAG_log_api) return;
+ if (!Log::is_enabled() || !FLAG_log_api) return;
String* class_name_obj = holder->class_name();
SmartPointer<char> class_name =
class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
@@ -651,7 +819,7 @@ void Logger::ApiIndexedPropertyAccess(const char* tag,
JSObject* holder,
uint32_t index) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_api) return;
+ if (!Log::is_enabled() || !FLAG_log_api) return;
String* class_name_obj = holder->class_name();
SmartPointer<char> class_name =
class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
@@ -661,7 +829,7 @@ void Logger::ApiIndexedPropertyAccess(const char* tag,
void Logger::ApiObjectAccess(const char* tag, JSObject* object) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_api) return;
+ if (!Log::is_enabled() || !FLAG_log_api) return;
String* class_name_obj = object->class_name();
SmartPointer<char> class_name =
class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
@@ -672,7 +840,7 @@ void Logger::ApiObjectAccess(const char* tag, JSObject* object) {
void Logger::ApiEntryCall(const char* name) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_api) return;
+ if (!Log::is_enabled() || !FLAG_log_api) return;
Logger::ApiEvent("api,%s\n", name);
#endif
}
@@ -680,10 +848,9 @@ void Logger::ApiEntryCall(const char* name) {
void Logger::NewEvent(const char* name, void* object, size_t size) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log) return;
+ if (!Log::is_enabled() || !FLAG_log) return;
LogMessageBuilder msg;
- msg.Append("new,%s,0x%x,%u\n", name,
- reinterpret_cast<unsigned int>(object),
+ msg.Append("new,%s,0x%%"V8PRIp",%u\n", name, object,
static_cast<unsigned int>(size));
msg.WriteToLogFile();
#endif
@@ -692,10 +859,9 @@ void Logger::NewEvent(const char* name, void* object, size_t size) {
void Logger::DeleteEvent(const char* name, void* object) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log) return;
+ if (!Log::is_enabled() || !FLAG_log) return;
LogMessageBuilder msg;
- msg.Append("delete,%s,0x%x\n", name,
- reinterpret_cast<unsigned int>(object));
+ msg.Append("delete,%s,0x%%"V8PRIp"\n", name, object);
msg.WriteToLogFile();
#endif
}
@@ -703,10 +869,9 @@ void Logger::DeleteEvent(const char* name, void* object) {
void Logger::CodeCreateEvent(const char* tag, Code* code, const char* comment) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_code) return;
+ if (!Log::is_enabled() || !FLAG_log_code) return;
LogMessageBuilder msg;
- msg.Append("code-creation,%s,0x%x,%d,\"", tag,
- reinterpret_cast<unsigned int>(code->address()),
+ msg.Append("code-creation,%s,0x%"V8PRIp",%d,\"", tag, code->address(),
code->ExecutableSize());
for (const char* p = comment; *p != '\0'; p++) {
if (*p == '"') {
@@ -723,12 +888,11 @@ void Logger::CodeCreateEvent(const char* tag, Code* code, const char* comment) {
void Logger::CodeCreateEvent(const char* tag, Code* code, String* name) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_code) return;
+ if (!Log::is_enabled() || !FLAG_log_code) return;
LogMessageBuilder msg;
SmartPointer<char> str =
name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
- msg.Append("code-creation,%s,0x%x,%d,\"%s\"\n", tag,
- reinterpret_cast<unsigned int>(code->address()),
+ msg.Append("code-creation,%s,0x%"V8PRIp",%d,\"%s\"\n", tag, code->address(),
code->ExecutableSize(), *str);
msg.WriteToLogFile();
#endif
@@ -738,14 +902,14 @@ void Logger::CodeCreateEvent(const char* tag, Code* code, String* name) {
void Logger::CodeCreateEvent(const char* tag, Code* code, String* name,
String* source, int line) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_code) return;
+ if (!Log::is_enabled() || !FLAG_log_code) return;
LogMessageBuilder msg;
SmartPointer<char> str =
name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
SmartPointer<char> sourcestr =
source->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
- msg.Append("code-creation,%s,0x%x,%d,\"%s %s:%d\"\n", tag,
- reinterpret_cast<unsigned int>(code->address()),
+ msg.Append("code-creation,%s,0x%"V8PRIp",%d,\"%s %s:%d\"\n",
+ tag, code->address(),
code->ExecutableSize(),
*str, *sourcestr, line);
msg.WriteToLogFile();
@@ -755,10 +919,10 @@ void Logger::CodeCreateEvent(const char* tag, Code* code, String* name,
void Logger::CodeCreateEvent(const char* tag, Code* code, int args_count) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_code) return;
+ if (!Log::is_enabled() || !FLAG_log_code) return;
LogMessageBuilder msg;
- msg.Append("code-creation,%s,0x%x,%d,\"args_count: %d\"\n", tag,
- reinterpret_cast<unsigned int>(code->address()),
+ msg.Append("code-creation,%s,0x%"V8PRIp",%d,\"args_count: %d\"\n", tag,
+ code->address(),
code->ExecutableSize(),
args_count);
msg.WriteToLogFile();
@@ -768,10 +932,10 @@ void Logger::CodeCreateEvent(const char* tag, Code* code, int args_count) {
void Logger::RegExpCodeCreateEvent(Code* code, String* source) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_code) return;
+ if (!Log::is_enabled() || !FLAG_log_code) return;
LogMessageBuilder msg;
- msg.Append("code-creation,%s,0x%x,%d,\"", "RegExp",
- reinterpret_cast<unsigned int>(code->address()),
+ msg.Append("code-creation,%s,0x%"V8PRIp",%d,\"", "RegExp",
+ code->address(),
code->ExecutableSize());
msg.AppendDetailed(source, false);
msg.Append("\"\n");
@@ -782,11 +946,9 @@ void Logger::RegExpCodeCreateEvent(Code* code, String* source) {
void Logger::CodeAllocateEvent(Code* code, Assembler* assem) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_code) return;
+ if (!Log::is_enabled() || !FLAG_log_code) return;
LogMessageBuilder msg;
- msg.Append("code-allocate,0x%x,0x%x\n",
- reinterpret_cast<unsigned int>(code->address()),
- reinterpret_cast<unsigned int>(assem));
+ msg.Append("code-allocate,0x%"V8PRIp",0x%"V8PRIp"\n", code->address(), assem);
msg.WriteToLogFile();
#endif
}
@@ -794,11 +956,9 @@ void Logger::CodeAllocateEvent(Code* code, Assembler* assem) {
void Logger::CodeMoveEvent(Address from, Address to) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_code) return;
+ if (!Log::is_enabled() || !FLAG_log_code) return;
LogMessageBuilder msg;
- msg.Append("code-move,0x%x,0x%x\n",
- reinterpret_cast<unsigned int>(from),
- reinterpret_cast<unsigned int>(to));
+ msg.Append("code-move,0x%"V8PRIp",0x%"V8PRIp"\n", from, to);
msg.WriteToLogFile();
#endif
}
@@ -806,38 +966,9 @@ void Logger::CodeMoveEvent(Address from, Address to) {
void Logger::CodeDeleteEvent(Address from) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_code) return;
+ if (!Log::is_enabled() || !FLAG_log_code) return;
LogMessageBuilder msg;
- msg.Append("code-delete,0x%x\n", reinterpret_cast<unsigned int>(from));
- msg.WriteToLogFile();
-#endif
-}
-
-
-void Logger::BeginCodeRegionEvent(CodeRegion* region,
- Assembler* masm,
- const char* name) {
-#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_code) return;
- LogMessageBuilder msg;
- msg.Append("begin-code-region,0x%x,0x%x,0x%x,%s\n",
- reinterpret_cast<unsigned int>(region),
- reinterpret_cast<unsigned int>(masm),
- masm->pc_offset(),
- name);
- msg.WriteToLogFile();
-#endif
-}
-
-
-void Logger::EndCodeRegionEvent(CodeRegion* region, Assembler* masm) {
-#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_code) return;
- LogMessageBuilder msg;
- msg.Append("end-code-region,0x%x,0x%x,0x%x\n",
- reinterpret_cast<unsigned int>(region),
- reinterpret_cast<unsigned int>(masm),
- masm->pc_offset());
+ msg.Append("code-delete,0x%"V8PRIp"\n", from);
msg.WriteToLogFile();
#endif
}
@@ -845,7 +976,7 @@ void Logger::EndCodeRegionEvent(CodeRegion* region, Assembler* masm) {
void Logger::ResourceEvent(const char* name, const char* tag) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log) return;
+ if (!Log::is_enabled() || !FLAG_log) return;
LogMessageBuilder msg;
msg.Append("%s,%s,", name, tag);
@@ -863,12 +994,11 @@ void Logger::ResourceEvent(const char* name, const char* tag) {
void Logger::SuspectReadEvent(String* name, Object* obj) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_suspect) return;
+ if (!Log::is_enabled() || !FLAG_log_suspect) return;
LogMessageBuilder msg;
String* class_name = obj->IsJSObject()
? JSObject::cast(obj)->class_name()
: Heap::empty_string();
- ScopedLock sl(mutex_);
msg.Append("suspect-read,");
msg.Append(class_name);
msg.Append(',');
@@ -883,7 +1013,7 @@ void Logger::SuspectReadEvent(String* name, Object* obj) {
void Logger::HeapSampleBeginEvent(const char* space, const char* kind) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_gc) return;
+ if (!Log::is_enabled() || !FLAG_log_gc) return;
LogMessageBuilder msg;
msg.Append("heap-sample-begin,\"%s\",\"%s\"\n", space, kind);
msg.WriteToLogFile();
@@ -893,7 +1023,7 @@ void Logger::HeapSampleBeginEvent(const char* space, const char* kind) {
void Logger::HeapSampleEndEvent(const char* space, const char* kind) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_gc) return;
+ if (!Log::is_enabled() || !FLAG_log_gc) return;
LogMessageBuilder msg;
msg.Append("heap-sample-end,\"%s\",\"%s\"\n", space, kind);
msg.WriteToLogFile();
@@ -903,7 +1033,7 @@ void Logger::HeapSampleEndEvent(const char* space, const char* kind) {
void Logger::HeapSampleItemEvent(const char* type, int number, int bytes) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log_gc) return;
+ if (!Log::is_enabled() || !FLAG_log_gc) return;
LogMessageBuilder msg;
msg.Append("heap-sample-item,%s,%d,%d\n", type, number, bytes);
msg.WriteToLogFile();
@@ -913,7 +1043,7 @@ void Logger::HeapSampleItemEvent(const char* type, int number, int bytes) {
void Logger::DebugTag(const char* call_site_tag) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log) return;
+ if (!Log::is_enabled() || !FLAG_log) return;
LogMessageBuilder msg;
msg.Append("debug-tag,%s\n", call_site_tag);
msg.WriteToLogFile();
@@ -923,7 +1053,7 @@ void Logger::DebugTag(const char* call_site_tag) {
void Logger::DebugEvent(const char* event_type, Vector<uint16_t> parameter) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- if (logfile_ == NULL || !FLAG_log) return;
+ if (!Log::is_enabled() || !FLAG_log) return;
StringBuilder s(parameter.length() + 1);
for (int i = 0; i < parameter.length(); ++i) {
s.AddCharacter(static_cast<char>(parameter[i]));
@@ -942,15 +1072,15 @@ void Logger::DebugEvent(const char* event_type, Vector<uint16_t> parameter) {
#ifdef ENABLE_LOGGING_AND_PROFILING
void Logger::TickEvent(TickSample* sample, bool overflow) {
- if (logfile_ == NULL || !FLAG_prof) return;
+ if (!Log::is_enabled() || !FLAG_prof) return;
LogMessageBuilder msg;
- msg.Append("tick,0x%x,0x%x,%d", sample->pc, sample->sp,
+ msg.Append("tick,0x%"V8PRIp",0x%"V8PRIp",%d", sample->pc, sample->sp,
static_cast<int>(sample->state));
if (overflow) {
msg.Append(",overflow");
}
for (int i = 0; i < sample->frames_count; ++i) {
- msg.Append(",0x%x", reinterpret_cast<uint32_t>(sample->stack[i]));
+ msg.Append(",0x%"V8PRIp, sample->stack[i]);
}
msg.Append('\n');
msg.WriteToLogFile();
@@ -970,6 +1100,12 @@ void Logger::PauseProfiler() {
void Logger::ResumeProfiler() {
profiler_->resume();
}
+
+
+int Logger::GetLogLines(int from_pos, char* dest_buf, int max_size) {
+ return Log::GetLogLines(from_pos, dest_buf, max_size);
+}
+
#endif
@@ -996,7 +1132,9 @@ bool Logger::Setup() {
// If we're logging anything, we need to open the log file.
if (open_log_file) {
if (strcmp(FLAG_logfile, "-") == 0) {
- logfile_ = stdout;
+ Log::OpenStdout();
+ } else if (strcmp(FLAG_logfile, "*") == 0) {
+ Log::OpenMemoryBuffer();
} else if (strchr(FLAG_logfile, '%') != NULL) {
// If there's a '%' in the log file name we have to expand
// placeholders.
@@ -1032,12 +1170,10 @@ bool Logger::Setup() {
}
}
SmartPointer<const char> expanded = stream.ToCString();
- logfile_ = OS::FOpen(*expanded, OS::LogFileOpenMode);
+ Log::OpenFile(*expanded);
} else {
- logfile_ = OS::FOpen(FLAG_logfile, OS::LogFileOpenMode);
+ Log::OpenFile(FLAG_logfile);
}
- message_buffer_ = NewArray<char>(kMessageBufferSize);
- mutex_ = OS::CreateMutex();
}
current_state_ = &bottom_state_;
@@ -1045,7 +1181,7 @@ bool Logger::Setup() {
// as log is initialized early with V8, we can assume that JS execution
// frames can never reach this point on stack
int stack_var;
- ticker_ = new Ticker(1, reinterpret_cast<unsigned int>(&stack_var));
+ ticker_ = new Ticker(1, reinterpret_cast<uintptr_t>(&stack_var));
if (FLAG_sliding_state_window && sliding_state_window_ == NULL) {
sliding_state_window_ = new SlidingStateWindow();
@@ -1079,13 +1215,7 @@ void Logger::TearDown() {
delete ticker_;
- if (logfile_ != NULL) {
- fclose(logfile_);
- logfile_ = NULL;
- delete mutex_;
- mutex_ = NULL;
- DeleteArray(message_buffer_);
- }
+ Log::Close();
#endif
}
diff --git a/deps/v8/src/log.h b/deps/v8/src/log.h
index bbcfa42c6..5f3c188c5 100644
--- a/deps/v8/src/log.h
+++ b/deps/v8/src/log.h
@@ -103,10 +103,10 @@ class VMState BASE_EMBEDDED {
class Logger {
public:
- // Opens the file for logging if the right flags are set.
+ // Acquires resources for logging if the right flags are set.
static bool Setup();
- // Closes file opened in Setup.
+ // Frees resources acquired in Setup.
static void TearDown();
// Enable the computation of a sliding window of states.
@@ -174,11 +174,6 @@ class Logger {
static void CodeMoveEvent(Address from, Address to);
// Emits a code delete event.
static void CodeDeleteEvent(Address from);
- // Emits region delimiters
- static void BeginCodeRegionEvent(CodeRegion* region,
- Assembler* masm,
- const char* name);
- static void EndCodeRegionEvent(CodeRegion* region, Assembler* masm);
// ==== Events logged by --log-gc. ====
// Heap sampling events: start, end, and individual types.
@@ -206,7 +201,7 @@ class Logger {
return current_state_ ? current_state_->state() : OTHER;
}
- static bool is_enabled() { return logfile_ != NULL; }
+ static bool is_enabled();
// Pause/Resume collection of profiling data.
// When data collection is paused, Tick events are discarded until
@@ -215,6 +210,10 @@ class Logger {
static void PauseProfiler();
static void ResumeProfiler();
+ // If logging is performed into a memory buffer, allows to
+ // retrieve previously written messages. See v8.h.
+ static int GetLogLines(int from_pos, char* dest_buf, int max_size);
+
private:
// Emits the source code of a regexp. Used by regexp events.
@@ -228,17 +227,6 @@ class Logger {
// Logs a StringEvent regardless of whether FLAG_log is true.
static void UncheckedStringEvent(const char* name, const char* value);
- // Size of buffer used for formatting log messages.
- static const int kMessageBufferSize = 2048;
-
- // Buffer used for formatting log messages. This is a singleton buffer and
- // mutex_ should be acquired before using it.
- static char* message_buffer_;
-
- // When logging is active, logfile_ refers the file events are written to.
- // mutex_ should be acquired before using logfile_.
- static FILE* logfile_;
-
// The sampler used by the profiler and the sliding state window.
static Ticker* ticker_;
@@ -247,10 +235,6 @@ class Logger {
// of samples.
static Profiler* profiler_;
- // mutex_ is a Mutex used for enforcing exclusive
- // access to the formatting buffer and the log file.
- static Mutex* mutex_;
-
// A stack of VM states.
static VMState* current_state_;
@@ -263,7 +247,6 @@ class Logger {
// Internal implementation classes with access to
// private members.
- friend class LogMessageBuilder;
friend class EventLog;
friend class TimeLog;
friend class Profiler;
@@ -278,12 +261,12 @@ class Logger {
// Class that extracts stack trace, used for profiling.
class StackTracer BASE_EMBEDDED {
public:
- explicit StackTracer(unsigned int low_stack_bound)
+ explicit StackTracer(uintptr_t low_stack_bound)
: low_stack_bound_(low_stack_bound) { }
void Trace(TickSample* sample);
private:
- unsigned int low_stack_bound_;
+ uintptr_t low_stack_bound_;
};
diff --git a/deps/v8/src/macro-assembler.h b/deps/v8/src/macro-assembler.h
index 84a1eef39..116381bb3 100644
--- a/deps/v8/src/macro-assembler.h
+++ b/deps/v8/src/macro-assembler.h
@@ -28,23 +28,25 @@
#ifndef V8_MACRO_ASSEMBLER_H_
#define V8_MACRO_ASSEMBLER_H_
-#ifdef ARM
-
-#include "constants-arm.h"
+#if V8_TARGET_ARCH_IA32
#include "assembler.h"
-#include "assembler-arm.h"
-#include "assembler-arm-inl.h"
+#include "ia32/assembler-ia32.h"
+#include "ia32/assembler-ia32-inl.h"
#include "code.h" // must be after assembler_*.h
-#include "macro-assembler-arm.h"
-
-#else // ia32
-
+#include "ia32/macro-assembler-ia32.h"
+#elif V8_TARGET_ARCH_X64
#include "assembler.h"
-#include "assembler-ia32.h"
-#include "assembler-ia32-inl.h"
+#include "x64/assembler-x64.h"
+#include "x64/assembler-x64-inl.h"
#include "code.h" // must be after assembler_*.h
-#include "macro-assembler-ia32.h"
-
+#include "x64/macro-assembler-x64.h"
+#elif V8_TARGET_ARCH_ARM
+#include "arm/constants-arm.h"
+#include "assembler.h"
+#include "arm/assembler-arm.h"
+#include "arm/assembler-arm-inl.h"
+#include "code.h" // must be after assembler_*.h
+#include "arm/macro-assembler-arm.h"
#endif
#endif // V8_MACRO_ASSEMBLER_H_
diff --git a/deps/v8/src/macros.py b/deps/v8/src/macros.py
index d78ecd94d..ebfd816a0 100644
--- a/deps/v8/src/macros.py
+++ b/deps/v8/src/macros.py
@@ -84,6 +84,8 @@ macro IS_BOOLEAN(arg) = (typeof(arg) === 'boolean');
macro IS_REGEXP(arg) = %HasRegExpClass(arg);
macro IS_ARRAY(arg) = %HasArrayClass(arg);
macro IS_DATE(arg) = %HasDateClass(arg);
+macro IS_NUMBER_WRAPPER(arg) = %HasNumberClass(arg);
+macro IS_STRING_WRAPPER(arg) = %HasStringClass(arg);
macro IS_ERROR(arg) = (%ClassOf(arg) === 'Error');
macro IS_SCRIPT(arg) = (%ClassOf(arg) === 'Script');
macro FLOOR(arg) = %Math_floor(arg);
diff --git a/deps/v8/src/mark-compact.cc b/deps/v8/src/mark-compact.cc
index c55345dc1..48774ec5b 100644
--- a/deps/v8/src/mark-compact.cc
+++ b/deps/v8/src/mark-compact.cc
@@ -555,25 +555,62 @@ static void ScanOverflowedObjects(T* it) {
}
-bool MarkCompactCollector::MustBeMarked(Object** p) {
- // Check whether *p is a HeapObject pointer.
- if (!(*p)->IsHeapObject()) return false;
- return !HeapObject::cast(*p)->IsMarked();
+bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) {
+ return (*p)->IsHeapObject() && !HeapObject::cast(*p)->IsMarked();
}
-void MarkCompactCollector::ProcessRoots(RootMarkingVisitor* visitor) {
- // Mark the heap roots gray, including global variables, stack variables,
- // etc.
- Heap::IterateStrongRoots(visitor);
+class SymbolMarkingVisitor : public ObjectVisitor {
+ public:
+ void VisitPointers(Object** start, Object** end) {
+ MarkingVisitor marker;
+ for (Object** p = start; p < end; p++) {
+ if (!(*p)->IsHeapObject()) continue;
- // Take care of the symbol table specially.
+ HeapObject* object = HeapObject::cast(*p);
+ // If the object is marked, we have marked or are in the process
+ // of marking subparts.
+ if (object->IsMarked()) continue;
+
+ // The object is unmarked, we do not need to unmark to use its
+ // map.
+ Map* map = object->map();
+ object->IterateBody(map->instance_type(),
+ object->SizeFromMap(map),
+ &marker);
+ }
+ }
+};
+
+
+void MarkCompactCollector::MarkSymbolTable() {
+ // Objects reachable from symbols are marked as live so as to ensure
+ // that if the symbol itself remains alive after GC for any reason,
+ // and if it is a sliced string or a cons string backed by an
+ // external string (even indirectly), then the external string does
+ // not receive a weak reference callback.
SymbolTable* symbol_table = SymbolTable::cast(Heap::symbol_table());
- // 1. Mark the prefix of the symbol table gray.
- symbol_table->IteratePrefix(visitor);
- // 2. Mark the symbol table black (ie, do not push it on the marking stack
- // or mark it overflowed).
+ // Mark the symbol table itself.
SetMark(symbol_table);
+ // Explicitly mark the prefix.
+ MarkingVisitor marker;
+ symbol_table->IteratePrefix(&marker);
+ ProcessMarkingStack(&marker);
+ // Mark subparts of the symbols but not the symbols themselves
+ // (unless reachable from another symbol).
+ SymbolMarkingVisitor symbol_marker;
+ symbol_table->IterateElements(&symbol_marker);
+ ProcessMarkingStack(&marker);
+}
+
+
+void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) {
+ // Mark the heap roots including global variables, stack variables,
+ // etc., and all objects reachable from them.
+ Heap::IterateStrongRoots(visitor);
+
+ // Handle the symbol table specially.
+ MarkSymbolTable();
// There may be overflowed objects in the heap. Visit them now.
while (marking_stack.overflowed()) {
@@ -715,21 +752,22 @@ void MarkCompactCollector::MarkLiveObjects() {
ASSERT(!marking_stack.overflowed());
RootMarkingVisitor root_visitor;
- ProcessRoots(&root_visitor);
+ MarkRoots(&root_visitor);
- // The objects reachable from the roots are marked black, unreachable
- // objects are white. Mark objects reachable from object groups with at
- // least one marked object, and continue until no new objects are
- // reachable from the object groups.
+ // The objects reachable from the roots are marked, yet unreachable
+ // objects are unmarked. Mark objects reachable from object groups
+ // containing at least one marked object, and continue until no new
+ // objects are reachable from the object groups.
ProcessObjectGroups(root_visitor.stack_visitor());
- // The objects reachable from the roots or object groups are marked black,
- // unreachable objects are white. Process objects reachable only from
- // weak global handles.
+ // The objects reachable from the roots or object groups are marked,
+ // yet unreachable objects are unmarked. Mark objects reachable
+ // only from weak global handles.
//
- // First we mark weak pointers not yet reachable.
- GlobalHandles::MarkWeakRoots(&MustBeMarked);
- // Then we process weak pointers and process the transitive closure.
+ // First we identify nonlive weak handles and mark them as pending
+ // destruction.
+ GlobalHandles::IdentifyWeakHandles(&IsUnmarkedHeapObject);
+ // Then we mark the objects and process the transitive closure.
GlobalHandles::IterateWeakRoots(&root_visitor);
while (marking_stack.overflowed()) {
RefillMarkingStack();
diff --git a/deps/v8/src/mark-compact.h b/deps/v8/src/mark-compact.h
index 9a92ade5f..bfa2c3ce5 100644
--- a/deps/v8/src/mark-compact.h
+++ b/deps/v8/src/mark-compact.h
@@ -172,7 +172,11 @@ class MarkCompactCollector: public AllStatic {
static void MarkDescriptorArray(DescriptorArray* descriptors);
// Mark the heap roots and all objects reachable from them.
- static void ProcessRoots(RootMarkingVisitor* visitor);
+ static void MarkRoots(RootMarkingVisitor* visitor);
+
+ // Mark the symbol table specially. References to symbols from the
+ // symbol table are weak.
+ static void MarkSymbolTable();
// Mark objects in object groups that have at least one object in the
// group marked.
@@ -198,8 +202,9 @@ class MarkCompactCollector: public AllStatic {
// flag on the marking stack.
static void RefillMarkingStack();
- // Callback function for telling whether the object *p must be marked.
- static bool MustBeMarked(Object** p);
+ // Callback function for telling whether the object *p is an unmarked
+ // heap object.
+ static bool IsUnmarkedHeapObject(Object** p);
#ifdef DEBUG
static void UpdateLiveObjectCount(HeapObject* obj);
diff --git a/deps/v8/src/math.js b/deps/v8/src/math.js
index 5b7c396cd..86d6dd101 100644
--- a/deps/v8/src/math.js
+++ b/deps/v8/src/math.js
@@ -164,7 +164,7 @@ function SetupMath() {
// Setup non-enumerable functions of the Math object and
// set their names.
- InstallFunctions($Math, DONT_ENUM, $Array(
+ InstallFunctionsOnHiddenPrototype($Math, DONT_ENUM, $Array(
"random", MathRandom,
"abs", MathAbs,
"acos", MathAcos,
diff --git a/deps/v8/src/messages.js b/deps/v8/src/messages.js
index cd9a1e8d6..df8a2d1d7 100644
--- a/deps/v8/src/messages.js
+++ b/deps/v8/src/messages.js
@@ -98,6 +98,7 @@ const kMessages = {
instanceof_function_expected: "Expecting a function in instanceof check, but got %0",
instanceof_nonobject_proto: "Function has non-object prototype '%0' in instanceof check",
null_to_object: "Cannot convert null to object",
+ reduce_no_initial: "Reduce of empty array with no initial value",
// RangeError
invalid_array_length: "Invalid array length",
invalid_array_apply_length: "Function.prototype.apply supports only up to 1024 arguments",
@@ -113,6 +114,9 @@ const kMessages = {
illegal_return: "Illegal return statement",
error_loading_debugger: "Error loading debugger %0",
no_input_to_regexp: "No input to %0",
+ result_not_primitive: "Result of %0 must be a primitive, was %1",
+ invalid_json: "String '%0' is not valid JSON",
+ circular_structure: "Converting circular structure to JSON"
};
diff --git a/deps/v8/src/mirror-delay.js b/deps/v8/src/mirror-delay.js
index 9c9d713da..30f19f0a0 100644
--- a/deps/v8/src/mirror-delay.js
+++ b/deps/v8/src/mirror-delay.js
@@ -155,6 +155,7 @@ const ERROR_TYPE = 'error';
const PROPERTY_TYPE = 'property';
const FRAME_TYPE = 'frame';
const SCRIPT_TYPE = 'script';
+const CONTEXT_TYPE = 'context';
// Maximum length when sending strings through the JSON protocol.
const kMaxProtocolStringLength = 80;
@@ -364,6 +365,15 @@ Mirror.prototype.isScript = function() {
/**
+ * Check whether the mirror reflects a context.
+ * @returns {boolean} True if the mirror reflects a context
+ */
+Mirror.prototype.isContext = function() {
+ return this instanceof ContextMirror;
+}
+
+
+/**
* Allocate a handle id for this object.
*/
Mirror.prototype.allocateHandle_ = function() {
@@ -756,6 +766,15 @@ FunctionMirror.prototype.name = function() {
/**
+ * Returns the inferred name of the function.
+ * @return {string} Name of the function
+ */
+FunctionMirror.prototype.inferredName = function() {
+ return %FunctionGetInferredName(this.value_);
+};
+
+
+/**
* Returns the source code for the function.
* @return {string or undefined} The source code for the function. If the
* function is not resolved undefined will be returned.
@@ -857,6 +876,11 @@ UnresolvedFunctionMirror.prototype.name = function() {
};
+UnresolvedFunctionMirror.prototype.inferredName = function() {
+ return undefined;
+};
+
+
UnresolvedFunctionMirror.prototype.propertyNames = function(kind, limit) {
return [];
}
@@ -1547,6 +1571,7 @@ FrameMirror.prototype.toText = function(opt_locals) {
function ScriptMirror(script) {
Mirror.call(this, SCRIPT_TYPE);
this.script_ = script;
+ this.context_ = new ContextMirror(script.context_data);
this.allocateHandle_();
}
inherits(ScriptMirror, Mirror);
@@ -1582,6 +1607,11 @@ ScriptMirror.prototype.columnOffset = function() {
};
+ScriptMirror.prototype.data = function() {
+ return this.script_.data;
+};
+
+
ScriptMirror.prototype.scriptType = function() {
return this.script_.type;
};
@@ -1603,6 +1633,11 @@ ScriptMirror.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
}
+ScriptMirror.prototype.context = function() {
+ return this.context_;
+};
+
+
ScriptMirror.prototype.toText = function() {
var result = '';
result += this.name();
@@ -1620,13 +1655,35 @@ ScriptMirror.prototype.toText = function() {
/**
+ * Mirror object for context.
+ * @param {Object} data The context data
+ * @constructor
+ * @extends Mirror
+ */
+function ContextMirror(data) {
+ Mirror.call(this, CONTEXT_TYPE);
+ this.data_ = data;
+ this.allocateHandle_();
+}
+inherits(ContextMirror, Mirror);
+
+
+ContextMirror.prototype.data = function() {
+ return this.data_;
+};
+
+
+/**
* Returns a mirror serializer
*
* @param {boolean} details Set to true to include details
+ * @param {Object} options Options comtrolling the serialization
+ * The following options can be set:
+ * includeSource: include ths full source of scripts
* @returns {MirrorSerializer} mirror serializer
*/
-function MakeMirrorSerializer(details) {
- return new JSONProtocolSerializer(details);
+function MakeMirrorSerializer(details, options) {
+ return new JSONProtocolSerializer(details, options);
}
@@ -1636,8 +1693,9 @@ function MakeMirrorSerializer(details) {
* serialized
* @constructor
*/
-function JSONProtocolSerializer(details) {
+function JSONProtocolSerializer(details, options) {
this.details_ = details;
+ this.options_ = options;
this.mirrors_ = [ ];
}
@@ -1689,6 +1747,11 @@ JSONProtocolSerializer.prototype.serializeReferencedObjects = function() {
}
+JSONProtocolSerializer.prototype.includeSource_ = function() {
+ return this.options_ && this.options_.includeSource;
+}
+
+
JSONProtocolSerializer.prototype.add_ = function(mirror) {
// If this mirror is already in the list just return.
for (var i = 0; i < this.mirrors_.length; i++) {
@@ -1707,7 +1770,7 @@ JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
// If serializing a reference to a mirror just return the reference and add
// the mirror to the referenced mirrors.
if (reference &&
- (mirror.isValue() || mirror.isScript())) {
+ (mirror.isValue() || mirror.isScript() || mirror.isContext())) {
this.add_(mirror);
return '{"ref":' + mirror.handle() + '}';
}
@@ -1716,7 +1779,7 @@ JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
var content = new Array();
// Add the mirror handle.
- if (mirror.isValue() || mirror.isScript()) {
+ if (mirror.isValue() || mirror.isScript() || mirror.isContext()) {
content.push(MakeJSONPair_('handle', NumberToJSON_(mirror.handle())));
}
@@ -1782,8 +1845,29 @@ JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
NumberToJSON_(mirror.columnOffset())));
content.push(MakeJSONPair_('lineCount',
NumberToJSON_(mirror.lineCount())));
+ if (mirror.data()) {
+ content.push(MakeJSONPair_('data', JSON.stringify(mirror.data())));
+ }
+ if (this.includeSource_()) {
+ content.push(MakeJSONPair_('source',
+ StringToJSON_(mirror.source())));
+ } else {
+ var sourceStart = mirror.source().substring(0, 80);
+ content.push(MakeJSONPair_('sourceStart',
+ StringToJSON_(sourceStart)));
+ }
+ content.push(MakeJSONPair_('sourceLength',
+ NumberToJSON_(mirror.source().length)));
content.push(MakeJSONPair_('scriptType',
NumberToJSON_(mirror.scriptType())));
+ if (mirror.context()) {
+ content.push(MakeJSONPair_('context',
+ this.serializeReference(mirror.context())));
+ }
+ break;
+
+ case CONTEXT_TYPE:
+ content.push(MakeJSONPair_('data', JSON.stringify(mirror.data())));
break;
}
@@ -1830,6 +1914,10 @@ JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content,
if (mirror.isFunction()) {
// Add function specific properties.
content.push(MakeJSONPair_('name', StringToJSON_(mirror.name())));
+ if (!IS_UNDEFINED(mirror.inferredName())) {
+ content.push(MakeJSONPair_('inferredName',
+ StringToJSON_(mirror.inferredName())));
+ }
content.push(MakeJSONPair_('resolved', BooleanToJSON_(mirror.resolved())));
if (mirror.resolved()) {
content.push(MakeJSONPair_('source', StringToJSON_(mirror.source())));
diff --git a/deps/v8/src/objects-debug.cc b/deps/v8/src/objects-debug.cc
index f40fd3e6b..e17201478 100644
--- a/deps/v8/src/objects-debug.cc
+++ b/deps/v8/src/objects-debug.cc
@@ -558,8 +558,6 @@ void SharedFunctionInfo::SharedFunctionInfoPrint() {
code()->ShortPrint();
PrintF("\n - source code = ");
GetSourceCode()->ShortPrint();
- PrintF("\n - lazy load: %s",
- lazy_load_data() == Heap::undefined_value() ? "no" : "yes");
// Script files are often large, hard to read.
// PrintF("\n - script =");
// script()->Print();
@@ -579,7 +577,6 @@ void SharedFunctionInfo::SharedFunctionInfoVerify() {
VerifyObjectField(kCodeOffset);
VerifyObjectField(kInstanceClassNameOffset);
VerifyObjectField(kExternalReferenceDataOffset);
- VerifyObjectField(kLazyLoadDataOffset);
VerifyObjectField(kScriptOffset);
VerifyObjectField(kDebugInfoOffset);
}
@@ -924,7 +921,11 @@ void Script::ScriptVerify() {
VerifyPointer(name());
line_offset()->SmiVerify();
column_offset()->SmiVerify();
+ VerifyPointer(data());
+ VerifyPointer(wrapper());
type()->SmiVerify();
+ VerifyPointer(line_ends());
+ VerifyPointer(id());
}
diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h
index c2143ea02..782117808 100644
--- a/deps/v8/src/objects-inl.h
+++ b/deps/v8/src/objects-inl.h
@@ -144,14 +144,14 @@ bool Object::IsSeqString() {
bool Object::IsSeqAsciiString() {
if (!IsString()) return false;
return StringShape(String::cast(this)).IsSequential() &&
- StringShape(String::cast(this)).IsAsciiRepresentation();
+ String::cast(this)->IsAsciiRepresentation();
}
bool Object::IsSeqTwoByteString() {
if (!IsString()) return false;
return StringShape(String::cast(this)).IsSequential() &&
- StringShape(String::cast(this)).IsTwoByteRepresentation();
+ String::cast(this)->IsTwoByteRepresentation();
}
@@ -164,14 +164,14 @@ bool Object::IsExternalString() {
bool Object::IsExternalAsciiString() {
if (!IsString()) return false;
return StringShape(String::cast(this)).IsExternal() &&
- StringShape(String::cast(this)).IsAsciiRepresentation();
+ String::cast(this)->IsAsciiRepresentation();
}
bool Object::IsExternalTwoByteString() {
if (!IsString()) return false;
return StringShape(String::cast(this)).IsExternal() &&
- StringShape(String::cast(this)).IsTwoByteRepresentation();
+ String::cast(this)->IsTwoByteRepresentation();
}
@@ -211,13 +211,28 @@ bool StringShape::IsSymbol() {
}
-bool StringShape::IsAsciiRepresentation() {
- return (type_ & kStringEncodingMask) == kAsciiStringTag;
+bool String::IsAsciiRepresentation() {
+ uint32_t type = map()->instance_type();
+ if ((type & kStringRepresentationMask) == kSlicedStringTag) {
+ return SlicedString::cast(this)->buffer()->IsAsciiRepresentation();
+ }
+ if ((type & kStringRepresentationMask) == kConsStringTag &&
+ ConsString::cast(this)->second()->length() == 0) {
+ return ConsString::cast(this)->first()->IsAsciiRepresentation();
+ }
+ return (type & kStringEncodingMask) == kAsciiStringTag;
}
-bool StringShape::IsTwoByteRepresentation() {
- return (type_ & kStringEncodingMask) == kTwoByteStringTag;
+bool String::IsTwoByteRepresentation() {
+ uint32_t type = map()->instance_type();
+ if ((type & kStringRepresentationMask) == kSlicedStringTag) {
+ return SlicedString::cast(this)->buffer()->IsTwoByteRepresentation();
+ } else if ((type & kStringRepresentationMask) == kConsStringTag &&
+ ConsString::cast(this)->second()->length() == 0) {
+ return ConsString::cast(this)->first()->IsTwoByteRepresentation();
+ }
+ return (type & kStringEncodingMask) == kTwoByteStringTag;
}
@@ -668,12 +683,20 @@ Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
int Smi::value() {
- return reinterpret_cast<int>(this) >> kSmiTagSize;
+ return static_cast<int>(reinterpret_cast<intptr_t>(this) >> kSmiTagSize);
}
Smi* Smi::FromInt(int value) {
ASSERT(Smi::IsValid(value));
+ intptr_t tagged_value =
+ (static_cast<intptr_t>(value) << kSmiTagSize) | kSmiTag;
+ return reinterpret_cast<Smi*>(tagged_value);
+}
+
+
+Smi* Smi::FromIntptr(intptr_t value) {
+ ASSERT(Smi::IsValid(value));
return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
}
@@ -724,7 +747,7 @@ Failure* Failure::OutOfMemoryException() {
int Failure::value() const {
- return reinterpret_cast<int>(this) >> kFailureTagSize;
+ return static_cast<int>(reinterpret_cast<intptr_t>(this) >> kFailureTagSize);
}
@@ -742,7 +765,8 @@ Failure* Failure::RetryAfterGC(int requested_bytes) {
Failure* Failure::Construct(Type type, int value) {
int info = (value << kFailureTypeTagSize) | type;
ASSERT(Smi::IsValid(info)); // Same validation check as in Smi
- return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
+ return reinterpret_cast<Failure*>(
+ static_cast<intptr_t>((info << kFailureTagSize) | kFailureTag));
}
@@ -768,6 +792,18 @@ bool Smi::IsValid(int value) {
}
+bool Smi::IsIntptrValid(intptr_t value) {
+#ifdef DEBUG
+ bool in_range = (value >= kMinValue) && (value <= kMaxValue);
+#endif
+ // See Smi::IsValid(int) for description.
+ bool result =
+ ((static_cast<uintptr_t>(value) + 0x40000000U) < 0x80000000U);
+ ASSERT(result == in_range);
+ return result;
+}
+
+
MapWord MapWord::FromMap(Map* map) {
return MapWord(reinterpret_cast<uintptr_t>(map));
}
@@ -1476,7 +1512,7 @@ void String::Set(int index, uint16_t value) {
ASSERT(index >= 0 && index < length());
ASSERT(StringShape(this).IsSequential());
- return StringShape(this).IsAsciiRepresentation()
+ return this->IsAsciiRepresentation()
? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
: SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
}
@@ -1576,11 +1612,6 @@ int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
String* ConsString::first() {
- ASSERT(String::cast(READ_FIELD(this, kSecondOffset))->length() != 0 ||
- StringShape(
- String::cast(
- READ_FIELD(this, kFirstOffset))).IsAsciiRepresentation()
- == StringShape(this).IsAsciiRepresentation());
return String::cast(READ_FIELD(this, kFirstOffset));
}
@@ -1613,10 +1644,6 @@ void ConsString::set_second(String* value, WriteBarrierMode mode) {
String* SlicedString::buffer() {
- ASSERT(
- StringShape(
- String::cast(READ_FIELD(this, kBufferOffset))).IsAsciiRepresentation()
- == StringShape(this).IsAsciiRepresentation());
return String::cast(READ_FIELD(this, kBufferOffset));
}
@@ -1811,6 +1838,16 @@ void Map::set_bit_field(byte value) {
}
+byte Map::bit_field2() {
+ return READ_BYTE_FIELD(this, kBitField2Offset);
+}
+
+
+void Map::set_bit_field2(byte value) {
+ WRITE_BYTE_FIELD(this, kBitField2Offset, value);
+}
+
+
void Map::set_non_instance_prototype(bool value) {
if (value) {
set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
@@ -2053,10 +2090,13 @@ ACCESSORS(Script, name, Object, kNameOffset)
ACCESSORS(Script, id, Object, kIdOffset)
ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
+ACCESSORS(Script, data, Object, kDataOffset)
+ACCESSORS(Script, context_data, Object, kContextOffset)
ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
ACCESSORS(Script, type, Smi, kTypeOffset)
ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
+#ifdef ENABLE_DEBUGGER_SUPPORT
ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
@@ -2066,13 +2106,13 @@ ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
+#endif
ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
kInstanceClassNameOffset)
ACCESSORS(SharedFunctionInfo, function_data, Object,
kExternalReferenceDataOffset)
-ACCESSORS(SharedFunctionInfo, lazy_load_data, Object, kLazyLoadDataOffset)
ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
@@ -2138,8 +2178,8 @@ bool JSFunction::IsBoilerplate() {
}
-bool JSFunction::IsLoaded() {
- return shared()->lazy_load_data() == Heap::undefined_value();
+bool JSObject::IsLoaded() {
+ return !map()->needs_loading();
}
diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc
index 9c640f463..9a7f7aa67 100644
--- a/deps/v8/src/objects.cc
+++ b/deps/v8/src/objects.cc
@@ -43,22 +43,6 @@
namespace v8 { namespace internal {
-#define FIELD_ADDR(p, offset) \
- (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
-
-
-#define WRITE_FIELD(p, offset, value) \
- (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
-
-
-#define WRITE_INT_FIELD(p, offset, value) \
- (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
-
-
-#define WRITE_BARRIER(object, offset) \
- Heap::RecordWrite(object->address(), offset);
-
-
// Getters and setters are stored in a fixed array property. These are
// constants for their indices.
const int kGetterIndex = 0;
@@ -374,7 +358,7 @@ Object* JSObject::GetLazyProperty(Object* receiver,
Handle<Object> receiver_handle(receiver);
Handle<String> name_handle(name);
bool pending_exception;
- LoadLazy(Handle<JSFunction>(JSFunction::cast(result->GetValue())),
+ LoadLazy(Handle<JSObject>(JSObject::cast(result->GetLazyValue())),
&pending_exception);
if (pending_exception) return Failure::Exception();
return this_handle->GetPropertyWithReceiver(*receiver_handle,
@@ -393,7 +377,7 @@ Object* JSObject::SetLazyProperty(LookupResult* result,
Handle<String> name_handle(name);
Handle<Object> value_handle(value);
bool pending_exception;
- LoadLazy(Handle<JSFunction>(JSFunction::cast(result->GetValue())),
+ LoadLazy(Handle<JSObject>(JSObject::cast(result->GetLazyValue())),
&pending_exception);
if (pending_exception) return Failure::Exception();
return this_handle->SetProperty(*name_handle, *value_handle, attributes);
@@ -405,7 +389,7 @@ Object* JSObject::DeleteLazyProperty(LookupResult* result, String* name) {
Handle<JSObject> this_handle(this);
Handle<String> name_handle(name);
bool pending_exception;
- LoadLazy(Handle<JSFunction>(JSFunction::cast(result->GetValue())),
+ LoadLazy(Handle<JSObject>(JSObject::cast(result->GetLazyValue())),
&pending_exception);
if (pending_exception) return Failure::Exception();
return this_handle->DeleteProperty(*name_handle);
@@ -618,8 +602,6 @@ Object* String::TryFlatten() {
if (StringShape(String::cast(ok)).IsCons()) {
ss->set_buffer(ConsString::cast(ok)->first());
}
- ASSERT(StringShape(this).IsAsciiRepresentation() ==
- StringShape(ss->buffer()).IsAsciiRepresentation());
return this;
}
case kConsStringTag: {
@@ -634,7 +616,7 @@ Object* String::TryFlatten() {
int len = length();
Object* object;
String* result;
- if (StringShape(this).IsAsciiRepresentation()) {
+ if (IsAsciiRepresentation()) {
object = Heap::AllocateRawAsciiString(len, tenure);
if (object->IsFailure()) return object;
result = String::cast(object);
@@ -972,10 +954,11 @@ int HeapObject::SlowSizeFromMap(Map* map) {
// Avoid calling functions such as FixedArray::cast during GC, which
// read map pointer of this object again.
InstanceType instance_type = map->instance_type();
+ uint32_t type = static_cast<uint32_t>(instance_type);
if (instance_type < FIRST_NONSTRING_TYPE
&& (StringShape(instance_type).IsSequential())) {
- if (StringShape(instance_type).IsAsciiRepresentation()) {
+ if ((type & kStringEncodingMask) == kAsciiStringTag) {
SeqAsciiString* seq_ascii_this = reinterpret_cast<SeqAsciiString*>(this);
return seq_ascii_this->SeqAsciiStringSize(instance_type);
} else {
@@ -1174,7 +1157,7 @@ Object* JSObject::AddFastProperty(String* name,
(index - map()->inobject_properties()) < properties()->length() ||
map()->unused_property_fields() == 0);
// Allocate a new map for the object.
- Object* r = map()->Copy();
+ Object* r = map()->CopyDropDescriptors();
if (r->IsFailure()) return r;
Map* new_map = Map::cast(r);
if (allow_map_transition) {
@@ -1219,7 +1202,7 @@ Object* JSObject::AddConstantFunctionProperty(String* name,
if (new_descriptors->IsFailure()) return new_descriptors;
// Allocate a new map for the object.
- Object* new_map = map()->Copy();
+ Object* new_map = map()->CopyDropDescriptors();
if (new_map->IsFailure()) return new_map;
DescriptorArray* descriptors = DescriptorArray::cast(new_descriptors);
@@ -1377,7 +1360,7 @@ Object* JSObject::ConvertDescriptorToField(String* name,
DescriptorArray::cast(descriptors_unchecked);
// Make a new map for the object.
- Object* new_map_unchecked = map()->Copy();
+ Object* new_map_unchecked = map()->CopyDropDescriptors();
if (new_map_unchecked->IsFailure()) return new_map_unchecked;
Map* new_map = Map::cast(new_map_unchecked);
new_map->set_instance_descriptors(new_descriptors);
@@ -1800,6 +1783,17 @@ Object* JSObject::IgnoreAttributesAndSetLocalProperty(
&& !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
return SetPropertyWithFailedAccessCheck(result, name, value);
}
+
+ if (IsJSGlobalProxy()) {
+ Object* proto = GetPrototype();
+ if (proto->IsNull()) return value;
+ ASSERT(proto->IsJSGlobalObject());
+ return JSObject::cast(proto)->IgnoreAttributesAndSetLocalProperty(
+ name,
+ value,
+ attributes);
+ }
+
// Check for accessor in prototype chain removed here in clone.
if (result->IsNotFound()) {
return AddProperty(name, value, attributes);
@@ -1820,20 +1814,16 @@ Object* JSObject::IgnoreAttributesAndSetLocalProperty(
return AddFastPropertyUsingMap(result->GetTransitionMap(),
name,
value);
- } else {
- return ConvertDescriptorToField(name, value, attributes);
}
+ return ConvertDescriptorToField(name, value, attributes);
case CONSTANT_FUNCTION:
if (value == result->GetConstantFunction()) return value;
// Only replace the function if necessary.
return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
case CALLBACKS:
- return SetPropertyWithCallback(result->GetCallbackObject(),
- name,
- value,
- result->holder());
case INTERCEPTOR:
- return SetPropertyWithInterceptor(name, value, attributes);
+ // Override callback in clone
+ return ConvertDescriptorToField(name, value, attributes);
case CONSTANT_TRANSITION:
// Replace with a MAP_TRANSITION to a new map with a FIELD, even
// if the value is a function.
@@ -2041,7 +2031,7 @@ Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode) {
dictionary->SetNextEnumerationIndex(index);
// Allocate new map.
- obj = map()->Copy();
+ obj = map()->CopyDropDescriptors();
if (obj->IsFailure()) return obj;
Map* new_map = Map::cast(obj);
@@ -2713,24 +2703,29 @@ Object* JSObject::SlowReverseLookup(Object* value) {
}
-Object* Map::Copy() {
+Object* Map::CopyDropDescriptors() {
Object* result = Heap::AllocateMap(instance_type(), instance_size());
if (result->IsFailure()) return result;
Map::cast(result)->set_prototype(prototype());
Map::cast(result)->set_constructor(constructor());
// Don't copy descriptors, so map transitions always remain a forest.
+ // If we retained the same descriptors we would have two maps
+ // pointing to the same transition which is bad because the garbage
+ // collector relies on being able to reverse pointers from transitions
+ // to maps. If properties need to be retained use CopyDropTransitions.
Map::cast(result)->set_instance_descriptors(Heap::empty_descriptor_array());
// Please note instance_type and instance_size are set when allocated.
Map::cast(result)->set_inobject_properties(inobject_properties());
Map::cast(result)->set_unused_property_fields(unused_property_fields());
Map::cast(result)->set_bit_field(bit_field());
+ Map::cast(result)->set_bit_field2(bit_field2());
Map::cast(result)->ClearCodeCache();
return result;
}
Object* Map::CopyDropTransitions() {
- Object* new_map = Copy();
+ Object* new_map = CopyDropDescriptors();
if (new_map->IsFailure()) return new_map;
Object* descriptors = instance_descriptors()->RemoveTransitions();
if (descriptors->IsFailure()) return descriptors;
@@ -2854,22 +2849,26 @@ static bool HasKey(FixedArray* array, Object* key) {
Object* FixedArray::AddKeysFromJSArray(JSArray* array) {
- // Remove array holes from array if any.
- Object* object = array->RemoveHoles();
- if (object->IsFailure()) return object;
- JSArray* compacted_array = JSArray::cast(object);
+ if (array->HasFastElements()) {
+ return UnionOfKeys(array->elements());
+ }
+ ASSERT(!array->HasFastElements());
+ Dictionary* dict = array->element_dictionary();
+ int size = dict->NumberOfElements();
// Allocate a temporary fixed array.
- int compacted_array_length = Smi::cast(compacted_array->length())->value();
- object = Heap::AllocateFixedArray(compacted_array_length);
+ Object* object = Heap::AllocateFixedArray(size);
if (object->IsFailure()) return object;
FixedArray* key_array = FixedArray::cast(object);
+ int capacity = dict->Capacity();
+ int pos = 0;
// Copy the elements from the JSArray to the temporary fixed array.
- for (int i = 0; i < compacted_array_length; i++) {
- key_array->set(i, compacted_array->GetElement(i));
+ for (int i = 0; i < capacity; i++) {
+ if (dict->IsKey(dict->KeyAt(i))) {
+ key_array->set(pos++, dict->ValueAt(i));
+ }
}
-
// Compute the union of this and the temporary fixed array.
return UnionOfKeys(key_array);
}
@@ -2885,9 +2884,12 @@ Object* FixedArray::UnionOfKeys(FixedArray* other) {
// Compute how many elements are not in this.
int extra = 0;
for (int y = 0; y < len1; y++) {
- if (!HasKey(this, other->get(y))) extra++;
+ Object* value = other->get(y);
+ if (!value->IsTheHole() && !HasKey(this, value)) extra++;
}
+ if (extra == 0) return this;
+
// Allocate the result
Object* obj = Heap::AllocateFixedArray(len0 + extra);
if (obj->IsFailure()) return obj;
@@ -2900,7 +2902,8 @@ Object* FixedArray::UnionOfKeys(FixedArray* other) {
// Fill in the extra keys.
int index = 0;
for (int y = 0; y < len1; y++) {
- if (!HasKey(this, other->get(y))) {
+ Object* value = other->get(y);
+ if (!value->IsTheHole() && !HasKey(this, value)) {
result->set(len0 + index, other->get(y), mode);
index++;
}
@@ -3231,7 +3234,7 @@ bool String::LooksValid() {
int String::Utf8Length() {
- if (StringShape(this).IsAsciiRepresentation()) return length();
+ if (IsAsciiRepresentation()) return length();
// Attempt to flatten before accessing the string. It probably
// doesn't make Utf8Length faster, but it is very likely that
// the string will be accessed later (for example by WriteUtf8)
@@ -3247,7 +3250,7 @@ int String::Utf8Length() {
Vector<const char> String::ToAsciiVector() {
- ASSERT(StringShape(this).IsAsciiRepresentation());
+ ASSERT(IsAsciiRepresentation());
ASSERT(IsFlat());
int offset = 0;
@@ -3278,7 +3281,7 @@ Vector<const char> String::ToAsciiVector() {
Vector<const uc16> String::ToUC16Vector() {
- ASSERT(StringShape(this).IsTwoByteRepresentation());
+ ASSERT(IsTwoByteRepresentation());
ASSERT(IsFlat());
int offset = 0;
@@ -3302,13 +3305,6 @@ Vector<const uc16> String::ToUC16Vector() {
}
ASSERT(string_tag == kExternalStringTag);
ExternalTwoByteString* ext = ExternalTwoByteString::cast(string);
- // This is a workaround for Chromium bug 9746: http://crbug.com/9746
- // For external strings with a deleted resource we return a special
- // Vector which will not compare to any string when doing SymbolTable
- // lookups.
- if (ext->resource() == NULL) {
- return Vector<const uc16>(NULL, length);
- }
const uc16* start =
reinterpret_cast<const uc16*>(ext->resource()->data());
return Vector<const uc16>(start + offset, length);
@@ -3381,7 +3377,7 @@ const uc16* String::GetTwoByteData() {
const uc16* String::GetTwoByteData(unsigned start) {
- ASSERT(!StringShape(this).IsAsciiRepresentation());
+ ASSERT(!IsAsciiRepresentation());
switch (StringShape(this).representation_tag()) {
case kSeqStringTag:
return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
@@ -3676,7 +3672,7 @@ const unibrow::byte* String::ReadBlock(String* input,
}
switch (StringShape(input).representation_tag()) {
case kSeqStringTag:
- if (StringShape(input).IsAsciiRepresentation()) {
+ if (input->IsAsciiRepresentation()) {
SeqAsciiString* str = SeqAsciiString::cast(input);
return str->SeqAsciiStringReadBlock(&rbb->remaining,
offset_ptr,
@@ -3697,7 +3693,7 @@ const unibrow::byte* String::ReadBlock(String* input,
offset_ptr,
max_chars);
case kExternalStringTag:
- if (StringShape(input).IsAsciiRepresentation()) {
+ if (input->IsAsciiRepresentation()) {
return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock(
&rbb->remaining,
offset_ptr,
@@ -3750,7 +3746,7 @@ void FlatStringReader::RefreshState() {
if (str_ == NULL) return;
Handle<String> str(str_);
ASSERT(str->IsFlat());
- is_ascii_ = StringShape(*str).IsAsciiRepresentation();
+ is_ascii_ = str->IsAsciiRepresentation();
if (is_ascii_) {
start_ = str->ToAsciiVector().start();
} else {
@@ -3791,7 +3787,7 @@ void String::ReadBlockIntoBuffer(String* input,
switch (StringShape(input).representation_tag()) {
case kSeqStringTag:
- if (StringShape(input).IsAsciiRepresentation()) {
+ if (input->IsAsciiRepresentation()) {
SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb,
offset_ptr,
max_chars);
@@ -3813,7 +3809,7 @@ void String::ReadBlockIntoBuffer(String* input,
max_chars);
return;
case kExternalStringTag:
- if (StringShape(input).IsAsciiRepresentation()) {
+ if (input->IsAsciiRepresentation()) {
ExternalAsciiString::cast(input)->
ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
} else {
@@ -4093,7 +4089,7 @@ static inline bool CompareRawStringContents(Vector<Char> a, Vector<Char> b) {
const Char* pa = a.start();
const Char* pb = b.start();
int i = 0;
-#ifndef CAN_READ_UNALIGNED
+#ifndef V8_HOST_CAN_READ_UNALIGNED
// If this architecture isn't comfortable reading unaligned ints
// then we have to check that the strings are aligned before
// comparing them blockwise.
@@ -4112,7 +4108,7 @@ static inline bool CompareRawStringContents(Vector<Char> a, Vector<Char> b) {
return false;
}
}
-#ifndef CAN_READ_UNALIGNED
+#ifndef V8_HOST_CAN_READ_UNALIGNED
}
#endif
// Compare the remaining characters that didn't fit into a block.
@@ -4125,31 +4121,17 @@ static inline bool CompareRawStringContents(Vector<Char> a, Vector<Char> b) {
}
-// This is a workaround for Chromium bug 9746: http://crbug.com/9746
-// Returns true if this Vector matches the problem exposed in the bug.
-template <typename T>
-static bool CheckVectorForBug9746(Vector<T> vec) {
- // The problem is that somehow external string entries in the symbol
- // table can have their resources collected while they are still in the
- // table. This should not happen according to the test in the function
- // DisposeExternalString in api.cc, but we have evidence that it does.
- return (vec.start() == NULL) ? true : false;
-}
-
-
static StringInputBuffer string_compare_buffer_b;
template <typename IteratorA>
static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) {
if (b->IsFlat()) {
- if (StringShape(b).IsAsciiRepresentation()) {
+ if (b->IsAsciiRepresentation()) {
VectorIterator<char> ib(b->ToAsciiVector());
return CompareStringContents(ia, &ib);
} else {
- Vector<const uc16> vb = b->ToUC16Vector();
- if (CheckVectorForBug9746(vb)) return false;
- VectorIterator<uc16> ib(vb);
+ VectorIterator<uc16> ib(b->ToUC16Vector());
return CompareStringContents(ia, &ib);
}
} else {
@@ -4183,17 +4165,15 @@ bool String::SlowEquals(String* other) {
}
if (this->IsFlat()) {
- if (StringShape(this).IsAsciiRepresentation()) {
+ if (IsAsciiRepresentation()) {
Vector<const char> vec1 = this->ToAsciiVector();
if (other->IsFlat()) {
- if (StringShape(other).IsAsciiRepresentation()) {
+ if (other->IsAsciiRepresentation()) {
Vector<const char> vec2 = other->ToAsciiVector();
return CompareRawStringContents(vec1, vec2);
} else {
VectorIterator<char> buf1(vec1);
- Vector<const uc16> vec2 = other->ToUC16Vector();
- if (CheckVectorForBug9746(vec2)) return false;
- VectorIterator<uc16> ib(vec2);
+ VectorIterator<uc16> ib(other->ToUC16Vector());
return CompareStringContents(&buf1, &ib);
}
} else {
@@ -4203,15 +4183,13 @@ bool String::SlowEquals(String* other) {
}
} else {
Vector<const uc16> vec1 = this->ToUC16Vector();
- if (CheckVectorForBug9746(vec1)) return false;
if (other->IsFlat()) {
- if (StringShape(other).IsAsciiRepresentation()) {
+ if (other->IsAsciiRepresentation()) {
VectorIterator<uc16> buf1(vec1);
VectorIterator<char> ib(other->ToAsciiVector());
return CompareStringContents(&buf1, &ib);
} else {
- Vector<const uc16> vec2 = other->ToUC16Vector();
- if (CheckVectorForBug9746(vec2)) return false;
+ Vector<const uc16> vec2(other->ToUC16Vector());
return CompareRawStringContents(vec1, vec2);
}
} else {
@@ -4256,18 +4234,6 @@ bool String::MarkAsUndetectable() {
bool String::IsEqualTo(Vector<const char> str) {
- // This is a workaround for Chromium bug 9746: http://crbug.com/9746
- // The problem is that somehow external string entries in the symbol
- // table can have their resources deleted while they are still in the
- // table. This should not happen according to the test in the function
- // DisposeExternalString in api.cc but we have evidence that it does.
- // Thus we add this bailout here.
- StringShape shape(this);
- if (shape.IsExternalTwoByte()) {
- ExternalTwoByteString* ext = ExternalTwoByteString::cast(this);
- if (ext->resource() == NULL) return false;
- }
-
int slen = length();
Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder());
decoder->Reset(str.start(), str.length());
@@ -4678,6 +4644,7 @@ void Code::ConvertICTargetsFromAddressToObject() {
it.rinfo()->set_target_object(code);
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
if (Debug::has_break_points()) {
for (RelocIterator it(this, RelocInfo::ModeMask(RelocInfo::JS_RETURN));
!it.done();
@@ -4691,6 +4658,7 @@ void Code::ConvertICTargetsFromAddressToObject() {
}
}
}
+#endif
set_ic_flag(IC_TARGET_IS_OBJECT);
}
@@ -4712,10 +4680,12 @@ void Code::CodeIterateBody(ObjectVisitor* v) {
v->VisitCodeTarget(it.rinfo());
} else if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
v->VisitExternalReference(it.rinfo()->target_reference_address());
+#ifdef ENABLE_DEBUGGER_SUPPORT
} else if (Debug::has_break_points() &&
RelocInfo::IsJSReturn(rmode) &&
it.rinfo()->IsCallInstruction()) {
v->VisitDebugTarget(it.rinfo());
+#endif
} else if (rmode == RelocInfo::RUNTIME_ENTRY) {
v->VisitRuntimeEntry(it.rinfo());
}
@@ -4740,6 +4710,7 @@ void Code::ConvertICTargetsFromObjectToAddress() {
it.rinfo()->set_target_address(code->instruction_start());
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
if (Debug::has_break_points()) {
for (RelocIterator it(this, RelocInfo::ModeMask(RelocInfo::JS_RETURN));
!it.done();
@@ -4751,6 +4722,7 @@ void Code::ConvertICTargetsFromObjectToAddress() {
}
}
}
+#endif
set_ic_flag(IC_TARGET_IS_ADDRESS);
}
@@ -5138,7 +5110,7 @@ bool JSObject::HasElementWithInterceptor(JSObject* receiver, uint32_t index) {
VMState state(EXTERNAL);
result = getter(index, info);
}
- if (!result.IsEmpty()) return !result->IsUndefined();
+ if (!result.IsEmpty()) return true;
}
return holder_handle->HasElementPostInterceptor(*receiver_handle, index);
}
@@ -5189,7 +5161,8 @@ Object* JSObject::GetHiddenProperties(bool create_if_needed) {
}
// Only attempt to find the hidden properties in the local object and not
- // in the prototype chain.
+ // in the prototype chain. Note that HasLocalProperty() can cause a GC in
+ // the general case, but in this case we know it won't hit an interceptor.
if (!this->HasLocalProperty(key)) {
// Hidden properties object not found. Allocate a new hidden properties
// object if requested. Otherwise return the undefined value.
@@ -5626,75 +5599,18 @@ bool JSObject::ShouldConvertToFastElements() {
}
-Object* Dictionary::RemoveHoles() {
- int capacity = Capacity();
- Object* obj = Allocate(NumberOfElements());
- if (obj->IsFailure()) return obj;
- Dictionary* dict = Dictionary::cast(obj);
- uint32_t pos = 0;
- for (int i = 0; i < capacity; i++) {
- Object* k = KeyAt(i);
- if (IsKey(k)) {
- dict->AddNumberEntry(pos++, ValueAt(i), DetailsAt(i));
- }
- }
- return dict;
-}
-
-
void Dictionary::CopyValuesTo(FixedArray* elements) {
int pos = 0;
int capacity = Capacity();
+ WriteBarrierMode mode = elements->GetWriteBarrierMode();
for (int i = 0; i < capacity; i++) {
Object* k = KeyAt(i);
- if (IsKey(k)) elements->set(pos++, ValueAt(i));
+ if (IsKey(k)) elements->set(pos++, ValueAt(i), mode);
}
ASSERT(pos == elements->length());
}
-Object* JSArray::RemoveHoles() {
- if (HasFastElements()) {
- int len = Smi::cast(length())->value();
- int pos = 0;
- FixedArray* elms = FixedArray::cast(elements());
- for (int index = 0; index < len; index++) {
- Object* e = elms->get(index);
- if (!e->IsTheHole()) {
- if (index != pos) elms->set(pos, e);
- pos++;
- }
- }
- set_length(Smi::FromInt(pos), SKIP_WRITE_BARRIER);
- for (int index = pos; index < len; index++) {
- elms->set_the_hole(index);
- }
- return this;
- }
-
- // Compact the sparse array if possible.
- Dictionary* dict = element_dictionary();
- int length = dict->NumberOfElements();
-
- // Try to make this a fast array again.
- if (length <= kMaxFastElementsLength) {
- Object* obj = Heap::AllocateFixedArray(length);
- if (obj->IsFailure()) return obj;
- dict->CopyValuesTo(FixedArray::cast(obj));
- set_length(Smi::FromInt(length), SKIP_WRITE_BARRIER);
- set_elements(FixedArray::cast(obj));
- return this;
- }
-
- // Make another dictionary with smaller indices.
- Object* obj = dict->RemoveHoles();
- if (obj->IsFailure()) return obj;
- set_length(Smi::FromInt(length), SKIP_WRITE_BARRIER);
- set_elements(Dictionary::cast(obj));
- return this;
-}
-
-
InterceptorInfo* JSObject::GetNamedInterceptor() {
ASSERT(map()->has_named_interceptor());
JSFunction* constructor = JSFunction::cast(map()->constructor());
@@ -5861,43 +5777,46 @@ int JSObject::NumberOfEnumProperties() {
}
-void FixedArray::Swap(int i, int j) {
+void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
Object* temp = get(i);
set(i, get(j));
set(j, temp);
+ if (this != numbers) {
+ temp = numbers->get(i);
+ numbers->set(i, numbers->get(j));
+ numbers->set(j, temp);
+ }
}
-static void InsertionSortPairs(FixedArray* content, FixedArray* smis) {
- int len = smis->length();
+static void InsertionSortPairs(FixedArray* content,
+ FixedArray* numbers,
+ int len) {
for (int i = 1; i < len; i++) {
int j = i;
while (j > 0 &&
- Smi::cast(smis->get(j-1))->value() >
- Smi::cast(smis->get(j))->value()) {
- smis->Swap(j-1, j);
- content->Swap(j-1, j);
+ (NumberToUint32(numbers->get(j - 1)) >
+ NumberToUint32(numbers->get(j)))) {
+ content->SwapPairs(numbers, j - 1, j);
j--;
}
}
}
-void HeapSortPairs(FixedArray* content, FixedArray* smis) {
+void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
// In-place heap sort.
- ASSERT(content->length() == smis->length());
- int len = smis->length();
+ ASSERT(content->length() == numbers->length());
// Bottom-up max-heap construction.
for (int i = 1; i < len; ++i) {
int child_index = i;
while (child_index > 0) {
int parent_index = ((child_index + 1) >> 1) - 1;
- int parent_value = Smi::cast(smis->get(parent_index))->value();
- int child_value = Smi::cast(smis->get(child_index))->value();
+ uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
+ uint32_t child_value = NumberToUint32(numbers->get(child_index));
if (parent_value < child_value) {
- content->Swap(parent_index, child_index);
- smis->Swap(parent_index, child_index);
+ content->SwapPairs(numbers, parent_index, child_index);
} else {
break;
}
@@ -5908,25 +5827,22 @@ void HeapSortPairs(FixedArray* content, FixedArray* smis) {
// Extract elements and create sorted array.
for (int i = len - 1; i > 0; --i) {
// Put max element at the back of the array.
- content->Swap(0, i);
- smis->Swap(0, i);
+ content->SwapPairs(numbers, 0, i);
// Sift down the new top element.
int parent_index = 0;
while (true) {
int child_index = ((parent_index + 1) << 1) - 1;
if (child_index >= i) break;
- uint32_t child1_value = Smi::cast(smis->get(child_index))->value();
- uint32_t child2_value = Smi::cast(smis->get(child_index + 1))->value();
- uint32_t parent_value = Smi::cast(smis->get(parent_index))->value();
+ uint32_t child1_value = NumberToUint32(numbers->get(child_index));
+ uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
+ uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
if (child_index + 1 >= i || child1_value > child2_value) {
if (parent_value > child1_value) break;
- content->Swap(parent_index, child_index);
- smis->Swap(parent_index, child_index);
+ content->SwapPairs(numbers, parent_index, child_index);
parent_index = child_index;
} else {
if (parent_value > child2_value) break;
- content->Swap(parent_index, child_index + 1);
- smis->Swap(parent_index, child_index + 1);
+ content->SwapPairs(numbers, parent_index, child_index + 1);
parent_index = child_index + 1;
}
}
@@ -5934,43 +5850,41 @@ void HeapSortPairs(FixedArray* content, FixedArray* smis) {
}
-// Sort this array and the smis as pairs wrt. the (distinct) smis.
-void FixedArray::SortPairs(FixedArray* smis) {
- ASSERT(this->length() == smis->length());
- int len = smis->length();
+// Sort this array and the numbers as pairs wrt. the (distinct) numbers.
+void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
+ ASSERT(this->length() == numbers->length());
// For small arrays, simply use insertion sort.
if (len <= 10) {
- InsertionSortPairs(this, smis);
+ InsertionSortPairs(this, numbers, len);
return;
}
// Check the range of indices.
- int min_index = Smi::cast(smis->get(0))->value();
- int max_index = min_index;
- int i;
+ uint32_t min_index = NumberToUint32(numbers->get(0));
+ uint32_t max_index = min_index;
+ uint32_t i;
for (i = 1; i < len; i++) {
- if (Smi::cast(smis->get(i))->value() < min_index) {
- min_index = Smi::cast(smis->get(i))->value();
- } else if (Smi::cast(smis->get(i))->value() > max_index) {
- max_index = Smi::cast(smis->get(i))->value();
+ if (NumberToUint32(numbers->get(i)) < min_index) {
+ min_index = NumberToUint32(numbers->get(i));
+ } else if (NumberToUint32(numbers->get(i)) > max_index) {
+ max_index = NumberToUint32(numbers->get(i));
}
}
if (max_index - min_index + 1 == len) {
// Indices form a contiguous range, unless there are duplicates.
- // Do an in-place linear time sort assuming distinct smis, but
+ // Do an in-place linear time sort assuming distinct numbers, but
// avoid hanging in case they are not.
for (i = 0; i < len; i++) {
- int p;
- int j = 0;
+ uint32_t p;
+ uint32_t j = 0;
// While the current element at i is not at its correct position p,
// swap the elements at these two positions.
- while ((p = Smi::cast(smis->get(i))->value() - min_index) != i &&
+ while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
j++ < len) {
- this->Swap(i, p);
- smis->Swap(i, p);
+ SwapPairs(numbers, i, p);
}
}
} else {
- HeapSortPairs(this, smis);
+ HeapSortPairs(this, numbers, len);
return;
}
}
@@ -6448,6 +6362,176 @@ template class HashTable<2, 3>;
template class HashTable<0, 2>;
+// Collates undefined and unexisting elements below limit from position
+// zero of the elements. The object stays in Dictionary mode.
+Object* JSObject::PrepareSlowElementsForSort(uint32_t limit) {
+ ASSERT(!HasFastElements());
+ // Must stay in dictionary mode, either because of requires_slow_elements,
+ // or because we are not going to sort (and therefore compact) all of the
+ // elements.
+ Dictionary* dict = element_dictionary();
+ HeapNumber* result_double = NULL;
+ if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
+ // Allocate space for result before we start mutating the object.
+ Object* new_double = Heap::AllocateHeapNumber(0.0);
+ if (new_double->IsFailure()) return new_double;
+ result_double = HeapNumber::cast(new_double);
+ }
+
+ int capacity = dict->Capacity();
+ Object* obj = Dictionary::Allocate(dict->Capacity());
+ if (obj->IsFailure()) return obj;
+ Dictionary* new_dict = Dictionary::cast(obj);
+
+ AssertNoAllocation no_alloc;
+
+ // Loose all details on properties when moving them around.
+ // Elements do not have special details like properties.
+ PropertyDetails no_details = PropertyDetails(NONE, NORMAL);
+
+ uint32_t pos = 0;
+ uint32_t undefs = 0;
+ for (int i = 0; i < capacity; i++) {
+ Object* k = dict->KeyAt(i);
+ if (dict->IsKey(k)) {
+ ASSERT(k->IsNumber());
+ ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0);
+ ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
+ ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
+ Object* value = dict->ValueAt(i);
+ uint32_t key = NumberToUint32(k);
+ if (key < limit) {
+ if (value->IsUndefined()) {
+ undefs++;
+ } else {
+ new_dict->AddNumberEntry(pos, value, no_details);
+ pos++;
+ }
+ } else {
+ new_dict->AddNumberEntry(key, value, no_details);
+ }
+ }
+ }
+
+ uint32_t result = pos;
+ while (undefs > 0) {
+ new_dict->AddNumberEntry(pos, Heap::undefined_value(), no_details);
+ pos++;
+ undefs--;
+ }
+
+ set_elements(new_dict);
+
+ if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
+ return Smi::FromInt(static_cast<int>(result));
+ }
+
+ ASSERT_NE(NULL, result_double);
+ result_double->set_value(static_cast<double>(result));
+ return result_double;
+}
+
+
+// Collects all defined (non-hole) and non-undefined (array) elements at
+// the start of the elements array.
+// If the object is in dictionary mode, it is converted to fast elements
+// mode.
+Object* JSObject::PrepareElementsForSort(uint32_t limit) {
+ if (!HasFastElements()) {
+ // Convert to fast elements containing only the existing properties.
+ // Ordering is irrelevant, since we are going to sort anyway.
+ Dictionary* dict = element_dictionary();
+ if (IsJSArray() || dict->requires_slow_elements() ||
+ dict->max_number_key() >= limit) {
+ return PrepareSlowElementsForSort(limit);
+ }
+ // Convert to fast elements.
+
+ PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED: TENURED;
+ Object* new_array =
+ Heap::AllocateFixedArray(dict->NumberOfElements(), tenure);
+ if (new_array->IsFailure()) {
+ return new_array;
+ }
+ FixedArray* fast_elements = FixedArray::cast(new_array);
+ dict->CopyValuesTo(fast_elements);
+ set_elements(fast_elements);
+ }
+ ASSERT(HasFastElements());
+
+ // Collect holes at the end, undefined before that and the rest at the
+ // start, and return the number of non-hole, non-undefined values.
+
+ FixedArray* elements = this->elements();
+ uint32_t elements_length = static_cast<uint32_t>(elements->length());
+ if (limit > elements_length) {
+ limit = elements_length ;
+ }
+ if (limit == 0) {
+ return Smi::FromInt(0);
+ }
+
+ HeapNumber* result_double = NULL;
+ if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
+ // Pessimistically allocate space for return value before
+ // we start mutating the array.
+ Object* new_double = Heap::AllocateHeapNumber(0.0);
+ if (new_double->IsFailure()) return new_double;
+ result_double = HeapNumber::cast(new_double);
+ }
+
+ AssertNoAllocation no_alloc;
+
+ // Split elements into defined, undefined and the_hole, in that order.
+ // Only count locations for undefined and the hole, and fill them afterwards.
+ WriteBarrierMode write_barrier = elements->GetWriteBarrierMode();
+ unsigned int undefs = limit;
+ unsigned int holes = limit;
+ // Assume most arrays contain no holes and undefined values, so minimize the
+ // number of stores of non-undefined, non-the-hole values.
+ for (unsigned int i = 0; i < undefs; i++) {
+ Object* current = elements->get(i);
+ if (current->IsTheHole()) {
+ holes--;
+ undefs--;
+ } else if (current->IsUndefined()) {
+ undefs--;
+ } else {
+ continue;
+ }
+ // Position i needs to be filled.
+ while (undefs > i) {
+ current = elements->get(undefs);
+ if (current->IsTheHole()) {
+ holes--;
+ undefs--;
+ } else if (current->IsUndefined()) {
+ undefs--;
+ } else {
+ elements->set(i, current, write_barrier);
+ break;
+ }
+ }
+ }
+ uint32_t result = undefs;
+ while (undefs < holes) {
+ elements->set_undefined(undefs);
+ undefs++;
+ }
+ while (holes < limit) {
+ elements->set_the_hole(holes);
+ holes++;
+ }
+
+ if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
+ return Smi::FromInt(static_cast<int>(result));
+ }
+ ASSERT_NE(NULL, result_double);
+ result_double->set_value(static_cast<double>(result));
+ return result_double;
+}
+
+
Object* SymbolTable::LookupString(String* string, Object** s) {
SymbolKey key(string);
return LookupKey(&key, s);
@@ -6758,7 +6842,7 @@ Object* Dictionary::GenerateNewEnumerationIndices() {
}
// Sort the arrays wrt. enumeration order.
- iteration_order->SortPairs(enumeration_order);
+ iteration_order->SortPairs(enumeration_order, enumeration_order->length());
// Overwrite the enumeration_order with the enumeration indices.
for (int i = 0; i < length; i++) {
@@ -7010,6 +7094,7 @@ void Dictionary::CopyKeysTo(FixedArray* storage, PropertyAttributes filter) {
if ((attr & filter) == 0) storage->set(index++, k);
}
}
+ storage->SortPairs(storage, index);
ASSERT(storage->length() >= index);
}
@@ -7031,7 +7116,7 @@ void Dictionary::CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array) {
}
}
}
- storage->SortPairs(sort_array);
+ storage->SortPairs(sort_array, sort_array->length());
ASSERT(storage->length() >= index);
}
@@ -7157,7 +7242,7 @@ Object* Dictionary::TransformPropertiesToFastFor(JSObject* obj,
descriptors->Sort();
// Allocate new map.
- Object* new_map = obj->map()->Copy();
+ Object* new_map = obj->map()->CopyDropDescriptors();
if (new_map->IsFailure()) return new_map;
// Transform the object.
@@ -7176,6 +7261,7 @@ Object* Dictionary::TransformPropertiesToFastFor(JSObject* obj,
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Check if there is a break point at this code position.
bool DebugInfo::HasBreakPoint(int code_position) {
// Get the break point info object for this code position.
@@ -7419,6 +7505,6 @@ int BreakPointInfo::GetBreakPointCount() {
// Multiple break points.
return FixedArray::cast(break_point_objects())->length();
}
-
+#endif
} } // namespace v8::internal
diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h
index ade282be6..3e132ff19 100644
--- a/deps/v8/src/objects.h
+++ b/deps/v8/src/objects.h
@@ -389,7 +389,7 @@ enum PropertyNormalizationMode {
// Note that for subtle reasons related to the ordering or numerical values of
// type tags, elements in this list have to be added to the INSTANCE_TYPE_LIST
// manually.
-#define STRUCT_LIST(V) \
+#define STRUCT_LIST_ALL(V) \
V(ACCESSOR_INFO, AccessorInfo, accessor_info) \
V(ACCESS_CHECK_INFO, AccessCheckInfo, access_check_info) \
V(INTERCEPTOR_INFO, InterceptorInfo, interceptor_info) \
@@ -398,10 +398,19 @@ enum PropertyNormalizationMode {
V(OBJECT_TEMPLATE_INFO, ObjectTemplateInfo, object_template_info) \
V(SIGNATURE_INFO, SignatureInfo, signature_info) \
V(TYPE_SWITCH_INFO, TypeSwitchInfo, type_switch_info) \
- V(DEBUG_INFO, DebugInfo, debug_info) \
- V(BREAK_POINT_INFO, BreakPointInfo, break_point_info) \
V(SCRIPT, Script, script)
+#ifdef ENABLE_DEBUGGER_SUPPORT
+#define STRUCT_LIST_DEBUGGER(V) \
+ V(DEBUG_INFO, DebugInfo, debug_info) \
+ V(BREAK_POINT_INFO, BreakPointInfo, break_point_info)
+#else
+#define STRUCT_LIST_DEBUGGER(V)
+#endif
+
+#define STRUCT_LIST(V) \
+ STRUCT_LIST_ALL(V) \
+ STRUCT_LIST_DEBUGGER(V)
// We use the full 8 bits of the instance_type field to encode heap object
// instance types. The high-order bit (bit 7) is set if the object is not a
@@ -773,9 +782,13 @@ class Smi: public Object {
// Convert a value to a Smi object.
static inline Smi* FromInt(int value);
+ static inline Smi* FromIntptr(intptr_t value);
+
// Returns whether value can be represented in a Smi.
static inline bool IsValid(int value);
+ static inline bool IsIntptrValid(intptr_t);
+
// Casting.
static inline Smi* cast(Object* object);
@@ -786,9 +799,10 @@ class Smi: public Object {
void SmiVerify();
#endif
+ static const int kSmiNumBits = 31;
// Min and max limits for Smi values.
- static const int kMinValue = -(1 << (kBitsPerPointer - (kSmiTagSize + 1)));
- static const int kMaxValue = (1 << (kBitsPerPointer - (kSmiTagSize + 1))) - 1;
+ static const int kMinValue = -(1 << (kSmiNumBits - 1));
+ static const int kMaxValue = (1 << (kSmiNumBits - 1)) - 1;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Smi);
@@ -1169,6 +1183,14 @@ class JSObject: public HeapObject {
inline bool HasFastElements();
inline Dictionary* element_dictionary(); // Gets slow elements.
+ // Collects elements starting at index 0.
+ // Undefined values are placed after non-undefined values.
+ // Returns the number of non-undefined values.
+ Object* PrepareElementsForSort(uint32_t limit);
+ // As PrepareElementsForSort, but only on objects where elements is
+ // a dictionary, and it will stay a dictionary.
+ Object* PrepareSlowElementsForSort(uint32_t limit);
+
Object* SetProperty(String* key,
Object* value,
PropertyAttributes attributes);
@@ -1233,10 +1255,14 @@ class JSObject: public HeapObject {
String* name,
PropertyAttributes* attributes);
+ // Tells whether this object needs to be loaded.
+ inline bool IsLoaded();
+
bool HasProperty(String* name) {
return GetPropertyAttribute(name) != ABSENT;
}
+ // Can cause a GC if it hits an interceptor.
bool HasLocalProperty(String* name) {
return GetLocalPropertyAttribute(name) != ABSENT;
}
@@ -1585,11 +1611,15 @@ class FixedArray: public Array {
bool IsEqualTo(FixedArray* other);
#endif
- // Swap two elements.
- void Swap(int i, int j);
+ // Swap two elements in a pair of arrays. If this array and the
+ // numbers array are the same object, the elements are only swapped
+ // once.
+ void SwapPairs(FixedArray* numbers, int i, int j);
- // Sort this array and the smis as pairs wrt. the smis.
- void SortPairs(FixedArray* smis);
+ // Sort prefix of this array and the numbers array as pairs wrt. the
+ // numbers. If the numbers array and the this array are the same
+ // object, the prefix of this array is sorted.
+ void SortPairs(FixedArray* numbers, uint32_t len);
protected:
// Set operation on FixedArray without using write barriers.
@@ -1992,7 +2022,6 @@ class Dictionary: public DictionaryBase {
void RemoveNumberEntries(uint32_t from, uint32_t to);
// Sorting support
- Object* RemoveHoles();
void CopyValuesTo(FixedArray* elements);
// Casting.
@@ -2301,8 +2330,7 @@ class Code: public HeapObject {
// the layout of the code object into account.
int ExecutableSize() {
// Check that the assumptions about the layout of the code object holds.
- ASSERT_EQ(reinterpret_cast<unsigned int>(instruction_start()) -
- reinterpret_cast<unsigned int>(address()),
+ ASSERT_EQ(instruction_start() - address(),
Code::kHeaderSize);
return instruction_size() + Code::kHeaderSize;
}
@@ -2384,6 +2412,10 @@ class Map: public HeapObject {
inline byte bit_field();
inline void set_bit_field(byte value);
+ // Bit field 2.
+ inline byte bit_field2();
+ inline void set_bit_field2(byte value);
+
// Tells whether the object in the prototype property will be used
// for instances created from this function. If the prototype
// property is set to a value that is not a JSObject, the prototype
@@ -2434,6 +2466,20 @@ class Map: public HeapObject {
return ((1 << kIsUndetectable) & bit_field()) != 0;
}
+ inline void set_needs_loading(bool value) {
+ if (value) {
+ set_bit_field2(bit_field2() | (1 << kNeedsLoading));
+ } else {
+ set_bit_field2(bit_field2() & ~(1 << kNeedsLoading));
+ }
+ }
+
+ // Does this object or function require a lazily loaded script to be
+ // run before being used?
+ inline bool needs_loading() {
+ return ((1 << kNeedsLoading) & bit_field2()) != 0;
+ }
+
// Tells whether the instance has a call-as-function handler.
inline void set_has_instance_call_handler() {
set_bit_field(bit_field() | (1 << kHasInstanceCallHandler));
@@ -2461,7 +2507,7 @@ class Map: public HeapObject {
DECL_ACCESSORS(code_cache, FixedArray)
// Returns a copy of the map.
- Object* Copy();
+ Object* CopyDropDescriptors();
// Returns a copy of the map, with all transitions dropped from the
// instance descriptors.
@@ -2537,7 +2583,7 @@ class Map: public HeapObject {
static const int kInstanceTypeOffset = kInstanceAttributesOffset + 0;
static const int kUnusedPropertyFieldsOffset = kInstanceAttributesOffset + 1;
static const int kBitFieldOffset = kInstanceAttributesOffset + 2;
- // The byte at position 3 is not in use at the moment.
+ static const int kBitField2Offset = kInstanceAttributesOffset + 3;
// Bit positions for bit field.
static const int kUnused = 0; // To be used for marking recently used maps.
@@ -2548,6 +2594,10 @@ class Map: public HeapObject {
static const int kIsUndetectable = 5;
static const int kHasInstanceCallHandler = 6;
static const int kIsAccessCheckNeeded = 7;
+
+ // Bit positions for but field 2
+ static const int kNeedsLoading = 0;
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Map);
};
@@ -2590,6 +2640,12 @@ class Script: public Struct {
// extracted.
DECL_ACCESSORS(column_offset, Smi)
+ // [data]: additional data associated with this script.
+ DECL_ACCESSORS(data, Object)
+
+ // [context_data]: context data for the context this script was compiled in.
+ DECL_ACCESSORS(context_data, Object)
+
// [wrapper]: the wrapper cache.
DECL_ACCESSORS(wrapper, Proxy)
@@ -2610,7 +2666,9 @@ class Script: public Struct {
static const int kNameOffset = kSourceOffset + kPointerSize;
static const int kLineOffsetOffset = kNameOffset + kPointerSize;
static const int kColumnOffsetOffset = kLineOffsetOffset + kPointerSize;
- static const int kWrapperOffset = kColumnOffsetOffset + kPointerSize;
+ static const int kDataOffset = kColumnOffsetOffset + kPointerSize;
+ static const int kContextOffset = kDataOffset + kPointerSize;
+ static const int kWrapperOffset = kContextOffset + kPointerSize;
static const int kTypeOffset = kWrapperOffset + kPointerSize;
static const int kLineEndsOffset = kTypeOffset + kPointerSize;
static const int kIdOffset = kLineEndsOffset + kPointerSize;
@@ -2660,10 +2718,6 @@ class SharedFunctionInfo: public HeapObject {
// on objects.
DECL_ACCESSORS(function_data, Object)
- // [lazy load data]: If the function has lazy loading, this field
- // contains contexts and other data needed to load it.
- DECL_ACCESSORS(lazy_load_data, Object)
-
// [script info]: Script from which the function originates.
DECL_ACCESSORS(script, Object)
@@ -2737,9 +2791,7 @@ class SharedFunctionInfo: public HeapObject {
kExpectedNofPropertiesOffset + kIntSize;
static const int kExternalReferenceDataOffset =
kInstanceClassNameOffset + kPointerSize;
- static const int kLazyLoadDataOffset =
- kExternalReferenceDataOffset + kPointerSize;
- static const int kScriptOffset = kLazyLoadDataOffset + kPointerSize;
+ static const int kScriptOffset = kExternalReferenceDataOffset + kPointerSize;
static const int kStartPositionAndTypeOffset = kScriptOffset + kPointerSize;
static const int kEndPositionOffset = kStartPositionAndTypeOffset + kIntSize;
static const int kFunctionTokenPositionOffset = kEndPositionOffset + kIntSize;
@@ -2792,9 +2844,6 @@ class JSFunction: public JSObject {
// function.
inline bool IsBoilerplate();
- // Tells whether this function needs to be loaded.
- inline bool IsLoaded();
-
// [literals]: Fixed array holding the materialized literals.
//
// If the function contains object, regexp or array literals, the
@@ -3167,8 +3216,6 @@ class StringShape BASE_EMBEDDED {
inline explicit StringShape(String* s);
inline explicit StringShape(Map* s);
inline explicit StringShape(InstanceType t);
- inline bool IsAsciiRepresentation();
- inline bool IsTwoByteRepresentation();
inline bool IsSequential();
inline bool IsExternal();
inline bool IsCons();
@@ -3220,6 +3267,9 @@ class String: public HeapObject {
inline uint32_t length_field();
inline void set_length_field(uint32_t value);
+ inline bool IsAsciiRepresentation();
+ inline bool IsTwoByteRepresentation();
+
// Get and set individual two byte chars in the string.
inline void Set(int index, uint16_t value);
// Get individual two byte char in the string. Repeated calls
@@ -3859,9 +3909,6 @@ class JSArray: public JSObject {
// Set the content of the array to the content of storage.
inline void SetContent(FixedArray* storage);
- // Support for sorting
- Object* RemoveHoles();
-
// Casting.
static inline JSArray* cast(Object* obj);
@@ -4147,6 +4194,7 @@ class TypeSwitchInfo: public Struct {
};
+#ifdef ENABLE_DEBUGGER_SUPPORT
// The DebugInfo class holds additional information for a function being
// debugged.
class DebugInfo: public Struct {
@@ -4252,6 +4300,7 @@ class BreakPointInfo: public Struct {
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(BreakPointInfo);
};
+#endif // ENABLE_DEBUGGER_SUPPORT
#undef DECL_BOOLEAN_ACCESSORS
diff --git a/deps/v8/src/platform-freebsd.cc b/deps/v8/src/platform-freebsd.cc
index 92099907b..82208f1a3 100644
--- a/deps/v8/src/platform-freebsd.cc
+++ b/deps/v8/src/platform-freebsd.cc
@@ -171,7 +171,7 @@ void OS::Abort() {
void OS::DebugBreak() {
-#if defined (__arm__) || defined(__thumb__)
+#if defined(__arm__) || defined(__thumb__)
asm("bkpt 0");
#else
asm("int $3");
@@ -262,7 +262,8 @@ void OS::LogSharedLibraryAddresses() {
}
-int OS::StackWalk(OS::StackFrame* frames, int frames_size) {
+int OS::StackWalk(Vector<OS::StackFrame> frames) {
+ int frames_size = frames.length();
void** addresses = NewArray<void*>(frames_size);
int frames_count = backtrace(addresses, frames_size);
@@ -502,27 +503,24 @@ void FreeBSDSemaphore::Wait() {
bool FreeBSDSemaphore::Wait(int timeout) {
const long kOneSecondMicros = 1000000; // NOLINT
- const long kOneSecondNanos = 1000000000; // NOLINT
// Split timeout into second and nanosecond parts.
- long nanos = (timeout % kOneSecondMicros) * 1000; // NOLINT
- time_t secs = timeout / kOneSecondMicros;
+ struct timeval delta;
+ delta.tv_usec = timeout % kOneSecondMicros;
+ delta.tv_sec = timeout / kOneSecondMicros;
- // Get the current real time clock.
- struct timespec ts;
- if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
+ struct timeval current_time;
+ // Get the current time.
+ if (gettimeofday(&current_time, NULL) == -1) {
return false;
}
- // Calculate realtime for end of timeout.
- ts.tv_nsec += nanos;
- if (ts.tv_nsec >= kOneSecondNanos) {
- ts.tv_nsec -= kOneSecondNanos;
- ts.tv_nsec++;
- }
- ts.tv_sec += secs;
+ // Calculate time for end of timeout.
+ struct timeval end_time;
+ timeradd(&current_time, &delta, &end_time);
- // Wait for semaphore signalled or timeout.
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC(&end_time, &ts);
while (true) {
int result = sem_timedwait(&sem_, &ts);
if (result == 0) return true; // Successfully got semaphore.
diff --git a/deps/v8/src/platform-linux.cc b/deps/v8/src/platform-linux.cc
index f9a5deacb..c02eebc3b 100644
--- a/deps/v8/src/platform-linux.cc
+++ b/deps/v8/src/platform-linux.cc
@@ -171,6 +171,8 @@ void OS::Abort() {
void OS::DebugBreak() {
+// TODO(lrn): Introduce processor define for runtime system (!= V8_ARCH_x,
+// which is the architecture of generated code).
#if defined(__arm__) || defined(__thumb__)
asm("bkpt 0");
#else
@@ -262,9 +264,10 @@ void OS::LogSharedLibraryAddresses() {
}
-int OS::StackWalk(OS::StackFrame* frames, int frames_size) {
+int OS::StackWalk(Vector<OS::StackFrame> frames) {
// backtrace is a glibc extension.
#ifdef __GLIBC__
+ int frames_size = frames.length();
void** addresses = NewArray<void*>(frames_size);
int frames_count = backtrace(addresses, frames_size);
@@ -506,28 +509,34 @@ void LinuxSemaphore::Wait() {
}
+#ifndef TIMEVAL_TO_TIMESPEC
+#define TIMEVAL_TO_TIMESPEC(tv, ts) do { \
+ (ts)->tv_sec = (tv)->tv_sec; \
+ (ts)->tv_nsec = (tv)->tv_usec * 1000; \
+} while (false)
+#endif
+
+
bool LinuxSemaphore::Wait(int timeout) {
const long kOneSecondMicros = 1000000; // NOLINT
- const long kOneSecondNanos = 1000000000; // NOLINT
// Split timeout into second and nanosecond parts.
- long nanos = (timeout % kOneSecondMicros) * 1000; // NOLINT
- time_t secs = timeout / kOneSecondMicros;
+ struct timeval delta;
+ delta.tv_usec = timeout % kOneSecondMicros;
+ delta.tv_sec = timeout / kOneSecondMicros;
- // Get the current realtime clock.
- struct timespec ts;
- if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
+ struct timeval current_time;
+ // Get the current time.
+ if (gettimeofday(&current_time, NULL) == -1) {
return false;
}
- // Calculate real time for end of timeout.
- ts.tv_nsec += nanos;
- if (ts.tv_nsec >= kOneSecondNanos) {
- ts.tv_nsec -= kOneSecondNanos;
- ts.tv_nsec++;
- }
- ts.tv_sec += secs;
+ // Calculate time for end of timeout.
+ struct timeval end_time;
+ timeradd(&current_time, &delta, &end_time);
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC(&end_time, &ts);
// Wait for semaphore signalled or timeout.
while (true) {
int result = sem_timedwait(&sem_, &ts);
@@ -591,14 +600,18 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
// Extracting the sample from the context is extremely machine dependent.
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
mcontext_t& mcontext = ucontext->uc_mcontext;
-#if defined (__arm__) || defined(__thumb__)
- sample.pc = mcontext.gregs[R15];
- sample.sp = mcontext.gregs[R13];
- sample.fp = mcontext.gregs[R11];
-#else
+#if V8_HOST_ARCH_IA32
sample.pc = mcontext.gregs[REG_EIP];
sample.sp = mcontext.gregs[REG_ESP];
sample.fp = mcontext.gregs[REG_EBP];
+#elif V8_HOST_ARCH_X64
+ sample.pc = mcontext.gregs[REG_RIP];
+ sample.sp = mcontext.gregs[REG_RSP];
+ sample.fp = mcontext.gregs[REG_RBP];
+#elif V8_HOST_ARCH_ARM
+ sample.pc = mcontext.gregs[R15];
+ sample.sp = mcontext.gregs[R13];
+ sample.fp = mcontext.gregs[R11];
#endif
}
diff --git a/deps/v8/src/platform-macos.cc b/deps/v8/src/platform-macos.cc
index b13122fae..79515434e 100644
--- a/deps/v8/src/platform-macos.cc
+++ b/deps/v8/src/platform-macos.cc
@@ -212,10 +212,11 @@ int OS::ActivationFrameAlignment() {
}
-int OS::StackWalk(StackFrame* frames, int frames_size) {
+int OS::StackWalk(Vector<StackFrame> frames) {
#ifndef MAC_OS_X_VERSION_10_5
return 0;
#else
+ int frames_size = frames.length();
void** addresses = NewArray<void*>(frames_size);
int frames_count = backtrace(addresses, frames_size);
diff --git a/deps/v8/src/platform-nullos.cc b/deps/v8/src/platform-nullos.cc
index 3a50b9ddd..42583f17f 100644
--- a/deps/v8/src/platform-nullos.cc
+++ b/deps/v8/src/platform-nullos.cc
@@ -215,7 +215,7 @@ void OS::LogSharedLibraryAddresses() {
}
-int OS::StackWalk(OS::StackFrame* frames, int frames_size) {
+int OS::StackWalk(Vector<OS::StackFrame> frames) {
UNIMPLEMENTED();
return 0;
}
diff --git a/deps/v8/src/platform-win32.cc b/deps/v8/src/platform-win32.cc
index 717787022..6c4e67a7f 100644
--- a/deps/v8/src/platform-win32.cc
+++ b/deps/v8/src/platform-win32.cc
@@ -1161,7 +1161,7 @@ void OS::LogSharedLibraryAddresses() {
// it is triggered by the use of inline assembler.
#pragma warning(push)
#pragma warning(disable : 4748)
-int OS::StackWalk(OS::StackFrame* frames, int frames_size) {
+int OS::StackWalk(Vector<OS::StackFrame> frames) {
BOOL ok;
// Load the required functions from DLL's.
@@ -1201,6 +1201,7 @@ int OS::StackWalk(OS::StackFrame* frames, int frames_size) {
int frames_count = 0;
// Collect stack frames.
+ int frames_size = frames.length();
while (frames_count < frames_size) {
ok = _StackWalk64(
IMAGE_FILE_MACHINE_I386, // MachineType
@@ -1284,7 +1285,7 @@ int OS::StackWalk(OS::StackFrame* frames, int frames_size) {
#else // __MINGW32__
void OS::LogSharedLibraryAddresses() { }
-int OS::StackWalk(OS::StackFrame* frames, int frames_size) { return 0; }
+int OS::StackWalk(Vector<OS::StackFrame> frames) { return 0; }
#endif // __MINGW32__
@@ -1774,9 +1775,16 @@ class Sampler::PlatformData : public Malloced {
context.ContextFlags = CONTEXT_FULL;
GetThreadContext(profiled_thread_, &context);
// Invoke tick handler with program counter and stack pointer.
+#if V8_HOST_ARCH_X64
+ UNIMPLEMENTED();
+ sample.pc = context.Rip;
+ sample.sp = context.Rsp;
+ sample.fp = context.Rbp;
+#else
sample.pc = context.Eip;
sample.sp = context.Esp;
sample.fp = context.Ebp;
+#endif
}
// We always sample the VM state.
diff --git a/deps/v8/src/platform.h b/deps/v8/src/platform.h
index db4f2fdab..e23abfc37 100644
--- a/deps/v8/src/platform.h
+++ b/deps/v8/src/platform.h
@@ -207,7 +207,7 @@ class OS {
char text[kStackWalkMaxTextLen];
};
- static int StackWalk(StackFrame* frames, int frames_size);
+ static int StackWalk(Vector<StackFrame> frames);
// Factory method for creating platform dependent Mutex.
// Please use delete to reclaim the storage for the returned Mutex.
@@ -350,7 +350,16 @@ class Thread: public ThreadHandle {
static LocalStorageKey CreateThreadLocalKey();
static void DeleteThreadLocalKey(LocalStorageKey key);
static void* GetThreadLocal(LocalStorageKey key);
+ static int GetThreadLocalInt(LocalStorageKey key) {
+ return static_cast<int>(reinterpret_cast<intptr_t>(GetThreadLocal(key)));
+ }
static void SetThreadLocal(LocalStorageKey key, void* value);
+ static void SetThreadLocalInt(LocalStorageKey key, int value) {
+ SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
+ }
+ static bool HasThreadLocal(LocalStorageKey key) {
+ return GetThreadLocal(key) != NULL;
+ }
// A hint to the scheduler to let another thread run.
static void YieldCPU();
@@ -483,9 +492,9 @@ class Socket {
class TickSample {
public:
TickSample() : pc(0), sp(0), fp(0), state(OTHER) {}
- unsigned int pc; // Instruction pointer.
- unsigned int sp; // Stack pointer.
- unsigned int fp; // Frame pointer.
+ uintptr_t pc; // Instruction pointer.
+ uintptr_t sp; // Stack pointer.
+ uintptr_t fp; // Frame pointer.
StateTag state; // The state of the VM.
static const int kMaxFramesCount = 100;
EmbeddedVector<Address, kMaxFramesCount> stack; // Call stack.
diff --git a/deps/v8/src/property.h b/deps/v8/src/property.h
index 65d4a0d6d..60a9b544d 100644
--- a/deps/v8/src/property.h
+++ b/deps/v8/src/property.h
@@ -245,14 +245,25 @@ class LookupResult BASE_EMBEDDED {
// Tells whether the value needs to be loaded.
bool IsLoaded() {
if (lookup_type_ == DESCRIPTOR_TYPE || lookup_type_ == DICTIONARY_TYPE) {
- Object* value = GetValue();
- if (value->IsJSFunction()) {
- return JSFunction::cast(value)->IsLoaded();
- }
+ Object* target = GetLazyValue();
+ return !target->IsJSObject() || JSObject::cast(target)->IsLoaded();
}
return true;
}
+ Object* GetLazyValue() {
+ switch (type()) {
+ case FIELD:
+ return holder()->FastPropertyAt(GetFieldIndex());
+ case NORMAL:
+ return holder()->property_dictionary()->ValueAt(GetDictionaryEntry());
+ case CONSTANT_FUNCTION:
+ return GetConstantFunction();
+ default:
+ return Smi::FromInt(0);
+ }
+ }
+
Map* GetTransitionMap() {
ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
ASSERT(type() == MAP_TRANSITION);
diff --git a/deps/v8/src/regexp-macro-assembler-irregexp-inl.h b/deps/v8/src/regexp-macro-assembler-irregexp-inl.h
index 378529108..fa4c3d16b 100644
--- a/deps/v8/src/regexp-macro-assembler-irregexp-inl.h
+++ b/deps/v8/src/regexp-macro-assembler-irregexp-inl.h
@@ -32,6 +32,8 @@
#include "ast.h"
#include "bytecodes-irregexp.h"
+#ifndef V8_REGEXP_MACRO_ASSEMBLER_IRREGEXP_INL_H_
+#define V8_REGEXP_MACRO_ASSEMBLER_IRREGEXP_INL_H_
namespace v8 { namespace internal {
@@ -69,3 +71,5 @@ void RegExpMacroAssemblerIrregexp::Emit32(uint32_t word) {
} } // namespace v8::internal
+
+#endif // V8_REGEXP_MACRO_ASSEMBLER_IRREGEXP_INL_H_
diff --git a/deps/v8/src/regexp-macro-assembler-tracer.h b/deps/v8/src/regexp-macro-assembler-tracer.h
index d3aeff73a..f25289e6e 100644
--- a/deps/v8/src/regexp-macro-assembler-tracer.h
+++ b/deps/v8/src/regexp-macro-assembler-tracer.h
@@ -25,8 +25,8 @@
// (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 REGEXP_MACRO_ASSEMBLER_TRACER_H_
-#define REGEXP_MACRO_ASSEMBLER_TRACER_H_
+#ifndef V8_REGEXP_MACRO_ASSEMBLER_TRACER_H_
+#define V8_REGEXP_MACRO_ASSEMBLER_TRACER_H_
namespace v8 { namespace internal {
@@ -115,4 +115,4 @@ class RegExpMacroAssemblerTracer: public RegExpMacroAssembler {
}} // namespace v8::internal
-#endif // REGEXP_MACRO_ASSEMBLER_TRACER_H_
+#endif // V8_REGEXP_MACRO_ASSEMBLER_TRACER_H_
diff --git a/deps/v8/src/regexp-stack.h b/deps/v8/src/regexp-stack.h
index e47462ffd..b955e76a0 100644
--- a/deps/v8/src/regexp-stack.h
+++ b/deps/v8/src/regexp-stack.h
@@ -25,8 +25,8 @@
// (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 REGEXP_STACK_H_
-#define REGEXP_STACK_H_
+#ifndef V8_REGEXP_STACK_H_
+#define V8_REGEXP_STACK_H_
namespace v8 { namespace internal {
@@ -103,4 +103,4 @@ class RegExpStack {
}} // namespace v8::internal
-#endif /* REGEXP_STACK_H_ */
+#endif // V8_REGEXP_STACK_H_
diff --git a/deps/v8/src/register-allocator.h b/deps/v8/src/register-allocator.h
index dcc2eb7ee..f79d6cfdf 100644
--- a/deps/v8/src/register-allocator.h
+++ b/deps/v8/src/register-allocator.h
@@ -275,6 +275,11 @@ class RegisterAllocator BASE_EMBEDDED {
// Unuse all the reserved registers in a register file.
static void UnuseReserved(RegisterFile* register_file);
+ // True if the register is reserved by the code generator, false if it
+ // can be freely used by the allocator.
+ static bool IsReserved(int reg_code);
+ static bool IsReserved(Register reg) { return IsReserved(reg); }
+
// Predicates and accessors for the registers' reference counts.
bool is_used(int reg_code) const { return registers_.is_used(reg_code); }
bool is_used(Register reg) const { return registers_.is_used(reg.code()); }
diff --git a/deps/v8/src/rewriter.cc b/deps/v8/src/rewriter.cc
index 6641f2615..4e3676b7d 100644
--- a/deps/v8/src/rewriter.cc
+++ b/deps/v8/src/rewriter.cc
@@ -194,7 +194,7 @@ void AstOptimizer::VisitFunctionLiteral(FunctionLiteral* node) {
if (node->name()->length() == 0) {
// Anonymous function.
- func_name_inferrer_.SetFuncToInfer(node);
+ func_name_inferrer_.AddFunction(node);
}
}
@@ -282,10 +282,7 @@ void AstOptimizer::VisitAssignment(Assignment* node) {
case Token::ASSIGN:
// No type can be infered from the general assignment.
- if (node->value()->AsFunctionLiteral() != NULL ||
- node->value()->AsObjectLiteral() != NULL) {
- scoped_fni.Enter();
- }
+ scoped_fni.Enter();
break;
case Token::ASSIGN_BIT_OR:
case Token::ASSIGN_BIT_XOR:
diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc
index ab25c9ec3..bf6286fe3 100644
--- a/deps/v8/src/runtime.cc
+++ b/deps/v8/src/runtime.cc
@@ -474,6 +474,42 @@ static Object* Runtime_IsInPrototypeChain(Arguments args) {
}
+// Inserts an object as the hidden prototype of another object.
+static Object* Runtime_SetHiddenPrototype(Arguments args) {
+ NoHandleAllocation ha;
+ ASSERT(args.length() == 2);
+ CONVERT_CHECKED(JSObject, jsobject, args[0]);
+ CONVERT_CHECKED(JSObject, proto, args[1]);
+
+ // Sanity checks. The old prototype (that we are replacing) could
+ // theoretically be null, but if it is not null then check that we
+ // didn't already install a hidden prototype here.
+ RUNTIME_ASSERT(!jsobject->GetPrototype()->IsHeapObject() ||
+ !HeapObject::cast(jsobject->GetPrototype())->map()->is_hidden_prototype());
+ RUNTIME_ASSERT(!proto->map()->is_hidden_prototype());
+
+ // Allocate up front before we start altering state in case we get a GC.
+ Object* map_or_failure = proto->map()->CopyDropTransitions();
+ if (map_or_failure->IsFailure()) return map_or_failure;
+ Map* new_proto_map = Map::cast(map_or_failure);
+
+ map_or_failure = jsobject->map()->CopyDropTransitions();
+ if (map_or_failure->IsFailure()) return map_or_failure;
+ Map* new_map = Map::cast(map_or_failure);
+
+ // Set proto's prototype to be the old prototype of the object.
+ new_proto_map->set_prototype(jsobject->GetPrototype());
+ proto->set_map(new_proto_map);
+ new_proto_map->set_is_hidden_prototype();
+
+ // Set the object's prototype to proto.
+ new_map->set_prototype(proto);
+ jsobject->set_map(new_map);
+
+ return Heap::undefined_value();
+}
+
+
static Object* Runtime_IsConstructCall(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 0);
@@ -1282,7 +1318,7 @@ class ReplacementStringBuilder {
parts_(Factory::NewFixedArray(estimated_part_count)),
part_count_(0),
character_count_(0),
- is_ascii_(StringShape(*subject).IsAsciiRepresentation()) {
+ is_ascii_(subject->IsAsciiRepresentation()) {
// Require a non-zero initial size. Ensures that doubling the size to
// extend the array will work.
ASSERT(estimated_part_count > 0);
@@ -1326,7 +1362,7 @@ class ReplacementStringBuilder {
int length = string->length();
ASSERT(length > 0);
AddElement(*string);
- if (!StringShape(*string).IsAsciiRepresentation()) {
+ if (!string->IsAsciiRepresentation()) {
is_ascii_ = false;
}
IncrementCharacterCount(length);
@@ -1583,14 +1619,14 @@ void CompiledReplacement::Compile(Handle<String> replacement,
int capture_count,
int subject_length) {
ASSERT(replacement->IsFlat());
- if (StringShape(*replacement).IsAsciiRepresentation()) {
+ if (replacement->IsAsciiRepresentation()) {
AssertNoAllocation no_alloc;
ParseReplacementPattern(&parts_,
replacement->ToAsciiVector(),
capture_count,
subject_length);
} else {
- ASSERT(StringShape(*replacement).IsTwoByteRepresentation());
+ ASSERT(replacement->IsTwoByteRepresentation());
AssertNoAllocation no_alloc;
ParseReplacementPattern(&parts_,
@@ -2165,7 +2201,7 @@ int Runtime::StringMatch(Handle<String> sub,
// algorithm is unnecessary overhead.
if (pattern_length == 1) {
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
- if (StringShape(*sub).IsAsciiRepresentation()) {
+ if (sub->IsAsciiRepresentation()) {
uc16 pchar = pat->Get(0);
if (pchar > String::kMaxAsciiCharCode) {
return -1;
@@ -2190,15 +2226,15 @@ int Runtime::StringMatch(Handle<String> sub,
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
// dispatch on type of strings
- if (StringShape(*pat).IsAsciiRepresentation()) {
+ if (pat->IsAsciiRepresentation()) {
Vector<const char> pat_vector = pat->ToAsciiVector();
- if (StringShape(*sub).IsAsciiRepresentation()) {
+ if (sub->IsAsciiRepresentation()) {
return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
}
return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
}
Vector<const uc16> pat_vector = pat->ToUC16Vector();
- if (StringShape(*sub).IsAsciiRepresentation()) {
+ if (sub->IsAsciiRepresentation()) {
return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
}
return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
@@ -2688,6 +2724,59 @@ Object* Runtime::SetObjectProperty(Handle<Object> object,
}
+Object* Runtime::ForceSetObjectProperty(Handle<JSObject> js_object,
+ Handle<Object> key,
+ Handle<Object> value,
+ PropertyAttributes attr) {
+ HandleScope scope;
+
+ // Check if the given key is an array index.
+ uint32_t index;
+ if (Array::IndexFromObject(*key, &index)) {
+ ASSERT(attr == NONE);
+
+ // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
+ // of a string using [] notation. We need to support this too in
+ // JavaScript.
+ // In the case of a String object we just need to redirect the assignment to
+ // the underlying string if the index is in range. Since the underlying
+ // string does nothing with the assignment then we can ignore such
+ // assignments.
+ if (js_object->IsStringObjectWithCharacterAt(index)) {
+ return *value;
+ }
+
+ return js_object->SetElement(index, *value);
+ }
+
+ if (key->IsString()) {
+ if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
+ ASSERT(attr == NONE);
+ return js_object->SetElement(index, *value);
+ } else {
+ Handle<String> key_string = Handle<String>::cast(key);
+ key_string->TryFlattenIfNotFlat();
+ return js_object->IgnoreAttributesAndSetLocalProperty(*key_string,
+ *value,
+ attr);
+ }
+ }
+
+ // Call-back into JavaScript to convert the key to a string.
+ bool has_pending_exception = false;
+ Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
+ if (has_pending_exception) return Failure::Exception();
+ Handle<String> name = Handle<String>::cast(converted);
+
+ if (name->AsArrayIndex(&index)) {
+ ASSERT(attr == NONE);
+ return js_object->SetElement(index, *value);
+ } else {
+ return js_object->IgnoreAttributesAndSetLocalProperty(*name, *value, attr);
+ }
+}
+
+
static Object* Runtime_SetProperty(Arguments args) {
NoHandleAllocation ha;
RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
@@ -2743,20 +2832,42 @@ static Object* Runtime_DeleteProperty(Arguments args) {
}
+static Object* HasLocalPropertyImplementation(Handle<JSObject> object,
+ Handle<String> key) {
+ if (object->HasLocalProperty(*key)) return Heap::true_value();
+ // Handle hidden prototypes. If there's a hidden prototype above this thing
+ // then we have to check it for properties, because they are supposed to
+ // look like they are on this object.
+ Handle<Object> proto(object->GetPrototype());
+ if (proto->IsJSObject() &&
+ Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) {
+ return HasLocalPropertyImplementation(Handle<JSObject>::cast(proto), key);
+ }
+ return Heap::false_value();
+}
+
+
static Object* Runtime_HasLocalProperty(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
CONVERT_CHECKED(String, key, args[1]);
+ Object* obj = args[0];
// Only JS objects can have properties.
- if (args[0]->IsJSObject()) {
- JSObject* object = JSObject::cast(args[0]);
- if (object->HasLocalProperty(key)) return Heap::true_value();
- } else if (args[0]->IsString()) {
+ if (obj->IsJSObject()) {
+ JSObject* object = JSObject::cast(obj);
+ // Fast case - no interceptors.
+ if (object->HasRealNamedProperty(key)) return Heap::true_value();
+ // Slow case. Either it's not there or we have an interceptor. We should
+ // have handles for this kind of deal.
+ HandleScope scope;
+ return HasLocalPropertyImplementation(Handle<JSObject>(object),
+ Handle<String>(key));
+ } else if (obj->IsString()) {
// Well, there is one exception: Handle [] on strings.
uint32_t index;
if (key->AsArrayIndex(&index)) {
- String* string = String::cast(args[0]);
+ String* string = String::cast(obj);
if (index < static_cast<uint32_t>(string->length()))
return Heap::true_value();
}
@@ -3276,7 +3387,7 @@ static Object* ConvertCaseHelper(String* s,
// character is also ascii. This is currently the case, but it
// might break in the future if we implement more context and locale
// dependent upper/lower conversions.
- Object* o = StringShape(s).IsAsciiRepresentation()
+ Object* o = s->IsAsciiRepresentation()
? Heap::AllocateRawAsciiString(length)
: Heap::AllocateRawTwoByteString(length);
if (o->IsFailure()) return o;
@@ -3482,6 +3593,7 @@ static Object* Runtime_NumberToSmi(Arguments args) {
return Heap::nan_value();
}
+
static Object* Runtime_NumberAdd(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
@@ -3626,7 +3738,7 @@ static Object* Runtime_StringBuilderConcat(Arguments args) {
if (first->IsString()) return first;
}
- bool ascii = StringShape(special).IsAsciiRepresentation();
+ bool ascii = special->IsAsciiRepresentation();
int position = 0;
for (int i = 0; i < array_length; i++) {
Object* elt = fixed_array->get(i);
@@ -3646,7 +3758,7 @@ static Object* Runtime_StringBuilderConcat(Arguments args) {
return Failure::OutOfMemoryException();
}
position += element_length;
- if (ascii && !StringShape(element).IsAsciiRepresentation()) {
+ if (ascii && !element->IsAsciiRepresentation()) {
ascii = false;
}
} else {
@@ -4158,10 +4270,12 @@ static Object* Runtime_NewObject(Arguments args) {
JSFunction* function = JSFunction::cast(constructor);
// Handle stepping into constructors if step into is active.
+#ifdef ENABLE_DEBUGGER_SUPPORT
if (Debug::StepInActive()) {
HandleScope scope;
Debug::HandleStepIn(Handle<JSFunction>(function), 0, true);
}
+#endif
if (function->has_initial_map() &&
function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
@@ -4525,12 +4639,6 @@ static Object* Runtime_StackOverflow(Arguments args) {
}
-static Object* Runtime_DebugBreak(Arguments args) {
- ASSERT(args.length() == 0);
- return Execution::DebugBreakHelper();
-}
-
-
static Object* Runtime_StackGuard(Arguments args) {
ASSERT(args.length() == 1);
@@ -4707,10 +4815,10 @@ static Object* Runtime_DateParseString(Arguments args) {
FixedArray* output_array = output->elements();
RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
bool result;
- if (StringShape(*str).IsAsciiRepresentation()) {
+ if (str->IsAsciiRepresentation()) {
result = DateParser::Parse(str->ToAsciiVector(), output_array);
} else {
- ASSERT(StringShape(*str).IsTwoByteRepresentation());
+ ASSERT(str->IsTwoByteRepresentation());
result = DateParser::Parse(str->ToUC16Vector(), output_array);
}
@@ -4774,14 +4882,18 @@ static Object* Runtime_GlobalReceiver(Arguments args) {
static Object* Runtime_CompileString(Arguments args) {
HandleScope scope;
- ASSERT(args.length() == 2);
+ ASSERT_EQ(3, args.length());
CONVERT_ARG_CHECKED(String, source, 0);
CONVERT_ARG_CHECKED(Smi, line_offset, 1);
+ CONVERT_ARG_CHECKED(Oddball, is_json, 2)
// Compile source string in the global context.
Handle<Context> context(Top::context()->global_context());
- Handle<JSFunction> boilerplate =
- Compiler::CompileEval(source, context, line_offset->value(), true);
+ Handle<JSFunction> boilerplate = Compiler::CompileEval(source,
+ context,
+ line_offset->value(),
+ true,
+ is_json->IsTrue());
if (boilerplate.is_null()) return Failure::Exception();
Handle<JSFunction> fun =
Factory::NewFunctionFromBoilerplate(boilerplate, context);
@@ -4806,7 +4918,7 @@ static Object* CompileDirectEval(Handle<String> source) {
// Compile source string in the current context.
Handle<JSFunction> boilerplate =
- Compiler::CompileEval(source, context, 0, is_global);
+ Compiler::CompileEval(source, context, 0, is_global, false);
if (boilerplate.is_null()) return Failure::Exception();
Handle<JSFunction> fun =
Factory::NewFunctionFromBoilerplate(boilerplate, context);
@@ -4892,26 +5004,6 @@ static Object* Runtime_ResolvePossiblyDirectEval(Arguments args) {
}
-static Object* Runtime_CompileScript(Arguments args) {
- HandleScope scope;
- ASSERT(args.length() == 4);
-
- CONVERT_ARG_CHECKED(String, source, 0);
- CONVERT_ARG_CHECKED(String, script, 1);
- CONVERT_CHECKED(Smi, line_attrs, args[2]);
- int line = line_attrs->value();
- CONVERT_CHECKED(Smi, col_attrs, args[3]);
- int col = col_attrs->value();
- Handle<JSFunction> boilerplate =
- Compiler::Compile(source, script, line, col, NULL, NULL);
- if (boilerplate.is_null()) return Failure::Exception();
- Handle<JSFunction> fun =
- Factory::NewFunctionFromBoilerplate(boilerplate,
- Handle<Context>(Top::context()));
- return *fun;
-}
-
-
static Object* Runtime_SetNewFunctionAttributes(Arguments args) {
// This utility adjusts the property attributes for newly created Function
// object ("new Function(...)") by changing the map.
@@ -5210,12 +5302,16 @@ static Object* Runtime_GlobalPrint(Arguments args) {
return string;
}
-
+// Moves all own elements of an object, that are below a limit, to positions
+// starting at zero. All undefined values are placed after non-undefined values,
+// and are followed by non-existing element. Does not change the length
+// property.
+// Returns the number of non-undefined elements collected.
static Object* Runtime_RemoveArrayHoles(Arguments args) {
- ASSERT(args.length() == 1);
- // Ignore the case if this is not a JSArray.
- if (!args[0]->IsJSArray()) return args[0];
- return JSArray::cast(args[0])->RemoveHoles();
+ ASSERT(args.length() == 2);
+ CONVERT_CHECKED(JSObject, object, args[0]);
+ CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
+ return object->PrepareElementsForSort(limit);
}
@@ -5251,8 +5347,7 @@ static Object* Runtime_EstimateNumberOfElements(Arguments args) {
static Object* Runtime_GetArrayKeys(Arguments args) {
ASSERT(args.length() == 2);
HandleScope scope;
- CONVERT_CHECKED(JSArray, raw_array, args[0]);
- Handle<JSArray> array(raw_array);
+ CONVERT_ARG_CHECKED(JSObject, array, 0);
CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
if (array->elements()->IsDictionary()) {
// Create an array and get all the keys into it, then remove all the
@@ -5274,8 +5369,10 @@ static Object* Runtime_GetArrayKeys(Arguments args) {
single_interval->set(0,
Smi::FromInt(-1),
SKIP_WRITE_BARRIER);
+ uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
+ uint32_t min_length = actual_length < length ? actual_length : length;
Handle<Object> length_object =
- Factory::NewNumber(static_cast<double>(length));
+ Factory::NewNumber(static_cast<double>(min_length));
single_interval->set(1, *length_object);
return *Factory::NewJSArrayWithElements(single_interval);
}
@@ -5316,6 +5413,13 @@ static Object* Runtime_LookupAccessor(Arguments args) {
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
+static Object* Runtime_DebugBreak(Arguments args) {
+ ASSERT(args.length() == 0);
+ return Execution::DebugBreakHelper();
+}
+
+
// Helper functions for wrapping and unwrapping stack frame ids.
static Smi* WrapFrameId(StackFrame::Id id) {
ASSERT(IsAligned(OffsetFrom(id), 4));
@@ -5928,8 +6032,8 @@ static Object* Runtime_GetCFrames(Arguments args) {
if (result->IsFailure()) return result;
static const int kMaxCFramesSize = 200;
- OS::StackFrame frames[kMaxCFramesSize];
- int frames_count = OS::StackWalk(frames, kMaxCFramesSize);
+ ScopedVector<OS::StackFrame> frames(kMaxCFramesSize);
+ int frames_count = OS::StackWalk(frames);
if (frames_count == OS::kStackWalkError) {
return Heap::undefined_value();
}
@@ -6442,7 +6546,8 @@ static Object* Runtime_DebugEvaluate(Arguments args) {
Compiler::CompileEval(function_source,
context,
0,
- context->IsGlobalContext());
+ context->IsGlobalContext(),
+ false);
if (boilerplate.is_null()) return Failure::Exception();
Handle<JSFunction> compiled_function =
Factory::NewFunctionFromBoilerplate(boilerplate, context);
@@ -6500,7 +6605,11 @@ static Object* Runtime_DebugEvaluateGlobal(Arguments args) {
// Compile the source to be evaluated.
Handle<JSFunction> boilerplate =
- Handle<JSFunction>(Compiler::CompileEval(source, context, 0, true));
+ Handle<JSFunction>(Compiler::CompileEval(source,
+ context,
+ 0,
+ true,
+ false));
if (boilerplate.is_null()) return Failure::Exception();
Handle<JSFunction> compiled_function =
Handle<JSFunction>(Factory::NewFunctionFromBoilerplate(boilerplate,
@@ -6523,9 +6632,9 @@ static bool IsExternalStringValid(Object* str) {
if (!str->IsString() || !StringShape(String::cast(str)).IsExternal()) {
return true;
}
- if (StringShape(String::cast(str)).IsAsciiRepresentation()) {
+ if (String::cast(str)->IsAsciiRepresentation()) {
return ExternalAsciiString::cast(str)->resource() != NULL;
- } else if (StringShape(String::cast(str)).IsTwoByteRepresentation()) {
+ } else if (String::cast(str)->IsTwoByteRepresentation()) {
return ExternalTwoByteString::cast(str)->resource() != NULL;
} else {
return true;
@@ -6796,6 +6905,31 @@ static Object* Runtime_SystemBreak(Arguments args) {
}
+static Object* Runtime_FunctionGetAssemblerCode(Arguments args) {
+#ifdef DEBUG
+ HandleScope scope;
+ ASSERT(args.length() == 1);
+ // Get the function and make sure it is compiled.
+ CONVERT_ARG_CHECKED(JSFunction, func, 0);
+ if (!func->is_compiled() && !CompileLazy(func, KEEP_EXCEPTION)) {
+ return Failure::Exception();
+ }
+ func->code()->PrintLn();
+#endif // DEBUG
+ return Heap::undefined_value();
+}
+
+
+static Object* Runtime_FunctionGetInferredName(Arguments args) {
+ NoHandleAllocation ha;
+ ASSERT(args.length() == 1);
+
+ CONVERT_CHECKED(JSFunction, f, args[0]);
+ return f->shared()->inferred_name();
+}
+#endif // ENABLE_DEBUGGER_SUPPORT
+
+
// Finds the script object from the script data. NOTE: This operation uses
// heap traversal to find the function generated for the source position
// for the requested break point. For lazily compiled functions several heap
@@ -6845,21 +6979,6 @@ static Object* Runtime_GetScript(Arguments args) {
}
-static Object* Runtime_FunctionGetAssemblerCode(Arguments args) {
-#ifdef DEBUG
- HandleScope scope;
- ASSERT(args.length() == 1);
- // Get the function and make sure it is compiled.
- CONVERT_ARG_CHECKED(JSFunction, func, 0);
- if (!func->is_compiled() && !CompileLazy(func, KEEP_EXCEPTION)) {
- return Failure::Exception();
- }
- func->code()->PrintLn();
-#endif // DEBUG
- return Heap::undefined_value();
-}
-
-
static Object* Runtime_Abort(Arguments args) {
ASSERT(args.length() == 2);
OS::PrintError("abort: %s\n", reinterpret_cast<char*>(args[0]) +
diff --git a/deps/v8/src/runtime.h b/deps/v8/src/runtime.h
index 657e5c5d9..204129515 100644
--- a/deps/v8/src/runtime.h
+++ b/deps/v8/src/runtime.h
@@ -53,6 +53,7 @@ namespace v8 { namespace internal {
F(ToSlowProperties, 1) \
\
F(IsInPrototypeChain, 2) \
+ F(SetHiddenPrototype, 2) \
\
F(IsConstructCall, 0) \
\
@@ -194,8 +195,7 @@ namespace v8 { namespace internal {
F(NumberIsFinite, 1) \
\
/* Globals */ \
- F(CompileString, 2) \
- F(CompileScript, 4) \
+ F(CompileString, 3) \
F(GlobalPrint, 1) \
\
/* Eval */ \
@@ -206,7 +206,7 @@ namespace v8 { namespace internal {
F(IgnoreAttributesAndSetProperty, -1 /* 3 or 4 */) \
\
/* Arrays */ \
- F(RemoveArrayHoles, 1) \
+ F(RemoveArrayHoles, 2) \
F(GetArrayKeys, 2) \
F(MoveArrayContents, 2) \
F(EstimateNumberOfElements, 1) \
@@ -215,42 +215,6 @@ namespace v8 { namespace internal {
F(DefineAccessor, -1 /* 4 or 5 */) \
F(LookupAccessor, 3) \
\
- /* Debugging */ \
- F(SetDebugEventListener, 2) \
- F(Break, 0) \
- F(DebugGetPropertyDetails, 2) \
- F(DebugGetProperty, 2) \
- F(DebugLocalPropertyNames, 1) \
- F(DebugLocalElementNames, 1) \
- F(DebugPropertyTypeFromDetails, 1) \
- F(DebugPropertyAttributesFromDetails, 1) \
- F(DebugPropertyIndexFromDetails, 1) \
- F(DebugInterceptorInfo, 1) \
- F(DebugNamedInterceptorPropertyNames, 1) \
- F(DebugIndexedInterceptorElementNames, 1) \
- F(DebugNamedInterceptorPropertyValue, 2) \
- F(DebugIndexedInterceptorElementValue, 2) \
- F(CheckExecutionState, 1) \
- F(GetFrameCount, 1) \
- F(GetFrameDetails, 2) \
- F(GetCFrames, 1) \
- F(GetThreadCount, 1) \
- F(GetThreadDetails, 2) \
- F(GetBreakLocations, 1) \
- F(SetFunctionBreakPoint, 3) \
- F(SetScriptBreakPoint, 3) \
- F(ClearBreakPoint, 1) \
- F(ChangeBreakOnException, 2) \
- F(PrepareStep, 3) \
- F(ClearStepping, 0) \
- F(DebugEvaluate, 4) \
- F(DebugEvaluateGlobal, 3) \
- F(DebugGetLoadedScripts, 0) \
- F(DebugReferencedBy, 3) \
- F(DebugConstructedBy, 2) \
- F(DebugGetPrototype, 1) \
- F(SystemBreak, 0) \
- \
/* Literals */ \
F(MaterializeRegExpLiteral, 4)\
F(CreateArrayLiteralBoilerplate, 3) \
@@ -290,8 +254,6 @@ namespace v8 { namespace internal {
F(DebugTrace, 0) \
F(TraceEnter, 0) \
F(TraceExit, 1) \
- F(DebugBreak, 0) \
- F(FunctionGetAssemblerCode, 1) \
F(Abort, 2) \
/* Logging */ \
F(Log, 2) \
@@ -299,6 +261,49 @@ namespace v8 { namespace internal {
/* Pseudo functions - handled as macros by parser */ \
F(IS_VAR, 1)
+#ifdef ENABLE_DEBUGGER_SUPPORT
+#define RUNTIME_FUNCTION_LIST_DEBUGGER_SUPPORT(F) \
+ /* Debugger support*/ \
+ F(DebugBreak, 0) \
+ F(SetDebugEventListener, 2) \
+ F(Break, 0) \
+ F(DebugGetPropertyDetails, 2) \
+ F(DebugGetProperty, 2) \
+ F(DebugLocalPropertyNames, 1) \
+ F(DebugLocalElementNames, 1) \
+ F(DebugPropertyTypeFromDetails, 1) \
+ F(DebugPropertyAttributesFromDetails, 1) \
+ F(DebugPropertyIndexFromDetails, 1) \
+ F(DebugInterceptorInfo, 1) \
+ F(DebugNamedInterceptorPropertyNames, 1) \
+ F(DebugIndexedInterceptorElementNames, 1) \
+ F(DebugNamedInterceptorPropertyValue, 2) \
+ F(DebugIndexedInterceptorElementValue, 2) \
+ F(CheckExecutionState, 1) \
+ F(GetFrameCount, 1) \
+ F(GetFrameDetails, 2) \
+ F(GetCFrames, 1) \
+ F(GetThreadCount, 1) \
+ F(GetThreadDetails, 2) \
+ F(GetBreakLocations, 1) \
+ F(SetFunctionBreakPoint, 3) \
+ F(SetScriptBreakPoint, 3) \
+ F(ClearBreakPoint, 1) \
+ F(ChangeBreakOnException, 2) \
+ F(PrepareStep, 3) \
+ F(ClearStepping, 0) \
+ F(DebugEvaluate, 4) \
+ F(DebugEvaluateGlobal, 3) \
+ F(DebugGetLoadedScripts, 0) \
+ F(DebugReferencedBy, 3) \
+ F(DebugConstructedBy, 2) \
+ F(DebugGetPrototype, 1) \
+ F(SystemBreak, 0) \
+ F(FunctionGetAssemblerCode, 1) \
+ F(FunctionGetInferredName, 1)
+#else
+#define RUNTIME_FUNCTION_LIST_DEBUGGER_SUPPORT(F)
+#endif
#ifdef DEBUG
#define RUNTIME_FUNCTION_LIST_DEBUG(F) \
@@ -316,7 +321,8 @@ namespace v8 { namespace internal {
#define RUNTIME_FUNCTION_LIST(F) \
RUNTIME_FUNCTION_LIST_ALWAYS(F) \
- RUNTIME_FUNCTION_LIST_DEBUG(F)
+ RUNTIME_FUNCTION_LIST_DEBUG(F) \
+ RUNTIME_FUNCTION_LIST_DEBUGGER_SUPPORT(F)
// ----------------------------------------------------------------------------
// Runtime provides access to all C++ runtime functions.
@@ -369,6 +375,11 @@ class Runtime : public AllStatic {
Handle<Object> value,
PropertyAttributes attr);
+ static Object* ForceSetObjectProperty(Handle<JSObject> object,
+ Handle<Object> key,
+ Handle<Object> value,
+ PropertyAttributes attr);
+
static Object* GetObjectProperty(Handle<Object> object, Handle<Object> key);
// This function is used in FunctionNameUsing* tests.
diff --git a/deps/v8/src/serialize.cc b/deps/v8/src/serialize.cc
index 9a2be23e5..62287bc0d 100644
--- a/deps/v8/src/serialize.cc
+++ b/deps/v8/src/serialize.cc
@@ -78,8 +78,8 @@ const int kPageAndOffsetMask = (1 << kPageAndOffsetBits) - 1;
static inline AllocationSpace GetSpace(Address addr) {
- const int encoded = reinterpret_cast<int>(addr);
- int space_number = ((encoded >> kSpaceShift) & kSpaceMask);
+ const intptr_t encoded = reinterpret_cast<intptr_t>(addr);
+ int space_number = (static_cast<int>(encoded >> kSpaceShift) & kSpaceMask);
if (space_number == kLOSpaceExecutable) space_number = LO_SPACE;
else if (space_number == kLOSpacePointer) space_number = LO_SPACE;
return static_cast<AllocationSpace>(space_number);
@@ -87,43 +87,45 @@ static inline AllocationSpace GetSpace(Address addr) {
static inline bool IsLargeExecutableObject(Address addr) {
- const int encoded = reinterpret_cast<int>(addr);
- const int space_number = ((encoded >> kSpaceShift) & kSpaceMask);
- if (space_number == kLOSpaceExecutable) return true;
- return false;
+ const intptr_t encoded = reinterpret_cast<intptr_t>(addr);
+ const int space_number =
+ (static_cast<int>(encoded >> kSpaceShift) & kSpaceMask);
+ return (space_number == kLOSpaceExecutable);
}
static inline bool IsLargeFixedArray(Address addr) {
- const int encoded = reinterpret_cast<int>(addr);
- const int space_number = ((encoded >> kSpaceShift) & kSpaceMask);
- if (space_number == kLOSpacePointer) return true;
- return false;
+ const intptr_t encoded = reinterpret_cast<intptr_t>(addr);
+ const int space_number =
+ (static_cast<int>(encoded >> kSpaceShift) & kSpaceMask);
+ return (space_number == kLOSpacePointer);
}
static inline int PageIndex(Address addr) {
- const int encoded = reinterpret_cast<int>(addr);
- return (encoded >> kPageShift) & kPageMask;
+ const intptr_t encoded = reinterpret_cast<intptr_t>(addr);
+ return static_cast<int>(encoded >> kPageShift) & kPageMask;
}
static inline int PageOffset(Address addr) {
- const int encoded = reinterpret_cast<int>(addr);
- return ((encoded >> kOffsetShift) & kOffsetMask) << kObjectAlignmentBits;
+ const intptr_t encoded = reinterpret_cast<intptr_t>(addr);
+ const int offset = static_cast<int>(encoded >> kOffsetShift) & kOffsetMask;
+ return offset << kObjectAlignmentBits;
}
static inline int NewSpaceOffset(Address addr) {
- const int encoded = reinterpret_cast<int>(addr);
- return ((encoded >> kPageAndOffsetShift) & kPageAndOffsetMask) <<
- kObjectAlignmentBits;
+ const intptr_t encoded = reinterpret_cast<intptr_t>(addr);
+ const int page_offset =
+ static_cast<int>(encoded >> kPageAndOffsetShift) & kPageAndOffsetMask;
+ return page_offset << kObjectAlignmentBits;
}
static inline int LargeObjectIndex(Address addr) {
- const int encoded = reinterpret_cast<int>(addr);
- return (encoded >> kPageAndOffsetShift) & kPageAndOffsetMask;
+ const intptr_t encoded = reinterpret_cast<intptr_t>(addr);
+ return static_cast<int>(encoded >> kPageAndOffsetShift) & kPageAndOffsetMask;
}
@@ -548,6 +550,7 @@ void ExternalReferenceTable::PopulateTable() {
AddFromId(ref_table[i].type, ref_table[i].id, ref_table[i].name);
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Debug addresses
Add(Debug_Address(Debug::k_after_break_target_address).address(),
DEBUG_ADDRESS,
@@ -567,6 +570,7 @@ void ExternalReferenceTable::PopulateTable() {
Debug::k_register_address << kDebugIdShift | i,
name.start());
}
+#endif
// Stat counters
struct StatsRefTableEntry {
@@ -659,10 +663,6 @@ void ExternalReferenceTable::PopulateTable() {
UNCLASSIFIED,
4,
"RegExpStack::limit_address()");
- Add(ExternalReference::debug_break().address(),
- UNCLASSIFIED,
- 5,
- "Debug::Break()");
Add(ExternalReference::new_space_start().address(),
UNCLASSIFIED,
6,
@@ -679,10 +679,28 @@ void ExternalReferenceTable::PopulateTable() {
UNCLASSIFIED,
9,
"Heap::NewSpaceAllocationTopAddress()");
+#ifdef ENABLE_DEBUGGER_SUPPORT
+ Add(ExternalReference::debug_break().address(),
+ UNCLASSIFIED,
+ 5,
+ "Debug::Break()");
Add(ExternalReference::debug_step_in_fp_address().address(),
UNCLASSIFIED,
10,
"Debug::step_in_fp_addr()");
+ Add(ExternalReference::double_fp_operation(Token::ADD).address(),
+ UNCLASSIFIED,
+ 11,
+ "add_two_doubles");
+ Add(ExternalReference::double_fp_operation(Token::SUB).address(),
+ UNCLASSIFIED,
+ 12,
+ "sub_two_doubles");
+ Add(ExternalReference::double_fp_operation(Token::MUL).address(),
+ UNCLASSIFIED,
+ 13,
+ "mul_two_doubles");
+#endif
}
@@ -712,7 +730,9 @@ int ExternalReferenceEncoder::IndexOf(Address key) const {
if (key == NULL) return -1;
HashMap::Entry* entry =
const_cast<HashMap &>(encodings_).Lookup(key, Hash(key), false);
- return entry == NULL ? -1 : reinterpret_cast<int>(entry->value);
+ return entry == NULL
+ ? -1
+ : static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
}
@@ -778,6 +798,10 @@ class SnapshotWriter {
InsertInt(i, len_);
}
+ void PutAddress(Address p) {
+ PutBytes(reinterpret_cast<byte*>(&p), sizeof(p));
+ }
+
void PutBytes(const byte* a, int size) {
InsertBytes(a, len_, size);
}
@@ -898,7 +922,8 @@ class ReferenceUpdater: public ObjectVisitor {
// Helper functions for a map of encoded heap object addresses.
static uint32_t HeapObjectHash(HeapObject* key) {
- return reinterpret_cast<uint32_t>(key) >> 2;
+ uint32_t low32bits = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key));
+ return low32bits >> 2;
}
@@ -1137,7 +1162,7 @@ void Serializer::PutContextStack() {
void Serializer::PutEncodedAddress(Address addr) {
writer_->PutC('P');
- writer_->PutInt(reinterpret_cast<int>(addr));
+ writer_->PutAddress(addr);
}
@@ -1320,7 +1345,7 @@ void Deserializer::VisitPointers(Object** start, Object** end) {
*p = GetObject(); // embedded object
} else {
ASSERT(c == 'P'); // pointer to previously serialized object
- *p = Resolve(reinterpret_cast<Address>(reader_.GetInt()));
+ *p = Resolve(reader_.GetAddress());
}
} else {
// A pointer internal to a HeapObject that we've already
@@ -1334,7 +1359,7 @@ void Deserializer::VisitPointers(Object** start, Object** end) {
void Deserializer::VisitExternalReferences(Address* start, Address* end) {
for (Address* p = start; p < end; ++p) {
- uint32_t code = reinterpret_cast<uint32_t>(*p);
+ uint32_t code = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(*p));
*p = reference_decoder_->Decode(code);
}
}
@@ -1460,7 +1485,7 @@ void Deserializer::GetContextStack() {
Address Deserializer::GetEncodedAddress() {
reader_.ExpectC('P');
- return reinterpret_cast<Address>(reader_.GetInt());
+ return reader_.GetAddress();
}
diff --git a/deps/v8/src/serialize.h b/deps/v8/src/serialize.h
index ce7d94784..f6594aca8 100644
--- a/deps/v8/src/serialize.h
+++ b/deps/v8/src/serialize.h
@@ -70,7 +70,7 @@ class ExternalReferenceEncoder {
private:
HashMap encodings_;
static uint32_t Hash(Address key) {
- return reinterpret_cast<uint32_t>(key) >> 2;
+ return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key) >> 2);
}
int IndexOf(Address key) const;
@@ -231,6 +231,12 @@ class SnapshotReader {
return result;
}
+ Address GetAddress() {
+ Address result;
+ GetBytes(reinterpret_cast<Address>(&result), sizeof(result));
+ return result;
+ }
+
void GetBytes(Address a, int size) {
ASSERT(str_ + size <= end_);
memcpy(a, str_, size);
diff --git a/deps/v8/src/shell.h b/deps/v8/src/shell.h
index 4042c07ca..671245128 100644
--- a/deps/v8/src/shell.h
+++ b/deps/v8/src/shell.h
@@ -27,6 +27,9 @@
//
// A simple interactive shell. Enable with --shell.
+#ifndef V8_SHELL_H_
+#define V8_SHELL_H_
+
#include "../public/debug.h"
namespace v8 { namespace internal {
@@ -47,3 +50,5 @@ class Shell {
};
} } // namespace v8::internal
+
+#endif // V8_SHELL_H_
diff --git a/deps/v8/src/spaces-inl.h b/deps/v8/src/spaces-inl.h
index d7cddb4fd..397365847 100644
--- a/deps/v8/src/spaces-inl.h
+++ b/deps/v8/src/spaces-inl.h
@@ -64,15 +64,16 @@ HeapObject* HeapObjectIterator::next() {
// PageIterator
bool PageIterator::has_next() {
- return cur_page_ != stop_page_;
+ return prev_page_ != stop_page_;
}
Page* PageIterator::next() {
ASSERT(has_next());
- Page* result = cur_page_;
- cur_page_ = cur_page_->next_page();
- return result;
+ prev_page_ = (prev_page_ == NULL)
+ ? space_->first_page_
+ : prev_page_->next_page();
+ return prev_page_;
}
diff --git a/deps/v8/src/spaces.cc b/deps/v8/src/spaces.cc
index ea40d5211..f15af9e72 100644
--- a/deps/v8/src/spaces.cc
+++ b/deps/v8/src/spaces.cc
@@ -111,17 +111,17 @@ void HeapObjectIterator::Verify() {
// -----------------------------------------------------------------------------
// PageIterator
-PageIterator::PageIterator(PagedSpace* space, Mode mode) {
- cur_page_ = space->first_page_;
+PageIterator::PageIterator(PagedSpace* space, Mode mode) : space_(space) {
+ prev_page_ = NULL;
switch (mode) {
case PAGES_IN_USE:
- stop_page_ = space->AllocationTopPage()->next_page();
+ stop_page_ = space->AllocationTopPage();
break;
case PAGES_USED_BY_MC:
- stop_page_ = space->MCRelocationTopPage()->next_page();
+ stop_page_ = space->MCRelocationTopPage();
break;
case ALL_PAGES:
- stop_page_ = Page::FromAddress(NULL);
+ stop_page_ = space->last_page_;
break;
default:
UNREACHABLE();
@@ -496,8 +496,11 @@ bool PagedSpace::Setup(Address start, size_t size) {
accounting_stats_.ExpandSpace(num_pages * Page::kObjectAreaSize);
ASSERT(Capacity() <= max_capacity_);
+ // Sequentially initialize remembered sets in the newly allocated
+ // pages and cache the current last page in the space.
for (Page* p = first_page_; p->is_valid(); p = p->next_page()) {
p->ClearRSet();
+ last_page_ = p;
}
// Use first_page_ for allocation.
@@ -676,9 +679,11 @@ bool PagedSpace::Expand(Page* last_page) {
MemoryAllocator::SetNextPage(last_page, p);
- // Clear remembered set of new pages.
+ // Sequentially clear remembered set of new pages and and cache the
+ // new last page in the space.
while (p->is_valid()) {
p->ClearRSet();
+ last_page_ = p;
p = p->next_page();
}
@@ -723,10 +728,12 @@ void PagedSpace::Shrink() {
Page* p = MemoryAllocator::FreePages(last_page_to_keep->next_page());
MemoryAllocator::SetNextPage(last_page_to_keep, p);
- // Since pages are only freed in whole chunks, we may have kept more than
- // pages_to_keep.
+ // Since pages are only freed in whole chunks, we may have kept more
+ // than pages_to_keep. Count the extra pages and cache the new last
+ // page in the space.
while (p->is_valid()) {
pages_to_keep++;
+ last_page_ = p;
p = p->next_page();
}
@@ -811,7 +818,7 @@ bool NewSpace::Setup(Address start, int size) {
start_ = start;
address_mask_ = ~(size - 1);
object_mask_ = address_mask_ | kHeapObjectTag;
- object_expected_ = reinterpret_cast<uint32_t>(start) | kHeapObjectTag;
+ object_expected_ = reinterpret_cast<uintptr_t>(start) | kHeapObjectTag;
allocation_info_.top = to_space_.low();
allocation_info_.limit = to_space_.high();
@@ -970,7 +977,7 @@ bool SemiSpace::Setup(Address start,
start_ = start;
address_mask_ = ~(maximum_capacity - 1);
object_mask_ = address_mask_ | kHeapObjectTag;
- object_expected_ = reinterpret_cast<uint32_t>(start) | kHeapObjectTag;
+ object_expected_ = reinterpret_cast<uintptr_t>(start) | kHeapObjectTag;
age_mark_ = start_;
return true;
@@ -1890,7 +1897,7 @@ static void PrintRSetRange(Address start, Address end, Object** object_p,
// If the range starts on on odd numbered word (eg, for large object extra
// remembered set ranges), print some spaces.
- if ((reinterpret_cast<uint32_t>(start) / kIntSize) % 2 == 1) {
+ if ((reinterpret_cast<uintptr_t>(start) / kIntSize) % 2 == 1) {
PrintF(" ");
}
@@ -1929,7 +1936,7 @@ static void PrintRSetRange(Address start, Address end, Object** object_p,
}
// Print a newline after every odd numbered word, otherwise a space.
- if ((reinterpret_cast<uint32_t>(rset_address) / kIntSize) % 2 == 1) {
+ if ((reinterpret_cast<uintptr_t>(rset_address) / kIntSize) % 2 == 1) {
PrintF("\n");
} else {
PrintF(" ");
diff --git a/deps/v8/src/spaces.h b/deps/v8/src/spaces.h
index 3138cc360..e8504a427 100644
--- a/deps/v8/src/spaces.h
+++ b/deps/v8/src/spaces.h
@@ -511,11 +511,22 @@ class ObjectIterator : public Malloced {
//
// A HeapObjectIterator iterates objects from a given address to the
// top of a space. The given address must be below the current
-// allocation pointer (space top). If the space top changes during
-// iteration (because of allocating new objects), the iterator does
-// not iterate new objects. The caller function must create a new
-// iterator starting from the old top in order to visit these new
-// objects. Heap::Scavenage() is such an example.
+// allocation pointer (space top). There are some caveats.
+//
+// (1) If the space top changes upward during iteration (because of
+// allocating new objects), the iterator does not iterate objects
+// above the original space top. The caller must create a new
+// iterator starting from the old top in order to visit these new
+// objects.
+//
+// (2) If new objects are allocated below the original allocation top
+// (e.g., free-list allocation in paged spaces), the new objects
+// may or may not be iterated depending on their position with
+// respect to the current point of iteration.
+//
+// (3) The space top should not change downward during iteration,
+// otherwise the iterator will return not-necessarily-valid
+// objects.
class HeapObjectIterator: public ObjectIterator {
public:
@@ -559,17 +570,35 @@ class HeapObjectIterator: public ObjectIterator {
// -----------------------------------------------------------------------------
-// A PageIterator iterates pages in a space.
+// A PageIterator iterates the pages in a paged space.
//
// The PageIterator class provides three modes for iterating pages in a space:
-// PAGES_IN_USE iterates pages that are in use by the allocator;
-// PAGES_USED_BY_GC iterates pages that hold relocated objects during a
-// mark-compact collection;
+// PAGES_IN_USE iterates pages containing allocated objects.
+// PAGES_USED_BY_MC iterates pages that hold relocated objects during a
+// mark-compact collection.
// ALL_PAGES iterates all pages in the space.
+//
+// There are some caveats.
+//
+// (1) If the space expands during iteration, new pages will not be
+// returned by the iterator in any mode.
+//
+// (2) If new objects are allocated during iteration, they will appear
+// in pages returned by the iterator. Allocation may cause the
+// allocation pointer or MC allocation pointer in the last page to
+// change between constructing the iterator and iterating the last
+// page.
+//
+// (3) The space should not shrink during iteration, otherwise the
+// iterator will return deallocated pages.
class PageIterator BASE_EMBEDDED {
public:
- enum Mode {PAGES_IN_USE, PAGES_USED_BY_MC, ALL_PAGES};
+ enum Mode {
+ PAGES_IN_USE,
+ PAGES_USED_BY_MC,
+ ALL_PAGES
+ };
PageIterator(PagedSpace* space, Mode mode);
@@ -577,8 +606,9 @@ class PageIterator BASE_EMBEDDED {
inline Page* next();
private:
- Page* cur_page_; // next page to return
- Page* stop_page_; // page where to stop
+ PagedSpace* space_;
+ Page* prev_page_; // Previous page returned.
+ Page* stop_page_; // Page to stop at (last page returned by the iterator).
};
@@ -809,6 +839,10 @@ class PagedSpace : public Space {
// The first page in this space.
Page* first_page_;
+ // The last page in this space. Initially set in Setup, updated in
+ // Expand and Shrink.
+ Page* last_page_;
+
// Normal allocation information.
AllocationInfo allocation_info_;
@@ -939,14 +973,14 @@ class SemiSpace : public Space {
// True if the address is in the address range of this semispace (not
// necessarily below the allocation pointer).
bool Contains(Address a) {
- return (reinterpret_cast<uint32_t>(a) & address_mask_)
- == reinterpret_cast<uint32_t>(start_);
+ return (reinterpret_cast<uintptr_t>(a) & address_mask_)
+ == reinterpret_cast<uintptr_t>(start_);
}
// True if the object is a heap object in the address range of this
// semispace (not necessarily below the allocation pointer).
bool Contains(Object* o) {
- return (reinterpret_cast<uint32_t>(o) & object_mask_) == object_expected_;
+ return (reinterpret_cast<uintptr_t>(o) & object_mask_) == object_expected_;
}
// The offset of an address from the beginning of the space.
@@ -975,9 +1009,9 @@ class SemiSpace : public Space {
Address age_mark_;
// Masks and comparison values to test for containment in this semispace.
- uint32_t address_mask_;
- uint32_t object_mask_;
- uint32_t object_expected_;
+ uintptr_t address_mask_;
+ uintptr_t object_mask_;
+ uintptr_t object_expected_;
public:
TRACK_MEMORY("SemiSpace")
@@ -1063,11 +1097,11 @@ class NewSpace : public Space {
// True if the address or object lies in the address range of either
// semispace (not necessarily below the allocation pointer).
bool Contains(Address a) {
- return (reinterpret_cast<uint32_t>(a) & address_mask_)
- == reinterpret_cast<uint32_t>(start_);
+ return (reinterpret_cast<uintptr_t>(a) & address_mask_)
+ == reinterpret_cast<uintptr_t>(start_);
}
bool Contains(Object* o) {
- return (reinterpret_cast<uint32_t>(o) & object_mask_) == object_expected_;
+ return (reinterpret_cast<uintptr_t>(o) & object_mask_) == object_expected_;
}
// Return the allocated bytes in the active semispace.
@@ -1183,9 +1217,9 @@ class NewSpace : public Space {
// Start address and bit mask for containment testing.
Address start_;
- uint32_t address_mask_;
- uint32_t object_mask_;
- uint32_t object_expected_;
+ uintptr_t address_mask_;
+ uintptr_t object_mask_;
+ uintptr_t object_expected_;
// Allocation pointer and limit for normal allocation and allocation during
// mark-compact collection.
diff --git a/deps/v8/src/string-stream.cc b/deps/v8/src/string-stream.cc
index f311e20bd..2e0912fbd 100644
--- a/deps/v8/src/string-stream.cc
+++ b/deps/v8/src/string-stream.cc
@@ -57,19 +57,26 @@ NoAllocationStringAllocator::NoAllocationStringAllocator(char* memory,
bool StringStream::Put(char c) {
- if (space() == 0) return false;
- if (length_ >= capacity_ - 1) {
+ if (full()) return false;
+ ASSERT(length_ < capacity_);
+ // Since the trailing '\0' is not accounted for in length_ fullness is
+ // indicated by a difference of 1 between length_ and capacity_. Thus when
+ // reaching a difference of 2 we need to grow the buffer.
+ if (length_ == capacity_ - 2) {
unsigned new_capacity = capacity_;
char* new_buffer = allocator_->grow(&new_capacity);
if (new_capacity > capacity_) {
capacity_ = new_capacity;
buffer_ = new_buffer;
} else {
- // Indicate truncation with dots.
- memset(cursor(), '.', space());
- length_ = capacity_;
- buffer_[length_ - 2] = '\n';
- buffer_[length_ - 1] = '\0';
+ // Reached the end of the available buffer.
+ ASSERT(capacity_ >= 5);
+ length_ = capacity_ - 1; // Indicate fullness of the stream.
+ buffer_[length_ - 4] = '.';
+ buffer_[length_ - 3] = '.';
+ buffer_[length_ - 2] = '.';
+ buffer_[length_ - 1] = '\n';
+ buffer_[length_] = '\0';
return false;
}
}
@@ -95,8 +102,7 @@ static bool IsControlChar(char c) {
void StringStream::Add(Vector<const char> format, Vector<FmtElm> elms) {
// If we already ran out of space then return immediately.
- if (space() == 0)
- return;
+ if (full()) return;
int offset = 0;
int elm = 0;
while (offset < format.length()) {
@@ -564,12 +570,10 @@ char* HeapStringAllocator::grow(unsigned* bytes) {
}
+// Only grow once to the maximum allowable size.
char* NoAllocationStringAllocator::grow(unsigned* bytes) {
- unsigned new_bytes = *bytes * 2;
- if (new_bytes > size_) {
- new_bytes = size_;
- }
- *bytes = new_bytes;
+ ASSERT(size_ >= *bytes);
+ *bytes = size_;
return space_;
}
diff --git a/deps/v8/src/string-stream.h b/deps/v8/src/string-stream.h
index 37ae93e2c..fa20064e4 100644
--- a/deps/v8/src/string-stream.h
+++ b/deps/v8/src/string-stream.h
@@ -72,13 +72,36 @@ class NoAllocationStringAllocator: public StringAllocator {
class FmtElm {
public:
- FmtElm(int value) : type_(INT) { data_.u_int_ = value; } // NOLINT
- explicit FmtElm(double value) : type_(DOUBLE) { data_.u_double_ = value; } // NOLINT
- FmtElm(const char* value) : type_(C_STR) { data_.u_c_str_ = value; } // NOLINT
- FmtElm(const Vector<const uc16>& value) : type_(LC_STR) { data_.u_lc_str_ = &value; } // NOLINT
- FmtElm(Object* value) : type_(OBJ) { data_.u_obj_ = value; } // NOLINT
- FmtElm(Handle<Object> value) : type_(HANDLE) { data_.u_handle_ = value.location(); } // NOLINT
- FmtElm(void* value) : type_(INT) { data_.u_int_ = reinterpret_cast<int>(value); } // NOLINT
+ FmtElm(int value) : type_(INT) { // NOLINT
+ data_.u_int_ = value;
+ }
+ explicit FmtElm(double value) : type_(DOUBLE) {
+ data_.u_double_ = value;
+ }
+ FmtElm(const char* value) : type_(C_STR) { // NOLINT
+ data_.u_c_str_ = value;
+ }
+ FmtElm(const Vector<const uc16>& value) : type_(LC_STR) { // NOLINT
+ data_.u_lc_str_ = &value;
+ }
+ FmtElm(Object* value) : type_(OBJ) { // NOLINT
+ data_.u_obj_ = value;
+ }
+ FmtElm(Handle<Object> value) : type_(HANDLE) { // NOLINT
+ data_.u_handle_ = value.location();
+ }
+ FmtElm(void* value) : type_(INT) { // NOLINT
+#if V8_HOST_ARCH_64_BIT
+ // TODO(x64): FmtElm needs to treat pointers as pointers, and not as
+ // ints. This will require adding a pointer type, etc. For now just
+ // hack it and truncate the pointer.
+ // http://code.google.com/p/v8/issues/detail?id=335
+ data_.u_int_ = 0;
+ UNIMPLEMENTED();
+#else
+ data_.u_int_ = reinterpret_cast<int>(value);
+#endif
+ }
private:
friend class StringStream;
enum Type { INT, DOUBLE, C_STR, LC_STR, OBJ, HANDLE };
@@ -162,8 +185,8 @@ class StringStream {
unsigned length_; // does not include terminating 0-character
char* buffer_;
+ bool full() const { return (capacity_ - length_) == 1; }
int space() const { return capacity_ - length_; }
- char* cursor() const { return buffer_ + length_; }
DISALLOW_IMPLICIT_CONSTRUCTORS(StringStream);
};
diff --git a/deps/v8/src/string.js b/deps/v8/src/string.js
index 3ccad9a21..0bcabc943 100644
--- a/deps/v8/src/string.js
+++ b/deps/v8/src/string.js
@@ -812,6 +812,11 @@ ReplaceResultBuilder.prototype.generate = function() {
}
+function StringToJSON(key) {
+ return CheckJSONPrimitive(this.valueOf());
+}
+
+
// -------------------------------------------------------------------
function SetupString() {
@@ -826,7 +831,7 @@ function SetupString() {
// Setup the non-enumerable functions on the String prototype object.
- InstallFunctions($String.prototype, DONT_ENUM, $Array(
+ InstallFunctionsOnHiddenPrototype($String.prototype, DONT_ENUM, $Array(
"valueOf", StringValueOf,
"toString", StringToString,
"charAt", StringCharAt,
@@ -858,7 +863,8 @@ function SetupString() {
"small", StringSmall,
"strike", StringStrike,
"sub", StringSub,
- "sup", StringSup
+ "sup", StringSup,
+ "toJSON", StringToJSON
));
}
diff --git a/deps/v8/src/stub-cache.cc b/deps/v8/src/stub-cache.cc
index 35e3d42a5..6811fd2e7 100644
--- a/deps/v8/src/stub-cache.cc
+++ b/deps/v8/src/stub-cache.cc
@@ -594,6 +594,7 @@ Object* StubCache::ComputeCallMiss(int argc) {
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
Object* StubCache::ComputeCallDebugBreak(int argc) {
Code::Flags flags =
Code::ComputeFlags(Code::CALL_IC, DEBUG_BREAK, NORMAL, argc);
@@ -612,6 +613,7 @@ Object* StubCache::ComputeCallDebugPrepareStepIn(int argc) {
StubCompiler compiler;
return FillCache(compiler.CompileCallDebugPrepareStepIn(flags));
}
+#endif
Object* StubCache::ComputeLazyCompile(int argc) {
@@ -836,6 +838,7 @@ Object* StubCompiler::CompileCallMiss(Code::Flags flags) {
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
Object* StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
HandleScope scope;
Debug::GenerateCallICDebugBreak(masm());
@@ -864,6 +867,7 @@ Object* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
}
return result;
}
+#endif
Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, const char* name) {
diff --git a/deps/v8/src/stub-cache.h b/deps/v8/src/stub-cache.h
index 05845e596..369b15da9 100644
--- a/deps/v8/src/stub-cache.h
+++ b/deps/v8/src/stub-cache.h
@@ -157,8 +157,10 @@ class StubCache : public AllStatic {
// Finds the Code object stored in the Heap::non_monomorphic_cache().
static Code* FindCallInitialize(int argc);
+#ifdef ENABLE_DEBUGGER_SUPPORT
static Object* ComputeCallDebugBreak(int argc);
static Object* ComputeCallDebugPrepareStepIn(int argc);
+#endif
static Object* ComputeLazyCompile(int argc);
@@ -201,14 +203,21 @@ class StubCache : public AllStatic {
// Compute the hash of the name (use entire length field).
ASSERT(name->HasHashCode());
uint32_t field = name->length_field();
+ // Using only the low bits in 64-bit mode is unlikely to increase the
+ // risk of collision even if the heap is spread over an area larger than
+ // 4Gb (and not at all if it isn't).
+ uint32_t map_low32bits =
+ static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
// Base the offset on a simple combination of name, flags, and map.
- uint32_t key = (reinterpret_cast<uint32_t>(map) + field) ^ flags;
+ uint32_t key = (map_low32bits + field) ^ flags;
return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
}
static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
// Use the seed from the primary cache in the secondary cache.
- uint32_t key = seed - reinterpret_cast<uint32_t>(name) + flags;
+ uint32_t string_low32bits =
+ static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
+ uint32_t key = seed - string_low32bits + flags;
return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
}
@@ -288,8 +297,10 @@ class StubCompiler BASE_EMBEDDED {
Object* CompileCallNormal(Code::Flags flags);
Object* CompileCallMegamorphic(Code::Flags flags);
Object* CompileCallMiss(Code::Flags flags);
+#ifdef ENABLE_DEBUGGER_SUPPORT
Object* CompileCallDebugBreak(Code::Flags flags);
Object* CompileCallDebugPrepareStepIn(Code::Flags flags);
+#endif
Object* CompileLazyCompile(Code::Flags flags);
// Static functions for generating parts of stubs.
diff --git a/deps/v8/src/top.cc b/deps/v8/src/top.cc
index a99e9fff8..96f98a5a2 100644
--- a/deps/v8/src/top.cc
+++ b/deps/v8/src/top.cc
@@ -116,15 +116,15 @@ class PreallocatedMemoryThread: public Thread {
// When the thread starts running it will allocate a fixed number of bytes
// on the stack and publish the location of this memory for others to use.
void Run() {
- EmbeddedVector<char, 32 * 1024> local_buffer;
+ EmbeddedVector<char, 15 * 1024> local_buffer;
// Initialize the buffer with a known good value.
OS::StrNCpy(local_buffer, "Trace data was not generated.\n",
local_buffer.length());
// Publish the local buffer and signal its availability.
- data_ = &local_buffer[0];
- length_ = sizeof(local_buffer);
+ data_ = local_buffer.start();
+ length_ = local_buffer.length();
data_ready_semaphore_->Signal();
while (keep_running_) {
@@ -728,8 +728,10 @@ void Top::DoThrow(Object* exception,
bool should_return_exception = ShouldReportException(&is_caught_externally);
bool report_exception = !is_out_of_memory && should_return_exception;
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Notify debugger of exception.
Debugger::OnException(exception_handle, report_exception);
+#endif
// Generate the message.
Handle<Object> message_obj;
diff --git a/deps/v8/src/unicode-inl.h b/deps/v8/src/unicode-inl.h
index 9737c2736..0ee03bd96 100644
--- a/deps/v8/src/unicode-inl.h
+++ b/deps/v8/src/unicode-inl.h
@@ -25,8 +25,8 @@
// (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 __UNIBROW_INL_H__
-#define __UNIBROW_INL_H__
+#ifndef V8_UNICODE_INL_H_
+#define V8_UNICODE_INL_H_
#include "unicode.h"
@@ -235,4 +235,4 @@ Utf8InputBuffer<s>::Utf8InputBuffer(const char* data, unsigned length)
} // namespace unibrow
-#endif // __UNIBROW_INL_H__
+#endif // V8_UNICODE_INL_H_
diff --git a/deps/v8/src/unicode.h b/deps/v8/src/unicode.h
index 86fd49885..f5e4210cb 100644
--- a/deps/v8/src/unicode.h
+++ b/deps/v8/src/unicode.h
@@ -25,8 +25,8 @@
// (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 __UNIBROW_H__
-#define __UNIBROW_H__
+#ifndef V8_UNICODE_H_
+#define V8_UNICODE_H_
#include <sys/types.h>
@@ -276,4 +276,4 @@ struct CanonicalizationRange {
} // namespace unibrow
-#endif // __UNIBROW_H__
+#endif // V8_UNICODE_H_
diff --git a/deps/v8/src/usage-analyzer.h b/deps/v8/src/usage-analyzer.h
index 2732dd576..2369422b9 100644
--- a/deps/v8/src/usage-analyzer.h
+++ b/deps/v8/src/usage-analyzer.h
@@ -25,8 +25,8 @@
// (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_USAGE_ANALYSER_H_
-#define V8_USAGE_ANALYSER_H_
+#ifndef V8_USAGE_ANALYZER_H_
+#define V8_USAGE_ANALYZER_H_
namespace v8 { namespace internal {
@@ -36,4 +36,4 @@ bool AnalyzeVariableUsage(FunctionLiteral* lit);
} } // namespace v8::internal
-#endif // V8_USAGE_ANALYSER_H_
+#endif // V8_USAGE_ANALYZER_H_
diff --git a/deps/v8/src/utils.h b/deps/v8/src/utils.h
index f62b47a54..0febe4a8d 100644
--- a/deps/v8/src/utils.h
+++ b/deps/v8/src/utils.h
@@ -406,6 +406,16 @@ class EmbeddedVector : public Vector<T> {
};
+template <typename T>
+class ScopedVector : public Vector<T> {
+ public:
+ explicit ScopedVector(int length) : Vector<T>(NewArray<T>(length), length) { }
+ ~ScopedVector() {
+ DeleteArray(this->start());
+ }
+};
+
+
inline Vector<const char> CStrVector(const char* data) {
return Vector<const char>(data, strlen(data));
}
@@ -517,7 +527,7 @@ class StringBuilder {
template <typename sourcechar, typename sinkchar>
static inline void CopyChars(sinkchar* dest, const sourcechar* src, int chars) {
sinkchar* limit = dest + chars;
-#ifdef CAN_READ_UNALIGNED
+#ifdef V8_HOST_CAN_READ_UNALIGNED
if (sizeof(*dest) == sizeof(*src)) {
// Number of characters in a uint32_t.
static const int kStepSize = sizeof(uint32_t) / sizeof(*dest); // NOLINT
diff --git a/deps/v8/src/v8-counters.h b/deps/v8/src/v8-counters.h
index 6596dbf47..34156ea6f 100644
--- a/deps/v8/src/v8-counters.h
+++ b/deps/v8/src/v8-counters.h
@@ -116,6 +116,8 @@ namespace v8 { namespace internal {
SC(keyed_load_interceptor, V8.KeyedLoadInterceptor) \
SC(keyed_load_inline, V8.KeyedLoadInline) \
SC(keyed_load_inline_miss, V8.KeyedLoadInlineMiss) \
+ SC(named_load_inline, V8.NamedLoadInline) \
+ SC(named_load_inline_miss, V8.NamedLoadInlineMiss) \
SC(keyed_store_field, V8.KeyedStoreField) \
SC(for_in, V8.ForIn) \
SC(enum_cache_hits, V8.EnumCacheHits) \
@@ -159,4 +161,4 @@ class Counters : AllStatic {
} } // namespace v8::internal
-#endif // V8_COUNTERS_H_
+#endif // V8_V8_COUNTERS_H_
diff --git a/deps/v8/src/v8.cc b/deps/v8/src/v8.cc
index 9158b5269..c0124e4de 100644
--- a/deps/v8/src/v8.cc
+++ b/deps/v8/src/v8.cc
@@ -72,7 +72,9 @@ bool V8::Initialize(Deserializer *des) {
v8::Locker::StartPreemption(100);
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
Debug::Setup(create_heap_objects);
+#endif
StubCache::Initialize(create_heap_objects);
// If we are deserializing, read the state into the now-empty heap.
@@ -111,8 +113,6 @@ void V8::TearDown() {
Heap::TearDown();
Logger::TearDown();
- Debugger::TearDown();
-
has_been_setup_ = false;
has_been_disposed_ = true;
}
diff --git a/deps/v8/src/v8.h b/deps/v8/src/v8.h
index 4cf0b70e4..4ced0d2b4 100644
--- a/deps/v8/src/v8.h
+++ b/deps/v8/src/v8.h
@@ -51,6 +51,11 @@
#error both DEBUG and NDEBUG are set
#endif
+// Enable debugger support by default, unless it is in ANDROID
+#if !defined(ENABLE_DEBUGGER_SUPPORT) && !defined(ANDROID)
+#define ENABLE_DEBUGGER_SUPPORT
+#endif
+
// Basic includes
#include "../include/v8.h"
#include "globals.h"
diff --git a/deps/v8/src/v8natives.js b/deps/v8/src/v8natives.js
index 9772e2f0c..55bc9f8ff 100644
--- a/deps/v8/src/v8natives.js
+++ b/deps/v8/src/v8natives.js
@@ -54,6 +54,16 @@ function InstallFunctions(object, attributes, functions) {
}
}
+// Emulates JSC by installing functions on a hidden prototype that
+// lies above the current object/prototype. This lets you override
+// functions on String.prototype etc. and then restore the old function
+// with delete. See http://code.google.com/p/chromium/issues/detail?id=1717
+function InstallFunctionsOnHiddenPrototype(object, attributes, functions) {
+ var hidden_prototype = new $Object();
+ %SetHiddenPrototype(object, hidden_prototype);
+ InstallFunctions(hidden_prototype, attributes, functions);
+}
+
// ----------------------------------------------------------------------------
@@ -110,7 +120,7 @@ function GlobalEval(x) {
'be the global object from which eval originated');
}
- var f = %CompileString(x, 0);
+ var f = %CompileString(x, 0, false);
if (!IS_FUNCTION(f)) return f;
return f.call(this);
@@ -121,7 +131,7 @@ function GlobalEval(x) {
function GlobalExecScript(expr, lang) {
// NOTE: We don't care about the character casing.
if (!lang || /javascript/i.test(lang)) {
- var f = %CompileString(ToString(expr), 0);
+ var f = %CompileString(ToString(expr), 0, false);
f.call(%GlobalReceiver(global));
}
return null;
@@ -312,13 +322,19 @@ function BooleanValueOf() {
}
+function BooleanToJSON(key) {
+ return CheckJSONPrimitive(this.valueOf());
+}
+
+
// ----------------------------------------------------------------------------
function SetupBoolean() {
InstallFunctions($Boolean.prototype, DONT_ENUM, $Array(
"toString", BooleanToString,
- "valueOf", BooleanValueOf
+ "valueOf", BooleanValueOf,
+ "toJSON", BooleanToJSON
));
}
@@ -418,6 +434,18 @@ function NumberToPrecision(precision) {
}
+function CheckJSONPrimitive(val) {
+ if (!IsPrimitive(val))
+ throw MakeTypeError('result_not_primitive', ['toJSON', val]);
+ return val;
+}
+
+
+function NumberToJSON(key) {
+ return CheckJSONPrimitive(this.valueOf());
+}
+
+
// ----------------------------------------------------------------------------
function SetupNumber() {
@@ -455,7 +483,8 @@ function SetupNumber() {
"valueOf", NumberValueOf,
"toFixed", NumberToFixed,
"toExponential", NumberToExponential,
- "toPrecision", NumberToPrecision
+ "toPrecision", NumberToPrecision,
+ "toJSON", NumberToJSON
));
}
@@ -521,7 +550,7 @@ function NewFunction(arg1) { // length == 1
// The call to SetNewFunctionAttributes will ensure the prototype
// property of the resulting function is enumerable (ECMA262, 15.3.5.2).
- var f = %CompileString(source, -1)();
+ var f = %CompileString(source, -1, false)();
%FunctionSetName(f, "anonymous");
return %SetNewFunctionAttributes(f);
}
diff --git a/deps/v8/src/v8threads.cc b/deps/v8/src/v8threads.cc
index e8f6f9b22..838cae772 100644
--- a/deps/v8/src/v8threads.cc
+++ b/deps/v8/src/v8threads.cc
@@ -144,7 +144,9 @@ bool ThreadManager::RestoreThread() {
char* from = state->data();
from = HandleScopeImplementer::RestoreThread(from);
from = Top::RestoreThread(from);
+#ifdef ENABLE_DEBUGGER_SUPPORT
from = Debug::RestoreDebug(from);
+#endif
from = StackGuard::RestoreStackGuard(from);
from = RegExpStack::RestoreStack(from);
from = Bootstrapper::RestoreState(from);
@@ -172,7 +174,9 @@ void ThreadManager::Unlock() {
static int ArchiveSpacePerThread() {
return HandleScopeImplementer::ArchiveSpacePerThread() +
Top::ArchiveSpacePerThread() +
+#ifdef ENABLE_DEBUGGER_SUPPORT
Debug::ArchiveSpacePerThread() +
+#endif
StackGuard::ArchiveSpacePerThread() +
RegExpStack::ArchiveSpacePerThread() +
Bootstrapper::ArchiveSpacePerThread();
@@ -259,7 +263,9 @@ void ThreadManager::EagerlyArchiveThread() {
char* to = state->data();
to = HandleScopeImplementer::ArchiveThread(to);
to = Top::ArchiveThread(to);
+#ifdef ENABLE_DEBUGGER_SUPPORT
to = Debug::ArchiveDebug(to);
+#endif
to = StackGuard::ArchiveStackGuard(to);
to = RegExpStack::ArchiveStack(to);
to = Bootstrapper::ArchiveState(to);
@@ -303,13 +309,13 @@ void ThreadManager::MarkCompactEpilogue(bool is_compacting) {
int ThreadManager::CurrentId() {
- return bit_cast<int, void*>(Thread::GetThreadLocal(thread_id_key));
+ return Thread::GetThreadLocalInt(thread_id_key);
}
void ThreadManager::AssignId() {
- if (Thread::GetThreadLocal(thread_id_key) == NULL) {
- Thread::SetThreadLocal(thread_id_key, bit_cast<void*, int>(next_id_++));
+ if (!Thread::HasThreadLocal(thread_id_key)) {
+ Thread::SetThreadLocalInt(thread_id_key, next_id_++);
}
}
diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc
new file mode 100644
index 000000000..0d2840d44
--- /dev/null
+++ b/deps/v8/src/version.cc
@@ -0,0 +1,87 @@
+// Copyright 2008 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 "v8.h"
+
+#include "version.h"
+
+// These macros define the version number for the current version.
+// NOTE these macros are used by the SCons build script so their names
+// cannot be changed without changing the SCons build script.
+#define MAJOR_VERSION 1
+#define MINOR_VERSION 2
+#define BUILD_NUMBER 3
+#define PATCH_LEVEL 0
+#define CANDIDATE_VERSION false
+
+// Define SONAME to have the SCons build the put a specific SONAME into the
+// shared library instead the generic SONAME generated from the V8 version
+// number. This define is mainly used by the SCons build script.
+#define SONAME ""
+
+namespace v8 { namespace internal {
+
+int Version::major_ = MAJOR_VERSION;
+int Version::minor_ = MINOR_VERSION;
+int Version::build_ = BUILD_NUMBER;
+int Version::patch_ = PATCH_LEVEL;
+bool Version::candidate_ = CANDIDATE_VERSION;
+const char* Version::soname_ = SONAME;
+
+
+// Calculate the V8 version string.
+void Version::GetString(Vector<char> str) {
+ const char* candidate = IsCandidate() ? " (candidate)" : "";
+ if (GetPatch() > 0) {
+ OS::SNPrintF(str, "%d.%d.%d.%d%s",
+ GetMajor(), GetMinor(), GetBuild(), GetPatch(), candidate);
+ } else {
+ OS::SNPrintF(str, "%d.%d.%d%s",
+ GetMajor(), GetMinor(), GetBuild(), candidate);
+ }
+}
+
+
+// Calculate the SONAME for the V8 shared library.
+void Version::GetSONAME(Vector<char> str) {
+ if (soname_ == NULL || *soname_ == '\0') {
+ // Generate generic SONAME if no specific SONAME is defined.
+ const char* candidate = IsCandidate() ? "-candidate" : "";
+ if (GetPatch() > 0) {
+ OS::SNPrintF(str, "libv8-%d.%d.%d.%d%s.so",
+ GetMajor(), GetMinor(), GetBuild(), GetPatch(), candidate);
+ } else {
+ OS::SNPrintF(str, "libv8-%d.%d.%d%s.so",
+ GetMajor(), GetMinor(), GetBuild(), candidate);
+ }
+ } else {
+ // Use specific SONAME.
+ OS::SNPrintF(str, "%s", soname_);
+ }
+}
+
+} } // namespace v8::internal
diff --git a/deps/v8/src/version.h b/deps/v8/src/version.h
new file mode 100644
index 000000000..423b5f7a1
--- /dev/null
+++ b/deps/v8/src/version.h
@@ -0,0 +1,63 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_VERSION_H_
+#define V8_VERSION_H_
+
+namespace v8 { namespace internal {
+
+class Version {
+ public:
+ // Return the various version components.
+ static int GetMajor() { return major_; }
+ static int GetMinor() { return minor_; }
+ static int GetBuild() { return build_; }
+ static int GetPatch() { return patch_; }
+ static bool IsCandidate() { return candidate_; }
+
+ // Calculate the V8 version string.
+ static void GetString(Vector<char> str);
+
+ // Calculate the SONAME for the V8 shared library.
+ static void GetSONAME(Vector<char> str);
+
+ private:
+ static int major_;
+ static int minor_;
+ static int build_;
+ static int patch_;
+ static bool candidate_;
+ static const char* soname_;
+
+ // In test-version.cc.
+ friend void SetVersion(int major, int minor, int build, int patch,
+ bool candidate, const char* soname);
+};
+
+} } // namespace v8::internal
+
+#endif // V8_VERSION_H_
diff --git a/deps/v8/src/virtual-frame.cc b/deps/v8/src/virtual-frame.cc
index a03e31a35..566fcdbc0 100644
--- a/deps/v8/src/virtual-frame.cc
+++ b/deps/v8/src/virtual-frame.cc
@@ -213,40 +213,14 @@ void VirtualFrame::SpillElementAt(int index) {
}
-// Clear the dirty bits for the range of elements in
-// [min(stack_pointer_ + 1,begin), end).
-void VirtualFrame::SyncRange(int begin, int end) {
- ASSERT(begin >= 0);
- ASSERT(end <= elements_.length());
- if (begin > stack_pointer_) {
- // Elements between stack_pointer_ + 1 and begin must also be synced.
- for (int i = stack_pointer_ + 1; i < end; i++) {
- SyncElementByPushing(i);
- }
- } else if (end <= stack_pointer_ + 1) {
- for (int i = begin; i < end; i++) {
- if (!elements_[i].is_synced()) {
- SyncElementBelowStackPointer(i);
- }
- }
- } else {
- // Split into two ranges that each satisfy a condition above.
- SyncRange(begin, stack_pointer_ + 1);
- SyncRange(stack_pointer_ + 1, end);
- }
-}
-
-
// Clear the dirty bit for the element at a given index.
void VirtualFrame::SyncElementAt(int index) {
if (index <= stack_pointer_) {
- if (!elements_[index].is_synced()) {
- SyncElementBelowStackPointer(index);
- }
+ if (!elements_[index].is_synced()) SyncElementBelowStackPointer(index);
+ } else if (index == stack_pointer_ + 1) {
+ SyncElementByPushing(index);
} else {
- for (int i = stack_pointer_ + 1; i <= index; i++) {
- SyncElementByPushing(i);
- }
+ SyncRange(stack_pointer_ + 1, index);
}
}
@@ -310,7 +284,7 @@ void VirtualFrame::PrepareForCall(int spilled_args, int dropped_args) {
ASSERT(height() >= spilled_args);
ASSERT(dropped_args <= spilled_args);
- SyncRange(0, elements_.length());
+ SyncRange(0, elements_.length() - 1);
// Spill registers.
for (int i = 0; i < kNumRegisters; i++) {
if (is_used(i)) {
@@ -533,4 +507,14 @@ bool VirtualFrame::Equals(VirtualFrame* other) {
return true;
}
+
+// Specialization of List::ResizeAdd to non-inlined version for FrameElements.
+// The function ResizeAdd becomes a real function, whose implementation is the
+// inlined ResizeAddInternal.
+template <>
+void List<FrameElement,
+ FreeStoreAllocationPolicy>::ResizeAdd(const FrameElement& element) {
+ ResizeAddInternal(element);
+}
+
} } // namespace v8::internal
diff --git a/deps/v8/src/virtual-frame.h b/deps/v8/src/virtual-frame.h
index 99b4f7672..794f1567c 100644
--- a/deps/v8/src/virtual-frame.h
+++ b/deps/v8/src/virtual-frame.h
@@ -191,16 +191,23 @@ class FrameElement BASE_EMBEDDED {
data_.index_ = new_index;
}
+ void set_reg(Register new_reg) {
+ ASSERT(is_register());
+ data_.reg_ = new_reg;
+ }
+
friend class VirtualFrame;
};
} } // namespace v8::internal
-#ifdef ARM
-#include "virtual-frame-arm.h"
-#else // ia32
-#include "virtual-frame-ia32.h"
+#if V8_TARGET_ARCH_IA32
+#include "ia32/virtual-frame-ia32.h"
+#elif V8_TARGET_ARCH_X64
+#include "x64/virtual-frame-x64.h"
+#elif V8_TARGET_ARCH_ARM
+#include "arm/virtual-frame-arm.h"
#endif
#endif // V8_VIRTUAL_FRAME_H_
diff --git a/deps/v8/src/x64/assembler-x64-inl.h b/deps/v8/src/x64/assembler-x64-inl.h
new file mode 100644
index 000000000..0b018490d
--- /dev/null
+++ b/deps/v8/src/x64/assembler-x64-inl.h
@@ -0,0 +1,68 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_X64_ASSEMBLER_X64_INL_H_
+#define V8_X64_ASSEMBLER_X64_INL_H_
+
+namespace v8 { namespace internal {
+
+Condition NegateCondition(Condition cc) {
+ return static_cast<Condition>(cc ^ 1);
+}
+
+
+Address RelocInfo::target_address() {
+ ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
+ return Assembler::target_address_at(pc_);
+}
+
+
+Address RelocInfo::target_address_address() {
+ ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
+ return reinterpret_cast<Address>(pc_);
+}
+
+
+void RelocInfo::set_target_address(Address target) {
+ ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
+ Assembler::set_target_address_at(pc_, target);
+}
+
+
+void Assembler::set_target_address_at(byte* location, byte* value) {
+ UNIMPLEMENTED();
+}
+
+
+byte* Assembler::target_address_at(byte* location) {
+ UNIMPLEMENTED();
+ return NULL;
+}
+
+} } // namespace v8::internal
+
+#endif // V8_X64_ASSEMBLER_X64_INL_H_
diff --git a/deps/v8/src/x64/assembler-x64.cc b/deps/v8/src/x64/assembler-x64.cc
new file mode 100644
index 000000000..6e2c42a12
--- /dev/null
+++ b/deps/v8/src/x64/assembler-x64.cc
@@ -0,0 +1,36 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#include "macro-assembler.h"
+
+namespace v8 { namespace internal {
+
+Register no_reg = { -1 };
+
+} } // namespace v8::internal
diff --git a/deps/v8/src/x64/assembler-x64.h b/deps/v8/src/x64/assembler-x64.h
new file mode 100644
index 000000000..40fcdd32b
--- /dev/null
+++ b/deps/v8/src/x64/assembler-x64.h
@@ -0,0 +1,925 @@
+// Copyright (c) 1994-2006 Sun Microsystems Inc.
+// 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.
+//
+// - Redistribution 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 Sun Microsystems or the names of 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.
+
+// The original source code covered by the above license above has been
+// modified significantly by Google Inc.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
+
+// A lightweight X64 Assembler.
+
+#ifndef V8_X64_ASSEMBLER_X64_H_
+#define V8_X64_ASSEMBLER_X64_H_
+
+namespace v8 { namespace internal {
+
+// CPU Registers.
+//
+// 1) We would prefer to use an enum, but enum values are assignment-
+// compatible with int, which has caused code-generation bugs.
+//
+// 2) We would prefer to use a class instead of a struct but we don't like
+// the register initialization to depend on the particular initialization
+// order (which appears to be different on OS X, Linux, and Windows for the
+// installed versions of C++ we tried). Using a struct permits C-style
+// "initialization". Also, the Register objects cannot be const as this
+// forces initialization stubs in MSVC, making us dependent on initialization
+// order.
+//
+// 3) By not using an enum, we are possibly preventing the compiler from
+// doing certain constant folds, which may significantly reduce the
+// code generated for some assembly instructions (because they boil down
+// to a few constants). If this is a problem, we could change the code
+// such that we use an enum in optimized mode, and the struct in debug
+// mode. This way we get the compile-time error checking in debug mode
+// and best performance in optimized code.
+//
+const int kNumRegisters = 16;
+
+struct Register {
+ bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
+ bool is(Register reg) const { return code_ == reg.code_; }
+ // The byte-register distinction of ai32 has dissapeared.
+ bool is_byte_register() const { return false; }
+ int code() const {
+ ASSERT(is_valid());
+ return code_;
+ }
+ int bit() const {
+ UNIMPLEMENTED();
+ return 0;
+ }
+
+ // (unfortunately we can't make this private in a struct)
+ int code_;
+};
+
+extern Register rax;
+extern Register rcx;
+extern Register rdx;
+extern Register rbx;
+extern Register rsp;
+extern Register rbp;
+extern Register rsi;
+extern Register rdi;
+extern Register r8;
+extern Register r9;
+extern Register r10;
+extern Register r11;
+extern Register r12;
+extern Register r13;
+extern Register r14;
+extern Register r15;
+extern Register no_reg;
+
+
+struct XMMRegister {
+ bool is_valid() const { return 0 <= code_ && code_ < 2; }
+ int code() const {
+ ASSERT(is_valid());
+ return code_;
+ }
+
+ int code_;
+};
+
+extern XMMRegister xmm0;
+extern XMMRegister xmm1;
+extern XMMRegister xmm2;
+extern XMMRegister xmm3;
+extern XMMRegister xmm4;
+extern XMMRegister xmm5;
+extern XMMRegister xmm6;
+extern XMMRegister xmm7;
+
+enum Condition {
+ // any value < 0 is considered no_condition
+ no_condition = -1,
+
+ overflow = 0,
+ no_overflow = 1,
+ below = 2,
+ above_equal = 3,
+ equal = 4,
+ not_equal = 5,
+ below_equal = 6,
+ above = 7,
+ negative = 8,
+ positive = 9,
+ parity_even = 10,
+ parity_odd = 11,
+ less = 12,
+ greater_equal = 13,
+ less_equal = 14,
+ greater = 15,
+
+ // aliases
+ carry = below,
+ not_carry = above_equal,
+ zero = equal,
+ not_zero = not_equal,
+ sign = negative,
+ not_sign = positive
+};
+
+
+// Returns the equivalent of !cc.
+// Negation of the default no_condition (-1) results in a non-default
+// no_condition value (-2). As long as tests for no_condition check
+// for condition < 0, this will work as expected.
+inline Condition NegateCondition(Condition cc);
+
+// Corresponds to transposing the operands of a comparison.
+inline Condition ReverseCondition(Condition cc) {
+ switch (cc) {
+ case below:
+ return above;
+ case above:
+ return below;
+ case above_equal:
+ return below_equal;
+ case below_equal:
+ return above_equal;
+ case less:
+ return greater;
+ case greater:
+ return less;
+ case greater_equal:
+ return less_equal;
+ case less_equal:
+ return greater_equal;
+ default:
+ return cc;
+ };
+}
+
+enum Hint {
+ no_hint = 0,
+ not_taken = 0x2e,
+ taken = 0x3e
+};
+
+// The result of negating a hint is as if the corresponding condition
+// were negated by NegateCondition. That is, no_hint is mapped to
+// itself and not_taken and taken are mapped to each other.
+inline Hint NegateHint(Hint hint) {
+ return (hint == no_hint)
+ ? no_hint
+ : ((hint == not_taken) ? taken : not_taken);
+}
+
+
+// -----------------------------------------------------------------------------
+// Machine instruction Immediates
+
+class Immediate BASE_EMBEDDED {
+ public:
+ inline explicit Immediate(int64_t x);
+ inline explicit Immediate(const char* s);
+ inline explicit Immediate(const ExternalReference& ext);
+ inline explicit Immediate(Handle<Object> handle);
+ inline explicit Immediate(Smi* value);
+
+ static Immediate CodeRelativeOffset(Label* label) {
+ return Immediate(label);
+ }
+
+ bool is_zero() const { return x_ == 0 && rmode_ == RelocInfo::NONE; }
+ bool is_int8() const {
+ return -128 <= x_ && x_ < 128 && rmode_ == RelocInfo::NONE;
+ }
+ bool is_int16() const {
+ return -32768 <= x_ && x_ < 32768 && rmode_ == RelocInfo::NONE;
+ }
+ bool is_int32() const {
+ return V8_INT64_C(-2147483648) <= x_
+ && x_ < V8_INT64_C(2147483648)
+ && rmode_ == RelocInfo::NONE;
+ }
+
+ private:
+ inline explicit Immediate(Label* value) { UNIMPLEMENTED(); }
+
+ int64_t x_;
+ RelocInfo::Mode rmode_;
+
+ friend class Assembler;
+};
+
+
+// -----------------------------------------------------------------------------
+// Machine instruction Operands
+
+enum ScaleFactor {
+ times_1 = 0,
+ times_2 = 1,
+ times_4 = 2,
+ times_8 = 3
+};
+
+
+class Operand BASE_EMBEDDED {
+ public:
+ // reg
+ INLINE(explicit Operand(Register reg));
+
+ // MemoryOperand
+ INLINE(explicit Operand()) { UNIMPLEMENTED(); }
+
+ // Returns true if this Operand is a wrapper for the specified register.
+ bool is_reg(Register reg) const;
+
+ // These constructors have been moved to MemOperand, and should
+ // be removed from Operand as soon as all their uses use MemOperands instead.
+ // [disp/r]
+ INLINE(explicit Operand(intptr_t disp, RelocInfo::Mode rmode)) {
+ UNIMPLEMENTED();
+ }
+ // disp only must always be relocated
+
+ // [base + disp/r]
+ explicit Operand(Register base, intptr_t disp,
+ RelocInfo::Mode rmode = RelocInfo::NONE);
+
+ // [base + index*scale + disp/r]
+ explicit Operand(Register base,
+ Register index,
+ ScaleFactor scale,
+ intptr_t disp,
+ RelocInfo::Mode rmode = RelocInfo::NONE);
+
+ // [index*scale + disp/r]
+ explicit Operand(Register index,
+ ScaleFactor scale,
+ intptr_t disp,
+ RelocInfo::Mode rmode = RelocInfo::NONE);
+
+ static Operand StaticVariable(const ExternalReference& ext) {
+ return Operand(reinterpret_cast<intptr_t>(ext.address()),
+ RelocInfo::EXTERNAL_REFERENCE);
+ }
+
+ static Operand StaticArray(Register index,
+ ScaleFactor scale,
+ const ExternalReference& arr) {
+ return Operand(index, scale, reinterpret_cast<intptr_t>(arr.address()),
+ RelocInfo::EXTERNAL_REFERENCE);
+ }
+
+ // End of constructors and methods that have been moved to MemOperand.
+
+ private:
+ byte rex_;
+ byte buf_[10];
+ // The number of bytes in buf_.
+ unsigned int len_;
+ // Only valid if len_ > 4.
+ RelocInfo::Mode rmode_;
+
+ // Set the ModRM byte without an encoded 'reg' register. The
+ // register is encoded later as part of the emit_operand operation.
+ inline void set_modrm(int mod, Register rm);
+
+ inline void set_sib(ScaleFactor scale, Register index, Register base);
+ inline void set_disp8(int8_t disp);
+ inline void set_disp32(int32_t disp);
+ inline void set_dispr(intptr_t disp, RelocInfo::Mode rmode);
+
+ friend class Assembler;
+};
+
+class MemOperand : public Operand {
+ public:
+ // [disp/r]
+ INLINE(explicit MemOperand(intptr_t disp, RelocInfo::Mode rmode)) :
+ Operand() {
+ UNIMPLEMENTED();
+ }
+ // disp only must always be relocated
+
+ // [base + disp/r]
+ explicit MemOperand(Register base, intptr_t disp,
+ RelocInfo::Mode rmode = RelocInfo::NONE);
+
+ // [base + index*scale + disp/r]
+ explicit MemOperand(Register base,
+ Register index,
+ ScaleFactor scale,
+ intptr_t disp,
+ RelocInfo::Mode rmode = RelocInfo::NONE);
+
+ // [index*scale + disp/r]
+ explicit MemOperand(Register index,
+ ScaleFactor scale,
+ intptr_t disp,
+ RelocInfo::Mode rmode = RelocInfo::NONE);
+
+ static MemOperand StaticVariable(const ExternalReference& ext) {
+ return MemOperand(reinterpret_cast<intptr_t>(ext.address()),
+ RelocInfo::EXTERNAL_REFERENCE);
+ }
+
+ static MemOperand StaticArray(Register index,
+ ScaleFactor scale,
+ const ExternalReference& arr) {
+ return MemOperand(index, scale, reinterpret_cast<intptr_t>(arr.address()),
+ RelocInfo::EXTERNAL_REFERENCE);
+ }
+};
+
+// -----------------------------------------------------------------------------
+// A Displacement describes the 32bit immediate field of an instruction which
+// may be used together with a Label in order to refer to a yet unknown code
+// position. Displacements stored in the instruction stream are used to describe
+// the instruction and to chain a list of instructions using the same Label.
+// A Displacement contains 2 different fields:
+//
+// next field: position of next displacement in the chain (0 = end of list)
+// type field: instruction type
+//
+// A next value of null (0) indicates the end of a chain (note that there can
+// be no displacement at position zero, because there is always at least one
+// instruction byte before the displacement).
+//
+// Displacement _data field layout
+//
+// |31.....2|1......0|
+// [ next | type |
+
+class Displacement BASE_EMBEDDED {
+ public:
+ enum Type {
+ UNCONDITIONAL_JUMP,
+ CODE_RELATIVE,
+ OTHER
+ };
+
+ int data() const { return data_; }
+ Type type() const { return TypeField::decode(data_); }
+ void next(Label* L) const {
+ int n = NextField::decode(data_);
+ n > 0 ? L->link_to(n) : L->Unuse();
+ }
+ void link_to(Label* L) { init(L, type()); }
+
+ explicit Displacement(int data) { data_ = data; }
+
+ Displacement(Label* L, Type type) { init(L, type); }
+
+ void print() {
+ PrintF("%s (%x) ", (type() == UNCONDITIONAL_JUMP ? "jmp" : "[other]"),
+ NextField::decode(data_));
+ }
+
+ private:
+ int data_;
+
+ class TypeField: public BitField<Type, 0, 2> {};
+ class NextField: public BitField<int, 2, 32-2> {};
+
+ void init(Label* L, Type type);
+};
+
+
+
+// CpuFeatures keeps track of which features are supported by the target CPU.
+// Supported features must be enabled by a Scope before use.
+// Example:
+// if (CpuFeatures::IsSupported(SSE2)) {
+// CpuFeatures::Scope fscope(SSE2);
+// // Generate SSE2 floating point code.
+// } else {
+// // Generate standard x87 floating point code.
+// }
+class CpuFeatures : public AllStatic {
+ public:
+ // Feature flags bit positions. They are mostly based on the CPUID spec.
+ // (We assign CPUID itself to one of the currently reserved bits --
+ // feel free to change this if needed.)
+ enum Feature { SSE3 = 32, SSE2 = 26, CMOV = 15, RDTSC = 4, CPUID = 10 };
+ // Detect features of the target CPU. Set safe defaults if the serializer
+ // is enabled (snapshots must be portable).
+ static void Probe();
+ // Check whether a feature is supported by the target CPU.
+ static bool IsSupported(Feature f) {
+ return (supported_ & (static_cast<uint64_t>(1) << f)) != 0;
+ }
+ // Check whether a feature is currently enabled.
+ static bool IsEnabled(Feature f) {
+ return (enabled_ & (static_cast<uint64_t>(1) << f)) != 0;
+ }
+ // Enable a specified feature within a scope.
+ class Scope BASE_EMBEDDED {
+#ifdef DEBUG
+ public:
+ explicit Scope(Feature f) {
+ ASSERT(CpuFeatures::IsSupported(f));
+ old_enabled_ = CpuFeatures::enabled_;
+ CpuFeatures::enabled_ |= (static_cast<uint64_t>(1) << f);
+ }
+ ~Scope() { CpuFeatures::enabled_ = old_enabled_; }
+ private:
+ uint64_t old_enabled_;
+#else
+ public:
+ explicit Scope(Feature f) {}
+#endif
+ };
+ private:
+ static uint64_t supported_;
+ static uint64_t enabled_;
+};
+
+
+class Assembler : public Malloced {
+ private:
+ // The relocation writer's position is kGap bytes below the end of
+ // the generated instructions. This leaves enough space for the
+ // longest possible ia32 instruction (17 bytes as of 9/26/06) and
+ // allows for a single, fast space check per instruction.
+ static const int kGap = 32;
+
+ public:
+ // Create an assembler. Instructions and relocation information are emitted
+ // into a buffer, with the instructions starting from the beginning and the
+ // relocation information starting from the end of the buffer. See CodeDesc
+ // for a detailed comment on the layout (globals.h).
+ //
+ // If the provided buffer is NULL, the assembler allocates and grows its own
+ // buffer, and buffer_size determines the initial buffer size. The buffer is
+ // owned by the assembler and deallocated upon destruction of the assembler.
+ //
+ // If the provided buffer is not NULL, the assembler uses the provided buffer
+ // for code generation and assumes its size to be buffer_size. If the buffer
+ // is too small, a fatal error occurs. No deallocation of the buffer is done
+ // upon destruction of the assembler.
+ Assembler(void* buffer, int buffer_size);
+ ~Assembler();
+
+ // GetCode emits any pending (non-emitted) code and fills the descriptor
+ // desc. GetCode() is idempotent; it returns the same result if no other
+ // Assembler functions are invoked in between GetCode() calls.
+ void GetCode(CodeDesc* desc);
+
+ // Read/Modify the code target in the branch/call instruction at pc.
+ inline static Address target_address_at(Address pc);
+ inline static void set_target_address_at(Address pc, Address target);
+
+ // Distance between the address of the code target in the call instruction
+ // and the return address
+ static const int kTargetAddrToReturnAddrDist = kPointerSize;
+
+
+ // ---------------------------------------------------------------------------
+ // Code generation
+ //
+ // - function names correspond one-to-one to ia32 instruction mnemonics
+ // - unless specified otherwise, instructions operate on 32bit operands
+ // - instructions on 8bit (byte) operands/registers have a trailing '_b'
+ // - instructions on 16bit (word) operands/registers have a trailing '_w'
+ // - naming conflicts with C++ keywords are resolved via a trailing '_'
+
+ // NOTE ON INTERFACE: Currently, the interface is not very consistent
+ // in the sense that some operations (e.g. mov()) can be called in more
+ // the one way to generate the same instruction: The Register argument
+ // can in some cases be replaced with an Operand(Register) argument.
+ // This should be cleaned up and made more orthogonal. The questions
+ // is: should we always use Operands instead of Registers where an
+ // Operand is possible, or should we have a Register (overloaded) form
+ // instead? We must be careful to make sure that the selected instruction
+ // is obvious from the parameters to avoid hard-to-find code generation
+ // bugs.
+
+ // Insert the smallest number of nop instructions
+ // possible to align the pc offset to a multiple
+ // of m. m must be a power of 2.
+ void Align(int m);
+
+ // Stack
+ void pushad();
+ void popad();
+
+ void pushfd();
+ void popfd();
+
+ void push(const Immediate& x);
+ void push(Register src);
+ void push(const Operand& src);
+ void push(Label* label, RelocInfo::Mode relocation_mode);
+
+ void pop(Register dst);
+ void pop(const Operand& dst);
+
+ void enter(const Immediate& size);
+ void leave();
+
+ // Moves
+ void mov_b(Register dst, const Operand& src);
+ void mov_b(const Operand& dst, int8_t imm8);
+ void mov_b(const Operand& dst, Register src);
+
+ void mov_w(Register dst, const Operand& src);
+ void mov_w(const Operand& dst, Register src);
+
+ void mov(Register dst, int32_t imm32);
+ void mov(Register dst, const Immediate& x);
+ void mov(Register dst, Handle<Object> handle);
+ void mov(Register dst, const Operand& src);
+ void mov(Register dst, Register src);
+ void mov(const Operand& dst, const Immediate& x);
+ void mov(const Operand& dst, Handle<Object> handle);
+ void mov(const Operand& dst, Register src);
+
+ void movsx_b(Register dst, const Operand& src);
+
+ void movsx_w(Register dst, const Operand& src);
+
+ void movzx_b(Register dst, const Operand& src);
+
+ void movzx_w(Register dst, const Operand& src);
+
+ // Conditional moves
+ void cmov(Condition cc, Register dst, int32_t imm32);
+ void cmov(Condition cc, Register dst, Handle<Object> handle);
+ void cmov(Condition cc, Register dst, const Operand& src);
+
+ // Exchange two registers
+ void xchg(Register dst, Register src);
+
+ // Arithmetics
+ void adc(Register dst, int32_t imm32);
+ void adc(Register dst, const Operand& src);
+
+ void add(Register dst, const Operand& src);
+ void add(const Operand& dst, const Immediate& x);
+
+ void and_(Register dst, int32_t imm32);
+ void and_(Register dst, const Operand& src);
+ void and_(const Operand& src, Register dst);
+ void and_(const Operand& dst, const Immediate& x);
+
+ void cmpb(const Operand& op, int8_t imm8);
+ void cmpb_al(const Operand& op);
+ void cmpw_ax(const Operand& op);
+ void cmpw(const Operand& op, Immediate imm16);
+ void cmp(Register reg, int32_t imm32);
+ void cmp(Register reg, Handle<Object> handle);
+ void cmp(Register reg, const Operand& op);
+ void cmp(const Operand& op, const Immediate& imm);
+
+ void dec_b(Register dst);
+
+ void dec(Register dst);
+ void dec(const Operand& dst);
+
+ void cdq();
+
+ void idiv(Register src);
+
+ void imul(Register dst, const Operand& src);
+ void imul(Register dst, Register src, int32_t imm32);
+
+ void inc(Register dst);
+ void inc(const Operand& dst);
+
+ void lea(Register dst, const Operand& src);
+
+ void mul(Register src);
+
+ void neg(Register dst);
+
+ void not_(Register dst);
+
+ void or_(Register dst, int32_t imm32);
+ void or_(Register dst, const Operand& src);
+ void or_(const Operand& dst, Register src);
+ void or_(const Operand& dst, const Immediate& x);
+
+ void rcl(Register dst, uint8_t imm8);
+
+ void sar(Register dst, uint8_t imm8);
+ void sar(Register dst);
+
+ void sbb(Register dst, const Operand& src);
+
+ void shld(Register dst, const Operand& src);
+
+ void shl(Register dst, uint8_t imm8);
+ void shl(Register dst);
+
+ void shrd(Register dst, const Operand& src);
+
+ void shr(Register dst, uint8_t imm8);
+ void shr(Register dst);
+ void shr_cl(Register dst);
+
+ void sub(const Operand& dst, const Immediate& x);
+ void sub(Register dst, const Operand& src);
+ void sub(const Operand& dst, Register src);
+
+ void test(Register reg, const Immediate& imm);
+ void test(Register reg, const Operand& op);
+ void test(const Operand& op, const Immediate& imm);
+
+ void xor_(Register dst, int32_t imm32);
+ void xor_(Register dst, const Operand& src);
+ void xor_(const Operand& src, Register dst);
+ void xor_(const Operand& dst, const Immediate& x);
+
+ // Bit operations.
+ void bt(const Operand& dst, Register src);
+ void bts(const Operand& dst, Register src);
+
+ // Miscellaneous
+ void hlt();
+ void int3();
+ void nop();
+ void rdtsc();
+ void ret(int imm16);
+
+ // Label operations & relative jumps (PPUM Appendix D)
+ //
+ // Takes a branch opcode (cc) and a label (L) and generates
+ // either a backward branch or a forward branch and links it
+ // to the label fixup chain. Usage:
+ //
+ // Label L; // unbound label
+ // j(cc, &L); // forward branch to unbound label
+ // bind(&L); // bind label to the current pc
+ // j(cc, &L); // backward branch to bound label
+ // bind(&L); // illegal: a label may be bound only once
+ //
+ // Note: The same Label can be used for forward and backward branches
+ // but it may be bound only once.
+
+ void bind(Label* L); // binds an unbound label L to the current code position
+
+ // Calls
+ void call(Label* L);
+ void call(byte* entry, RelocInfo::Mode rmode);
+ void call(const Operand& adr);
+ void call(Handle<Code> code, RelocInfo::Mode rmode);
+
+ // Jumps
+ void jmp(Label* L); // unconditional jump to L
+ void jmp(byte* entry, RelocInfo::Mode rmode);
+ void jmp(const Operand& adr);
+ void jmp(Handle<Code> code, RelocInfo::Mode rmode);
+
+ // Conditional jumps
+ void j(Condition cc, Label* L, Hint hint = no_hint);
+ void j(Condition cc, byte* entry, RelocInfo::Mode rmode, Hint hint = no_hint);
+ void j(Condition cc, Handle<Code> code, Hint hint = no_hint);
+
+ // Floating-point operations
+ void fld(int i);
+
+ void fld1();
+ void fldz();
+
+ void fld_s(const Operand& adr);
+ void fld_d(const Operand& adr);
+
+ void fstp_s(const Operand& adr);
+ void fstp_d(const Operand& adr);
+
+ void fild_s(const Operand& adr);
+ void fild_d(const Operand& adr);
+
+ void fist_s(const Operand& adr);
+
+ void fistp_s(const Operand& adr);
+ void fistp_d(const Operand& adr);
+
+ void fisttp_s(const Operand& adr);
+
+ void fabs();
+ void fchs();
+
+ void fadd(int i);
+ void fsub(int i);
+ void fmul(int i);
+ void fdiv(int i);
+
+ void fisub_s(const Operand& adr);
+
+ void faddp(int i = 1);
+ void fsubp(int i = 1);
+ void fsubrp(int i = 1);
+ void fmulp(int i = 1);
+ void fdivp(int i = 1);
+ void fprem();
+ void fprem1();
+
+ void fxch(int i = 1);
+ void fincstp();
+ void ffree(int i = 0);
+
+ void ftst();
+ void fucomp(int i);
+ void fucompp();
+ void fcompp();
+ void fnstsw_ax();
+ void fwait();
+ void fnclex();
+
+ void frndint();
+
+ void sahf();
+ void setcc(Condition cc, Register reg);
+
+ void cpuid();
+
+ // SSE2 instructions
+ void cvttss2si(Register dst, const Operand& src);
+ void cvttsd2si(Register dst, const Operand& src);
+
+ void cvtsi2sd(XMMRegister dst, const Operand& src);
+
+ void addsd(XMMRegister dst, XMMRegister src);
+ void subsd(XMMRegister dst, XMMRegister src);
+ void mulsd(XMMRegister dst, XMMRegister src);
+ void divsd(XMMRegister dst, XMMRegister src);
+
+ // Use either movsd or movlpd.
+ void movdbl(XMMRegister dst, const Operand& src);
+ void movdbl(const Operand& dst, XMMRegister src);
+
+ // Debugging
+ void Print();
+
+ // Check the code size generated from label to here.
+ int SizeOfCodeGeneratedSince(Label* l) { return pc_offset() - l->pos(); }
+
+ // Mark address of the ExitJSFrame code.
+ void RecordJSReturn();
+
+ // Record a comment relocation entry that can be used by a disassembler.
+ // Use --debug_code to enable.
+ void RecordComment(const char* msg);
+
+ void RecordPosition(int pos);
+ void RecordStatementPosition(int pos);
+ void WriteRecordedPositions();
+
+ // Writes a single word of data in the code stream.
+ // Used for inline tables, e.g., jump-tables.
+ void dd(uint32_t data, RelocInfo::Mode reloc_info);
+
+ // Writes the absolute address of a bound label at the given position in
+ // the generated code. That positions should have the relocation mode
+ // internal_reference!
+ void WriteInternalReference(int position, const Label& bound_label);
+
+ int pc_offset() const { return pc_ - buffer_; }
+ int current_statement_position() const { return current_statement_position_; }
+ int current_position() const { return current_position_; }
+
+ // Check if there is less than kGap bytes available in the buffer.
+ // If this is the case, we need to grow the buffer before emitting
+ // an instruction or relocation information.
+ inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; }
+
+ // Get the number of bytes available in the buffer.
+ inline int available_space() const { return reloc_info_writer.pos() - pc_; }
+
+ // Avoid overflows for displacements etc.
+ static const int kMaximalBufferSize = 512*MB;
+ static const int kMinimalBufferSize = 4*KB;
+
+ protected:
+ void movsd(XMMRegister dst, const Operand& src);
+ void movsd(const Operand& dst, XMMRegister src);
+
+ void emit_sse_operand(XMMRegister reg, const Operand& adr);
+ void emit_sse_operand(XMMRegister dst, XMMRegister src);
+
+
+ private:
+ byte* addr_at(int pos) { return buffer_ + pos; }
+ byte byte_at(int pos) { return buffer_[pos]; }
+ uint32_t long_at(int pos) {
+ return *reinterpret_cast<uint32_t*>(addr_at(pos));
+ }
+ void long_at_put(int pos, uint32_t x) {
+ *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
+ }
+
+ // code emission
+ void GrowBuffer();
+ inline void emit(uint32_t x);
+ inline void emit(Handle<Object> handle);
+ inline void emit(uint32_t x, RelocInfo::Mode rmode);
+ inline void emit(const Immediate& x);
+ inline void emit_w(const Immediate& x);
+
+ // Emit the code-object-relative offset of the label's position
+ inline void emit_code_relative_offset(Label* label);
+
+ // instruction generation
+ void emit_arith_b(int op1, int op2, Register dst, int imm8);
+
+ // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81)
+ // with a given destination expression and an immediate operand. It attempts
+ // to use the shortest encoding possible.
+ // sel specifies the /n in the modrm byte (see the Intel PRM).
+ void emit_arith(int sel, Operand dst, const Immediate& x);
+
+ void emit_operand(Register reg, const Operand& adr);
+
+ void emit_farith(int b1, int b2, int i);
+
+ // labels
+ void print(Label* L);
+ void bind_to(Label* L, int pos);
+ void link_to(Label* L, Label* appendix);
+
+ // displacements
+ inline Displacement disp_at(Label* L);
+ inline void disp_at_put(Label* L, Displacement disp);
+ inline void emit_disp(Label* L, Displacement::Type type);
+
+ // record reloc info for current pc_
+ void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
+
+ friend class CodePatcher;
+ friend class EnsureSpace;
+
+ // Code buffer:
+ // The buffer into which code and relocation info are generated.
+ byte* buffer_;
+ int buffer_size_;
+ // True if the assembler owns the buffer, false if buffer is external.
+ bool own_buffer_;
+
+ // code generation
+ byte* pc_; // the program counter; moves forward
+ RelocInfoWriter reloc_info_writer;
+
+ // push-pop elimination
+ byte* last_pc_;
+
+ // source position information
+ int current_statement_position_;
+ int current_position_;
+ int written_statement_position_;
+ int written_position_;
+};
+
+
+// Helper class that ensures that there is enough space for generating
+// instructions and relocation information. The constructor makes
+// sure that there is enough space and (in debug mode) the destructor
+// checks that we did not generate too much.
+class EnsureSpace BASE_EMBEDDED {
+ public:
+ explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
+ if (assembler_->overflow()) assembler_->GrowBuffer();
+#ifdef DEBUG
+ space_before_ = assembler_->available_space();
+#endif
+ }
+
+#ifdef DEBUG
+ ~EnsureSpace() {
+ int bytes_generated = space_before_ - assembler_->available_space();
+ ASSERT(bytes_generated < assembler_->kGap);
+ }
+#endif
+
+ private:
+ Assembler* assembler_;
+#ifdef DEBUG
+ int space_before_;
+#endif
+};
+
+} } // namespace v8::internal
+
+#endif // V8_X64_ASSEMBLER_X64_H_
diff --git a/deps/v8/src/x64/builtins-x64.cc b/deps/v8/src/x64/builtins-x64.cc
new file mode 100644
index 000000000..209aa2d30
--- /dev/null
+++ b/deps/v8/src/x64/builtins-x64.cc
@@ -0,0 +1,27 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/deps/v8/src/x64/codegen-x64.cc b/deps/v8/src/x64/codegen-x64.cc
new file mode 100644
index 000000000..209aa2d30
--- /dev/null
+++ b/deps/v8/src/x64/codegen-x64.cc
@@ -0,0 +1,27 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/deps/v8/src/codegen-ia32.h b/deps/v8/src/x64/codegen-x64.h
index 24a57a074..4acb0cb7f 100644
--- a/deps/v8/src/codegen-ia32.h
+++ b/deps/v8/src/x64/codegen-x64.h
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -25,8 +25,8 @@
// (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_CODEGEN_IA32_H_
-#define V8_CODEGEN_IA32_H_
+#ifndef V8_X64_CODEGEN_X64_H_
+#define V8_X64_CODEGEN_X64_H_
namespace v8 { namespace internal {
@@ -35,9 +35,6 @@ class DeferredCode;
class RegisterAllocator;
class RegisterFile;
-// Mode to overwrite BinaryExpression values.
-enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
-
enum InitState { CONST_INIT, NOT_CONST_INIT };
enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
@@ -393,7 +390,7 @@ class CodeGenerator: public AstVisitor {
// Expressions
Operand GlobalObject() const {
- return ContextOperand(esi, Context::GLOBAL_INDEX);
+ return ContextOperand(rsi, Context::GLOBAL_INDEX);
}
void LoadCondition(Expression* x,
@@ -435,7 +432,7 @@ class CodeGenerator: public AstVisitor {
void GenericBinaryOperation(
Token::Value op,
SmiAnalysis* type,
- const OverwriteMode overwrite_mode = NO_OVERWRITE);
+ OverwriteMode overwrite_mode);
// If possible, combine two constant smi values using op to produce
// a smi result, and push it on the virtual frame, all at compile time.
@@ -618,4 +615,4 @@ class CodeGenerator: public AstVisitor {
} } // namespace v8::internal
-#endif // V8_CODEGEN_IA32_H_
+#endif // V8_X64_CODEGEN_X64_H_
diff --git a/deps/v8/src/x64/cpu-x64.cc b/deps/v8/src/x64/cpu-x64.cc
new file mode 100644
index 000000000..209aa2d30
--- /dev/null
+++ b/deps/v8/src/x64/cpu-x64.cc
@@ -0,0 +1,27 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/deps/v8/src/x64/debug-x64.cc b/deps/v8/src/x64/debug-x64.cc
new file mode 100644
index 000000000..209aa2d30
--- /dev/null
+++ b/deps/v8/src/x64/debug-x64.cc
@@ -0,0 +1,27 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/deps/v8/src/x64/disasm-x64.cc b/deps/v8/src/x64/disasm-x64.cc
new file mode 100644
index 000000000..209aa2d30
--- /dev/null
+++ b/deps/v8/src/x64/disasm-x64.cc
@@ -0,0 +1,27 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/deps/v8/src/x64/frames-x64.cc b/deps/v8/src/x64/frames-x64.cc
new file mode 100644
index 000000000..209aa2d30
--- /dev/null
+++ b/deps/v8/src/x64/frames-x64.cc
@@ -0,0 +1,27 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/deps/v8/src/x64/frames-x64.h b/deps/v8/src/x64/frames-x64.h
new file mode 100644
index 000000000..f4468f6a2
--- /dev/null
+++ b/deps/v8/src/x64/frames-x64.h
@@ -0,0 +1,121 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_X64_FRAMES_X64_H_
+#define V8_X64_FRAMES_X64_H_
+
+namespace v8 { namespace internal {
+
+// TODO(x64): This is a stub, mostly just a copy of the ia32 bit version.
+// This will all need to change to be correct for x64.
+
+static const int kNumRegs = 8;
+static const RegList kJSCallerSaved = 0;
+static const int kNumJSCallerSaved = 5;
+typedef Object* JSCallerSavedBuffer[kNumJSCallerSaved];
+
+class StackHandlerConstants : public AllStatic {
+ public:
+ static const int kNextOffset = -1 * kPointerSize;
+ static const int kPPOffset = -1 * kPointerSize;
+ static const int kFPOffset = -1 * kPointerSize;
+
+ static const int kCodeOffset = -1 * kPointerSize;
+
+ static const int kStateOffset = -1 * kPointerSize;
+ static const int kPCOffset = -1 * kPointerSize;
+
+ static const int kAddressDisplacement = -1 * kPointerSize;
+ static const int kSize = kPCOffset + kPointerSize;
+};
+
+
+class EntryFrameConstants : public AllStatic {
+ public:
+ static const int kCallerFPOffset = -1 * kPointerSize;
+
+ static const int kFunctionArgOffset = -1 * kPointerSize;
+ static const int kReceiverArgOffset = -1 * kPointerSize;
+ static const int kArgcOffset = -1 * kPointerSize;
+ static const int kArgvOffset = -1 * kPointerSize;
+};
+
+
+class ExitFrameConstants : public AllStatic {
+ public:
+ static const int kDebugMarkOffset = -1 * kPointerSize;
+ static const int kSPOffset = -1 * kPointerSize;
+
+ static const int kPPDisplacement = -1 * kPointerSize;
+
+ static const int kCallerFPOffset = -1 * kPointerSize;
+ static const int kCallerPCOffset = -1 * kPointerSize;
+};
+
+
+class StandardFrameConstants : public AllStatic {
+ public:
+ static const int kExpressionsOffset = -1 * kPointerSize;
+ static const int kMarkerOffset = -1 * kPointerSize;
+ static const int kContextOffset = -1 * kPointerSize;
+ static const int kCallerFPOffset = -1 * kPointerSize;
+ static const int kCallerPCOffset = -1 * kPointerSize;
+ static const int kCallerSPOffset = -1 * kPointerSize;
+};
+
+
+class JavaScriptFrameConstants : public AllStatic {
+ public:
+ static const int kLocal0Offset = StandardFrameConstants::kExpressionsOffset;
+ static const int kSavedRegistersOffset = -1 * kPointerSize;
+ static const int kFunctionOffset = StandardFrameConstants::kMarkerOffset;
+
+ static const int kParam0Offset = -1 * kPointerSize;
+ static const int kReceiverOffset = -1 * kPointerSize;
+};
+
+
+class ArgumentsAdaptorFrameConstants : public AllStatic {
+ public:
+ static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
+};
+
+
+class InternalFrameConstants : public AllStatic {
+ public:
+ static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
+};
+
+
+inline Object* JavaScriptFrame::function_slot_object() const {
+ const int offset = JavaScriptFrameConstants::kFunctionOffset;
+ return Memory::Object_at(fp() + offset);
+}
+
+} } // namespace v8::internal
+
+#endif // V8_X64_FRAMES_X64_H_
diff --git a/deps/v8/src/x64/ic-x64.cc b/deps/v8/src/x64/ic-x64.cc
new file mode 100644
index 000000000..209aa2d30
--- /dev/null
+++ b/deps/v8/src/x64/ic-x64.cc
@@ -0,0 +1,27 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/deps/v8/src/x64/jump-target-x64.cc b/deps/v8/src/x64/jump-target-x64.cc
new file mode 100644
index 000000000..209aa2d30
--- /dev/null
+++ b/deps/v8/src/x64/jump-target-x64.cc
@@ -0,0 +1,27 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/deps/v8/src/x64/macro-assembler-x64.cc b/deps/v8/src/x64/macro-assembler-x64.cc
new file mode 100644
index 000000000..209aa2d30
--- /dev/null
+++ b/deps/v8/src/x64/macro-assembler-x64.cc
@@ -0,0 +1,27 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/deps/v8/src/macro-assembler-ia32.h b/deps/v8/src/x64/macro-assembler-x64.h
index 40aa84a0a..159d0c4f3 100644
--- a/deps/v8/src/macro-assembler-ia32.h
+++ b/deps/v8/src/x64/macro-assembler-x64.h
@@ -25,8 +25,8 @@
// (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_MACRO_ASSEMBLER_IA32_H_
-#define V8_MACRO_ASSEMBLER_IA32_H_
+#ifndef V8_X64_MACRO_ASSEMBLER_X64_H_
+#define V8_X64_MACRO_ASSEMBLER_X64_H_
#include "assembler.h"
@@ -73,7 +73,7 @@ class MacroAssembler: public Assembler {
Register value,
Register scratch);
-
+#ifdef ENABLE_DEBUGGER_SUPPORT
// ---------------------------------------------------------------------------
// Debugger Support
@@ -84,7 +84,7 @@ class MacroAssembler: public Assembler {
void CopyRegistersFromStackToMemory(Register base,
Register scratch,
RegList regs);
-
+#endif
// ---------------------------------------------------------------------------
// Activation frames
@@ -343,6 +343,29 @@ static inline Operand FieldOperand(Register object,
return Operand(object, index, scale, offset - kHeapObjectTag);
}
+
+#ifdef GENERATED_CODE_COVERAGE
+extern void LogGeneratedCodeCoverage(const char* file_line);
+#define CODE_COVERAGE_STRINGIFY(x) #x
+#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
+#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
+#define ACCESS_MASM(masm) { \
+ byte* x64_coverage_function = \
+ reinterpret_cast<byte*>(FUNCTION_ADDR(LogGeneratedCodeCoverage)); \
+ masm->pushfd(); \
+ masm->pushad(); \
+ masm->push(Immediate(reinterpret_cast<int>(&__FILE_LINE__))); \
+ masm->call(x64_coverage_function, RelocInfo::RUNTIME_ENTRY); \
+ masm->pop(rax); \
+ masm->popad(); \
+ masm->popfd(); \
+ } \
+ masm->
+#else
+#define ACCESS_MASM(masm) masm->
+#endif
+
+
} } // namespace v8::internal
-#endif // V8_MACRO_ASSEMBLER_IA32_H_
+#endif // V8_X64_MACRO_ASSEMBLER_X64_H_
diff --git a/deps/v8/src/x64/regexp-macro-assembler-x64.cc b/deps/v8/src/x64/regexp-macro-assembler-x64.cc
new file mode 100644
index 000000000..209aa2d30
--- /dev/null
+++ b/deps/v8/src/x64/regexp-macro-assembler-x64.cc
@@ -0,0 +1,27 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/deps/v8/src/x64/regexp-macro-assembler-x64.h b/deps/v8/src/x64/regexp-macro-assembler-x64.h
new file mode 100644
index 000000000..209aa2d30
--- /dev/null
+++ b/deps/v8/src/x64/regexp-macro-assembler-x64.h
@@ -0,0 +1,27 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/deps/v8/src/x64/register-allocator-x64.cc b/deps/v8/src/x64/register-allocator-x64.cc
new file mode 100644
index 000000000..209aa2d30
--- /dev/null
+++ b/deps/v8/src/x64/register-allocator-x64.cc
@@ -0,0 +1,27 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/deps/v8/src/x64/simulator-x64.cc b/deps/v8/src/x64/simulator-x64.cc
new file mode 100644
index 000000000..209aa2d30
--- /dev/null
+++ b/deps/v8/src/x64/simulator-x64.cc
@@ -0,0 +1,27 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/deps/v8/src/x64/simulator-x64.h b/deps/v8/src/x64/simulator-x64.h
new file mode 100644
index 000000000..8160e5364
--- /dev/null
+++ b/deps/v8/src/x64/simulator-x64.h
@@ -0,0 +1,47 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_X64_SIMULATOR_X64_H_
+#define V8_X64_SIMULATOR_X64_H_
+
+
+// Since there is no simulator for the ia32 architecture the only thing we can
+// do is to call the entry directly.
+#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
+ entry(p0, p1, p2, p3, p4);
+
+// Calculated the stack limit beyond which we will throw stack overflow errors.
+// This macro must be called from a C++ method. It relies on being able to take
+// the address of "this" to get a value on the current execution stack and then
+// calculates the stack limit based on that value.
+// NOTE: The check for overflow is not safe as there is no guarantee that the
+// running thread has its stack in all memory up to address 0x00000000.
+#define GENERATED_CODE_STACK_LIMIT(limit) \
+ (reinterpret_cast<uintptr_t>(this) >= limit ? \
+ reinterpret_cast<uintptr_t>(this) - limit : 0)
+
+#endif // V8_X64_SIMULATOR_X64_H_
diff --git a/deps/v8/src/x64/stub-cache-x64.cc b/deps/v8/src/x64/stub-cache-x64.cc
new file mode 100644
index 000000000..209aa2d30
--- /dev/null
+++ b/deps/v8/src/x64/stub-cache-x64.cc
@@ -0,0 +1,27 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/deps/v8/src/x64/virtual-frame-x64.cc b/deps/v8/src/x64/virtual-frame-x64.cc
new file mode 100644
index 000000000..209aa2d30
--- /dev/null
+++ b/deps/v8/src/x64/virtual-frame-x64.cc
@@ -0,0 +1,27 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/deps/v8/src/x64/virtual-frame-x64.h b/deps/v8/src/x64/virtual-frame-x64.h
new file mode 100644
index 000000000..f71766d03
--- /dev/null
+++ b/deps/v8/src/x64/virtual-frame-x64.h
@@ -0,0 +1,493 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_X64_VIRTUAL_FRAME_X64_H_
+#define V8_X64_VIRTUAL_FRAME_X64_H_
+
+#include "register-allocator.h"
+
+namespace v8 { namespace internal {
+
+// -------------------------------------------------------------------------
+// Virtual frames
+//
+// The virtual frame is an abstraction of the physical stack frame. It
+// encapsulates the parameters, frame-allocated locals, and the expression
+// stack. It supports push/pop operations on the expression stack, as well
+// as random access to the expression stack elements, locals, and
+// parameters.
+
+class VirtualFrame : public Malloced {
+ public:
+ // A utility class to introduce a scope where the virtual frame is
+ // expected to remain spilled. The constructor spills the code
+ // generator's current frame, but no attempt is made to require it
+ // to stay spilled. It is intended as documentation while the code
+ // generator is being transformed.
+ class SpilledScope BASE_EMBEDDED {
+ public:
+ explicit SpilledScope(CodeGenerator* cgen);
+
+ ~SpilledScope();
+
+ private:
+ CodeGenerator* cgen_;
+ bool previous_state_;
+ };
+
+ // An illegal index into the virtual frame.
+ static const int kIllegalIndex = -1;
+
+ // Construct an initial virtual frame on entry to a JS function.
+ explicit VirtualFrame(CodeGenerator* cgen);
+
+ // Construct a virtual frame as a clone of an existing one.
+ explicit VirtualFrame(VirtualFrame* original);
+
+ // Create a duplicate of an existing valid frame element.
+ FrameElement CopyElementAt(int index);
+
+ // The height of the virtual expression stack.
+ int height() const {
+ return elements_.length() - expression_base_index();
+ }
+
+ int register_index(Register reg) {
+ return register_locations_[reg.code()];
+ }
+
+ bool is_used(int reg_code) {
+ return register_locations_[reg_code] != kIllegalIndex;
+ }
+
+ bool is_used(Register reg) {
+ return is_used(reg.code());
+ }
+
+ // Add extra in-memory elements to the top of the frame to match an actual
+ // frame (eg, the frame after an exception handler is pushed). No code is
+ // emitted.
+ void Adjust(int count);
+
+ // Forget count elements from the top of the frame all in-memory
+ // (including synced) and adjust the stack pointer downward, to
+ // match an external frame effect (examples include a call removing
+ // its arguments, and exiting a try/catch removing an exception
+ // handler). No code will be emitted.
+ void Forget(int count);
+
+ // Forget count elements from the top of the frame without adjusting
+ // the stack pointer downward. This is used, for example, before
+ // merging frames at break, continue, and return targets.
+ void ForgetElements(int count);
+
+ // Spill all values from the frame to memory.
+ void SpillAll();
+
+ // Spill all occurrences of a specific register from the frame.
+ void Spill(Register reg);
+
+ // Spill all occurrences of an arbitrary register if possible. Return the
+ // register spilled or no_reg if it was not possible to free any register
+ // (ie, they all have frame-external references).
+ Register SpillAnyRegister();
+
+ // Prepare this virtual frame for merging to an expected frame by
+ // performing some state changes that do not require generating
+ // code. It is guaranteed that no code will be generated.
+ void PrepareMergeTo(VirtualFrame* expected);
+
+ // Make this virtual frame have a state identical to an expected virtual
+ // frame. As a side effect, code may be emitted to make this frame match
+ // the expected one.
+ void MergeTo(VirtualFrame* expected);
+
+ // Detach a frame from its code generator, perhaps temporarily. This
+ // tells the register allocator that it is free to use frame-internal
+ // registers. Used when the code generator's frame is switched from this
+ // one to NULL by an unconditional jump.
+ void DetachFromCodeGenerator();
+
+ // (Re)attach a frame to its code generator. This informs the register
+ // allocator that the frame-internal register references are active again.
+ // Used when a code generator's frame is switched from NULL to this one by
+ // binding a label.
+ void AttachToCodeGenerator();
+
+ // Emit code for the physical JS entry and exit frame sequences. After
+ // calling Enter, the virtual frame is ready for use; and after calling
+ // Exit it should not be used. Note that Enter does not allocate space in
+ // the physical frame for storing frame-allocated locals.
+ void Enter();
+ void Exit();
+
+ // Prepare for returning from the frame by spilling locals. This
+ // avoids generating unnecessary merge code when jumping to the
+ // shared return site. Emits code for spills.
+ void PrepareForReturn();
+
+ // Allocate and initialize the frame-allocated locals.
+ void AllocateStackSlots(int count);
+
+ // An element of the expression stack as an assembly operand.
+ Operand ElementAt(int index) const {
+ return Operand(rsp, index * kPointerSize);
+ }
+
+ // Random-access store to a frame-top relative frame element. The result
+ // becomes owned by the frame and is invalidated.
+ void SetElementAt(int index, Result* value);
+
+ // Set a frame element to a constant. The index is frame-top relative.
+ void SetElementAt(int index, Handle<Object> value) {
+ Result temp(value, cgen_);
+ SetElementAt(index, &temp);
+ }
+
+ void PushElementAt(int index) {
+ PushFrameSlotAt(elements_.length() - index - 1);
+ }
+
+ void StoreToElementAt(int index) {
+ StoreToFrameSlotAt(elements_.length() - index - 1);
+ }
+
+ // A frame-allocated local as an assembly operand.
+ Operand LocalAt(int index) const {
+ ASSERT(0 <= index);
+ ASSERT(index < local_count_);
+ return Operand(rbp, kLocal0Offset - index * kPointerSize);
+ }
+
+ // Push a copy of the value of a local frame slot on top of the frame.
+ void PushLocalAt(int index) {
+ PushFrameSlotAt(local0_index() + index);
+ }
+
+ // Push the value of a local frame slot on top of the frame and invalidate
+ // the local slot. The slot should be written to before trying to read
+ // from it again.
+ void TakeLocalAt(int index) {
+ TakeFrameSlotAt(local0_index() + index);
+ }
+
+ // Store the top value on the virtual frame into a local frame slot. The
+ // value is left in place on top of the frame.
+ void StoreToLocalAt(int index) {
+ StoreToFrameSlotAt(local0_index() + index);
+ }
+
+ // Push the address of the receiver slot on the frame.
+ void PushReceiverSlotAddress();
+
+ // Push the function on top of the frame.
+ void PushFunction() { PushFrameSlotAt(function_index()); }
+
+ // Save the value of the esi register to the context frame slot.
+ void SaveContextRegister();
+
+ // Restore the esi register from the value of the context frame
+ // slot.
+ void RestoreContextRegister();
+
+ // A parameter as an assembly operand.
+ Operand ParameterAt(int index) const {
+ ASSERT(-1 <= index); // -1 is the receiver.
+ ASSERT(index < parameter_count_);
+ return Operand(rbp, (1 + parameter_count_ - index) * kPointerSize);
+ }
+
+ // Push a copy of the value of a parameter frame slot on top of the frame.
+ void PushParameterAt(int index) {
+ PushFrameSlotAt(param0_index() + index);
+ }
+
+ // Push the value of a paramter frame slot on top of the frame and
+ // invalidate the parameter slot. The slot should be written to before
+ // trying to read from it again.
+ void TakeParameterAt(int index) {
+ TakeFrameSlotAt(param0_index() + index);
+ }
+
+ // Store the top value on the virtual frame into a parameter frame slot.
+ // The value is left in place on top of the frame.
+ void StoreToParameterAt(int index) {
+ StoreToFrameSlotAt(param0_index() + index);
+ }
+
+ // The receiver frame slot.
+ Operand Receiver() const { return ParameterAt(-1); }
+
+ // Push a try-catch or try-finally handler on top of the virtual frame.
+ void PushTryHandler(HandlerType type);
+
+ // Call stub given the number of arguments it expects on (and
+ // removes from) the stack.
+ Result CallStub(CodeStub* stub, int arg_count);
+
+ // Call stub that takes a single argument passed in eax. The
+ // argument is given as a result which does not have to be eax or
+ // even a register. The argument is consumed by the call.
+ Result CallStub(CodeStub* stub, Result* arg);
+
+ // Call stub that takes a pair of arguments passed in edx (arg0) and
+ // eax (arg1). The arguments are given as results which do not have
+ // to be in the proper registers or even in registers. The
+ // arguments are consumed by the call.
+ Result CallStub(CodeStub* stub, Result* arg0, Result* arg1);
+
+ // Call runtime given the number of arguments expected on (and
+ // removed from) the stack.
+ Result CallRuntime(Runtime::Function* f, int arg_count);
+ Result CallRuntime(Runtime::FunctionId id, int arg_count);
+
+ // Invoke builtin given the number of arguments it expects on (and
+ // removes from) the stack.
+ Result InvokeBuiltin(Builtins::JavaScript id,
+ InvokeFlag flag,
+ int arg_count);
+
+ // Call load IC. Name and receiver are found on top of the frame.
+ // Receiver is not dropped.
+ Result CallLoadIC(RelocInfo::Mode mode);
+
+ // Call keyed load IC. Key and receiver are found on top of the
+ // frame. They are not dropped.
+ Result CallKeyedLoadIC(RelocInfo::Mode mode);
+
+ // Call store IC. Name, value, and receiver are found on top of the
+ // frame. Receiver is not dropped.
+ Result CallStoreIC();
+
+ // Call keyed store IC. Value, key, and receiver are found on top
+ // of the frame. Key and receiver are not dropped.
+ Result CallKeyedStoreIC();
+
+ // Call call IC. Arguments, reciever, and function name are found
+ // on top of the frame. Function name slot is not dropped. The
+ // argument count does not include the receiver.
+ Result CallCallIC(RelocInfo::Mode mode, int arg_count, int loop_nesting);
+
+ // Allocate and call JS function as constructor. Arguments,
+ // receiver (global object), and function are found on top of the
+ // frame. Function is not dropped. The argument count does not
+ // include the receiver.
+ Result CallConstructor(int arg_count);
+
+ // Drop a number of elements from the top of the expression stack. May
+ // emit code to affect the physical frame. Does not clobber any registers
+ // excepting possibly the stack pointer.
+ void Drop(int count);
+
+ // Drop one element.
+ void Drop() { Drop(1); }
+
+ // Duplicate the top element of the frame.
+ void Dup() { PushFrameSlotAt(elements_.length() - 1); }
+
+ // Pop an element from the top of the expression stack. Returns a
+ // Result, which may be a constant or a register.
+ Result Pop();
+
+ // Pop and save an element from the top of the expression stack and
+ // emit a corresponding pop instruction.
+ void EmitPop(Register reg);
+ void EmitPop(Operand operand);
+
+ // Push an element on top of the expression stack and emit a
+ // corresponding push instruction.
+ void EmitPush(Register reg);
+ void EmitPush(Operand operand);
+ void EmitPush(Immediate immediate);
+
+ // Push an element on the virtual frame.
+ void Push(Register reg, StaticType static_type = StaticType());
+ void Push(Handle<Object> value);
+ void Push(Smi* value) { Push(Handle<Object>(value)); }
+
+ // Pushing a result invalidates it (its contents become owned by the
+ // frame).
+ void Push(Result* result);
+
+ // Nip removes zero or more elements from immediately below the top
+ // of the frame, leaving the previous top-of-frame value on top of
+ // the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x).
+ void Nip(int num_dropped);
+
+ private:
+ static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
+ static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset;
+ static const int kContextOffset = StandardFrameConstants::kContextOffset;
+
+ static const int kHandlerSize = StackHandlerConstants::kSize / kPointerSize;
+ static const int kPreallocatedElements = 5 + 8; // 8 expression stack slots.
+
+ CodeGenerator* cgen_;
+ MacroAssembler* masm_;
+
+ List<FrameElement> elements_;
+
+ // The number of frame-allocated locals and parameters respectively.
+ int parameter_count_;
+ int local_count_;
+
+ // The index of the element that is at the processor's stack pointer
+ // (the esp register).
+ int stack_pointer_;
+
+ // The index of the element that is at the processor's frame pointer
+ // (the ebp register).
+ int frame_pointer_;
+
+ // The index of the register frame element using each register, or
+ // kIllegalIndex if a register is not on the frame.
+ int register_locations_[kNumRegisters];
+
+ // The index of the first parameter. The receiver lies below the first
+ // parameter.
+ int param0_index() const { return 1; }
+
+ // The index of the context slot in the frame.
+ int context_index() const {
+ ASSERT(frame_pointer_ != kIllegalIndex);
+ return frame_pointer_ + 1;
+ }
+
+ // The index of the function slot in the frame. It lies above the context
+ // slot.
+ int function_index() const {
+ ASSERT(frame_pointer_ != kIllegalIndex);
+ return frame_pointer_ + 2;
+ }
+
+ // The index of the first local. Between the parameters and the locals
+ // lie the return address, the saved frame pointer, the context, and the
+ // function.
+ int local0_index() const {
+ ASSERT(frame_pointer_ != kIllegalIndex);
+ return frame_pointer_ + 3;
+ }
+
+ // The index of the base of the expression stack.
+ int expression_base_index() const { return local0_index() + local_count_; }
+
+ // Convert a frame index into a frame pointer relative offset into the
+ // actual stack.
+ int fp_relative(int index) const {
+ return (frame_pointer_ - index) * kPointerSize;
+ }
+
+ // Record an occurrence of a register in the virtual frame. This has the
+ // effect of incrementing the register's external reference count and
+ // of updating the index of the register's location in the frame.
+ void Use(Register reg, int index);
+
+ // Record that a register reference has been dropped from the frame. This
+ // decrements the register's external reference count and invalidates the
+ // index of the register's location in the frame.
+ void Unuse(Register reg);
+
+ // Spill the element at a particular index---write it to memory if
+ // necessary, free any associated register, and forget its value if
+ // constant.
+ void SpillElementAt(int index);
+
+ // Sync the element at a particular index. If it is a register or
+ // constant that disagrees with the value on the stack, write it to memory.
+ // Keep the element type as register or constant, and clear the dirty bit.
+ void SyncElementAt(int index);
+
+ // Sync the range of elements in [begin, end).
+ void SyncRange(int begin, int end);
+
+ // Sync a single unsynced element that lies beneath or at the stack pointer.
+ void SyncElementBelowStackPointer(int index);
+
+ // Sync a single unsynced element that lies just above the stack pointer.
+ void SyncElementByPushing(int index);
+
+ // Push a copy of a frame slot (typically a local or parameter) on top of
+ // the frame.
+ void PushFrameSlotAt(int index);
+
+ // Push a the value of a frame slot (typically a local or parameter) on
+ // top of the frame and invalidate the slot.
+ void TakeFrameSlotAt(int index);
+
+ // Store the value on top of the frame to a frame slot (typically a local
+ // or parameter).
+ void StoreToFrameSlotAt(int index);
+
+ // Spill all elements in registers. Spill the top spilled_args elements
+ // on the frame. Sync all other frame elements.
+ // Then drop dropped_args elements from the virtual frame, to match
+ // the effect of an upcoming call that will drop them from the stack.
+ void PrepareForCall(int spilled_args, int dropped_args);
+
+ // Move frame elements currently in registers or constants, that
+ // should be in memory in the expected frame, to memory.
+ void MergeMoveRegistersToMemory(VirtualFrame* expected);
+
+ // Make the register-to-register moves necessary to
+ // merge this frame with the expected frame.
+ // Register to memory moves must already have been made,
+ // and memory to register moves must follow this call.
+ // This is because some new memory-to-register moves are
+ // created in order to break cycles of register moves.
+ // Used in the implementation of MergeTo().
+ void MergeMoveRegistersToRegisters(VirtualFrame* expected);
+
+ // Make the memory-to-register and constant-to-register moves
+ // needed to make this frame equal the expected frame.
+ // Called after all register-to-memory and register-to-register
+ // moves have been made. After this function returns, the frames
+ // should be equal.
+ void MergeMoveMemoryToRegisters(VirtualFrame* expected);
+
+ // Invalidates a frame slot (puts an invalid frame element in it).
+ // Copies on the frame are correctly handled, and if this slot was
+ // the backing store of copies, the index of the new backing store
+ // is returned. Otherwise, returns kIllegalIndex.
+ // Register counts are correctly updated.
+ int InvalidateFrameSlotAt(int index);
+
+ // Call a code stub that has already been prepared for calling (via
+ // PrepareForCall).
+ Result RawCallStub(CodeStub* stub);
+
+ // Calls a code object which has already been prepared for calling
+ // (via PrepareForCall).
+ Result RawCallCodeObject(Handle<Code> code, RelocInfo::Mode rmode);
+
+ bool Equals(VirtualFrame* other);
+
+ friend class JumpTarget;
+};
+
+} } // namespace v8::internal
+
+#endif // V8_X64_VIRTUAL_FRAME_X64_H_
diff --git a/deps/v8/test/cctest/SConscript b/deps/v8/test/cctest/SConscript
index f66f72b0e..740acbaa6 100644
--- a/deps/v8/test/cctest/SConscript
+++ b/deps/v8/test/cctest/SConscript
@@ -47,6 +47,7 @@ SOURCES = {
'test-heap.cc',
'test-list.cc',
'test-lock.cc',
+ 'test-log.cc',
'test-mark-compact.cc',
'test-regexp.cc',
'test-serialize.cc',
@@ -54,7 +55,8 @@ SOURCES = {
'test-spaces.cc',
'test-strings.cc',
'test-threads.cc',
- 'test-utils.cc'
+ 'test-utils.cc',
+ 'test-version.cc'
],
'arch:arm': ['test-assembler-arm.cc', 'test-disasm-arm.cc'],
'arch:ia32': [
diff --git a/deps/v8/test/cctest/cctest.cc b/deps/v8/test/cctest/cctest.cc
index 2807c8b47..82a33e6da 100644
--- a/deps/v8/test/cctest/cctest.cc
+++ b/deps/v8/test/cctest/cctest.cc
@@ -26,9 +26,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <v8.h>
-#include <cstdlib>
-#include <cstring>
-#include <cstdio>
#include "cctest.h"
#include "debug.h"
diff --git a/deps/v8/test/cctest/cctest.status b/deps/v8/test/cctest/cctest.status
index 9a3f819e4..7b43c8de9 100644
--- a/deps/v8/test/cctest/cctest.status
+++ b/deps/v8/test/cctest/cctest.status
@@ -27,9 +27,6 @@
prefix cctest
-# BUG(96): Fix this flaky test.
-test-debug/ThreadedDebugging: PASS || FAIL
-
# BUG(281): This test fails on some Linuxes.
test-debug/DebuggerAgent: PASS, (PASS || FAIL) if $system == linux
@@ -43,8 +40,10 @@ test-spaces/LargeObjectSpace: PASS || FAIL
# BUG(240): Test seems flaky on ARM.
test-api/RegExpInterruption: SKIP
+[ $simulator == arm ]
+
# BUG(271): During exception propagation, we compare pointers into the
# stack. These tests fail on the ARM simulator because the C++ and
# the JavaScript stacks are separate.
-test-api/ExceptionOrder: PASS || FAIL
-test-api/TryCatchInTryFinally: PASS || FAIL
+test-api/ExceptionOrder: FAIL
+test-api/TryCatchInTryFinally: FAIL
diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc
index 23e57d548..4b55b6be0 100644
--- a/deps/v8/test/cctest/test-api.cc
+++ b/deps/v8/test/cctest/test-api.cc
@@ -27,9 +27,6 @@
#include <stdlib.h>
-#include <map>
-#include <string>
-
#include "v8.h"
#include "api.h"
@@ -161,7 +158,7 @@ class RegisterThreadedTest {
}
static int count() { return count_; }
static RegisterThreadedTest* nth(int i) {
- ASSERT(i < count());
+ CHECK(i < count());
RegisterThreadedTest* current = first_;
while (i > 0) {
i--;
@@ -295,13 +292,13 @@ THREADED_TEST(ArgumentSignature) {
env->Global()->Set(v8_str("Fun1"), fun->GetFunction());
v8::Handle<Value> value1 = CompileRun("Fun1(4) == '';");
- ASSERT(value1->IsTrue());
+ CHECK(value1->IsTrue());
v8::Handle<Value> value2 = CompileRun("Fun1(new Cons()) == '[object Cons]';");
- ASSERT(value2->IsTrue());
+ CHECK(value2->IsTrue());
v8::Handle<Value> value3 = CompileRun("Fun1() == '';");
- ASSERT(value3->IsTrue());
+ CHECK(value3->IsTrue());
v8::Handle<v8::FunctionTemplate> cons1 = v8::FunctionTemplate::New();
cons1->SetClassName(v8_str("Cons1"));
@@ -323,24 +320,24 @@ THREADED_TEST(ArgumentSignature) {
v8::Handle<Value> value4 = CompileRun(
"Fun2(new Cons1(), new Cons2(), new Cons3()) =="
"'[object Cons1],[object Cons2],[object Cons3]'");
- ASSERT(value4->IsTrue());
+ CHECK(value4->IsTrue());
v8::Handle<Value> value5 = CompileRun(
"Fun2(new Cons1(), new Cons2(), 5) == '[object Cons1],[object Cons2],'");
- ASSERT(value5->IsTrue());
+ CHECK(value5->IsTrue());
v8::Handle<Value> value6 = CompileRun(
"Fun2(new Cons3(), new Cons2(), new Cons1()) == ',[object Cons2],'");
- ASSERT(value6->IsTrue());
+ CHECK(value6->IsTrue());
v8::Handle<Value> value7 = CompileRun(
"Fun2(new Cons1(), new Cons2(), new Cons3(), 'd') == "
"'[object Cons1],[object Cons2],[object Cons3],d';");
- ASSERT(value7->IsTrue());
+ CHECK(value7->IsTrue());
v8::Handle<Value> value8 = CompileRun(
"Fun2(new Cons1(), new Cons2()) == '[object Cons1],[object Cons2]'");
- ASSERT(value8->IsTrue());
+ CHECK(value8->IsTrue());
}
@@ -423,7 +420,7 @@ class TestAsciiResource: public String::ExternalAsciiStringResource {
public:
static int dispose_count;
- explicit TestAsciiResource(char* data)
+ explicit TestAsciiResource(const char* data)
: data_(data),
length_(strlen(data)) { }
@@ -440,7 +437,7 @@ class TestAsciiResource: public String::ExternalAsciiStringResource {
return length_;
}
private:
- char* data_;
+ const char* data_;
size_t length_;
};
@@ -1394,6 +1391,7 @@ static void check_message(v8::Handle<v8::Message> message,
v8::Handle<Value> data) {
CHECK_EQ(5.76, data->NumberValue());
CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
+ CHECK_EQ(7.56, message->GetScriptData()->NumberValue());
message_received = true;
}
@@ -1406,7 +1404,10 @@ THREADED_TEST(MessageHandlerData) {
LocalContext context;
v8::ScriptOrigin origin =
v8::ScriptOrigin(v8_str("6.75"));
- Script::Compile(v8_str("throw 'error'"), &origin)->Run();
+ v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
+ &origin);
+ script->SetData(v8_str("7.56"));
+ script->Run();
CHECK(message_received);
// clear out the message listener
v8::V8::RemoveMessageListeners(check_message);
@@ -2925,7 +2926,19 @@ THREADED_TEST(Deleter) {
static v8::Handle<Value> GetK(Local<String> name, const AccessorInfo&) {
ApiTestFuzzer::Fuzz();
- return v8::Undefined();
+ if (name->Equals(v8_str("foo")) ||
+ name->Equals(v8_str("bar")) ||
+ name->Equals(v8_str("baz"))) {
+ return v8::Undefined();
+ }
+ return v8::Handle<Value>();
+}
+
+
+static v8::Handle<Value> IndexedGetK(uint32_t index, const AccessorInfo&) {
+ ApiTestFuzzer::Fuzz();
+ if (index == 0 || index == 1) return v8::Undefined();
+ return v8::Handle<Value>();
}
@@ -2942,8 +2955,8 @@ static v8::Handle<v8::Array> NamedEnum(const AccessorInfo&) {
static v8::Handle<v8::Array> IndexedEnum(const AccessorInfo&) {
ApiTestFuzzer::Fuzz();
v8::Handle<v8::Array> result = v8::Array::New(2);
- result->Set(v8::Integer::New(0), v8_str("hat"));
- result->Set(v8::Integer::New(1), v8_str("gyt"));
+ result->Set(v8::Integer::New(0), v8_str("0"));
+ result->Set(v8::Integer::New(1), v8_str("1"));
return result;
}
@@ -2952,21 +2965,56 @@ THREADED_TEST(Enumerators) {
v8::HandleScope scope;
v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
obj->SetNamedPropertyHandler(GetK, NULL, NULL, NULL, NamedEnum);
- obj->SetIndexedPropertyHandler(NULL, NULL, NULL, NULL, IndexedEnum);
+ obj->SetIndexedPropertyHandler(IndexedGetK, NULL, NULL, NULL, IndexedEnum);
LocalContext context;
context->Global()->Set(v8_str("k"), obj->NewInstance());
v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
+ "k[10] = 0;"
+ "k.a = 0;"
+ "k[5] = 0;"
+ "k.b = 0;"
+ "k[4294967295] = 0;"
+ "k.c = 0;"
+ "k[4294967296] = 0;"
+ "k.d = 0;"
+ "k[140000] = 0;"
+ "k.e = 0;"
+ "k[30000000000] = 0;"
+ "k.f = 0;"
"var result = [];"
"for (var prop in k) {"
" result.push(prop);"
"}"
"result"));
- CHECK_EQ(5, result->Length());
- CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(0)));
- CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(1)));
- CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(2)));
- CHECK_EQ(v8_str("hat"), result->Get(v8::Integer::New(3)));
- CHECK_EQ(v8_str("gyt"), result->Get(v8::Integer::New(4)));
+ // Check that we get all the property names returned including the
+ // ones from the enumerators in the right order: indexed properties
+ // in numerical order, indexed interceptor properties, named
+ // properties in insertion order, named interceptor properties.
+ // This order is not mandated by the spec, so this test is just
+ // documenting our behavior.
+ CHECK_EQ(17, result->Length());
+ // Indexed properties in numerical order.
+ CHECK_EQ(v8_str("5"), result->Get(v8::Integer::New(0)));
+ CHECK_EQ(v8_str("10"), result->Get(v8::Integer::New(1)));
+ CHECK_EQ(v8_str("140000"), result->Get(v8::Integer::New(2)));
+ CHECK_EQ(v8_str("4294967295"), result->Get(v8::Integer::New(3)));
+ // Indexed interceptor properties in the order they are returned
+ // from the enumerator interceptor.
+ CHECK_EQ(v8_str("0"), result->Get(v8::Integer::New(4)));
+ CHECK_EQ(v8_str("1"), result->Get(v8::Integer::New(5)));
+ // Named properties in insertion order.
+ CHECK_EQ(v8_str("a"), result->Get(v8::Integer::New(6)));
+ CHECK_EQ(v8_str("b"), result->Get(v8::Integer::New(7)));
+ CHECK_EQ(v8_str("c"), result->Get(v8::Integer::New(8)));
+ CHECK_EQ(v8_str("4294967296"), result->Get(v8::Integer::New(9)));
+ CHECK_EQ(v8_str("d"), result->Get(v8::Integer::New(10)));
+ CHECK_EQ(v8_str("e"), result->Get(v8::Integer::New(11)));
+ CHECK_EQ(v8_str("30000000000"), result->Get(v8::Integer::New(12)));
+ CHECK_EQ(v8_str("f"), result->Get(v8::Integer::New(13)));
+ // Named interceptor properties.
+ CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(14)));
+ CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(15)));
+ CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(16)));
}
@@ -4579,40 +4627,42 @@ THREADED_TEST(CallAsFunction) {
Local<Value> value;
CHECK(!try_catch.HasCaught());
- value = Script::Compile(v8_str("obj(42)"))->Run();
+ value = CompileRun("obj(42)");
CHECK(!try_catch.HasCaught());
CHECK_EQ(42, value->Int32Value());
- value = Script::Compile(v8_str("(function(o){return o(49)})(obj)"))->Run();
+ value = CompileRun("(function(o){return o(49)})(obj)");
CHECK(!try_catch.HasCaught());
CHECK_EQ(49, value->Int32Value());
// test special case of call as function
- value = Script::Compile(v8_str("[obj]['0'](45)"))->Run();
+ value = CompileRun("[obj]['0'](45)");
CHECK(!try_catch.HasCaught());
CHECK_EQ(45, value->Int32Value());
- value = Script::Compile(v8_str("obj.call = Function.prototype.call;"
- "obj.call(null, 87)"))->Run();
+ value = CompileRun("obj.call = Function.prototype.call;"
+ "obj.call(null, 87)");
CHECK(!try_catch.HasCaught());
CHECK_EQ(87, value->Int32Value());
// Regression tests for bug #1116356: Calling call through call/apply
// must work for non-function receivers.
const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
- value = Script::Compile(v8_str(apply_99))->Run();
+ value = CompileRun(apply_99);
CHECK(!try_catch.HasCaught());
CHECK_EQ(99, value->Int32Value());
const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
- value = Script::Compile(v8_str(call_17))->Run();
+ value = CompileRun(call_17);
CHECK(!try_catch.HasCaught());
CHECK_EQ(17, value->Int32Value());
- // Try something that will cause an exception: Call the object as a
- // constructor. This should be the last test.
- value = Script::Compile(v8_str("new obj(42)"))->Run();
- CHECK(try_catch.HasCaught());
+ // Check that the call-as-function handler can be called through
+ // new. Currently, there is no way to check in the call-as-function
+ // handler if it has been called through new or not.
+ value = CompileRun("new obj(42)");
+ CHECK(!try_catch.HasCaught());
+ CHECK_EQ(42, value->Int32Value());
}
@@ -4689,6 +4739,44 @@ THREADED_TEST(InterceptorHasOwnProperty) {
}
+static v8::Handle<Value> InterceptorHasOwnPropertyGetterGC(
+ Local<String> name,
+ const AccessorInfo& info) {
+ ApiTestFuzzer::Fuzz();
+ i::Heap::CollectAllGarbage();
+ return v8::Handle<Value>();
+}
+
+
+THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
+ v8::HandleScope scope;
+ LocalContext context;
+ Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+ Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
+ instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetterGC);
+ Local<Function> function = fun_templ->GetFunction();
+ context->Global()->Set(v8_str("constructor"), function);
+ // Let's first make some stuff so we can be sure to get a good GC.
+ CompileRun(
+ "function makestr(size) {"
+ " switch (size) {"
+ " case 1: return 'f';"
+ " case 2: return 'fo';"
+ " case 3: return 'foo';"
+ " }"
+ " return makestr(size >> 1) + makestr((size + 1) >> 1);"
+ "}"
+ "var x = makestr(12345);"
+ "x = makestr(31415);"
+ "x = makestr(23456);");
+ v8::Handle<Value> value = CompileRun(
+ "var o = new constructor();"
+ "o.__proto__ = new String(x);"
+ "o.hasOwnProperty('ostehaps');");
+ CHECK_EQ(false, value->BooleanValue());
+}
+
+
static v8::Handle<Value> InterceptorLoadICGetter(Local<String> name,
const AccessorInfo& info) {
ApiTestFuzzer::Fuzz();
@@ -5963,6 +6051,114 @@ TEST(RegExpInterruption) {
}
+class ApplyInterruptTest {
+ public:
+ ApplyInterruptTest() : block_(NULL) {}
+ ~ApplyInterruptTest() { delete block_; }
+ void RunTest() {
+ block_ = i::OS::CreateSemaphore(0);
+ gc_count_ = 0;
+ gc_during_apply_ = 0;
+ apply_success_ = false;
+ gc_success_ = false;
+ GCThread gc_thread(this);
+ gc_thread.Start();
+ v8::Locker::StartPreemption(1);
+
+ LongRunningApply();
+ {
+ v8::Unlocker unlock;
+ gc_thread.Join();
+ }
+ v8::Locker::StopPreemption();
+ CHECK(apply_success_);
+ CHECK(gc_success_);
+ }
+ private:
+ // Number of garbage collections required.
+ static const int kRequiredGCs = 2;
+
+ class GCThread : public i::Thread {
+ public:
+ explicit GCThread(ApplyInterruptTest* test)
+ : test_(test) {}
+ virtual void Run() {
+ test_->CollectGarbage();
+ }
+ private:
+ ApplyInterruptTest* test_;
+ };
+
+ void CollectGarbage() {
+ block_->Wait();
+ while (gc_during_apply_ < kRequiredGCs) {
+ {
+ v8::Locker lock;
+ i::Heap::CollectAllGarbage();
+ gc_count_++;
+ }
+ i::OS::Sleep(1);
+ }
+ gc_success_ = true;
+ }
+
+ void LongRunningApply() {
+ block_->Signal();
+ int rounds = 0;
+ while (gc_during_apply_ < kRequiredGCs) {
+ int gc_before = gc_count_;
+ {
+ const char* c_source =
+ "function do_very_little(bar) {"
+ " this.foo = bar;"
+ "}"
+ "for (var i = 0; i < 100000; i++) {"
+ " do_very_little.apply(this, ['bar']);"
+ "}";
+ Local<String> source = String::New(c_source);
+ Local<Script> script = Script::Compile(source);
+ Local<Value> result = script->Run();
+ // Check that no exception was thrown.
+ CHECK(!result.IsEmpty());
+ }
+ int gc_after = gc_count_;
+ gc_during_apply_ += gc_after - gc_before;
+ rounds++;
+ }
+ apply_success_ = true;
+ }
+
+ i::Semaphore* block_;
+ int gc_count_;
+ int gc_during_apply_;
+ bool apply_success_;
+ bool gc_success_;
+};
+
+
+// Test that nothing bad happens if we get a preemption just when we were
+// about to do an apply().
+TEST(ApplyInterruption) {
+ v8::Locker lock;
+ v8::V8::Initialize();
+ v8::HandleScope scope;
+ Local<Context> local_env;
+ {
+ LocalContext env;
+ local_env = env.local();
+ }
+
+ // Local context should still be live.
+ CHECK(!local_env.IsEmpty());
+ local_env->Enter();
+
+ // Should complete without problems.
+ ApplyInterruptTest().RunTest();
+
+ local_env->Exit();
+}
+
+
// Verify that we can clone an object
TEST(ObjectClone) {
v8::HandleScope scope;
@@ -5997,6 +6193,117 @@ TEST(ObjectClone) {
}
+class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
+ public:
+ explicit AsciiVectorResource(i::Vector<const char> vector)
+ : data_(vector) {}
+ virtual ~AsciiVectorResource() {}
+ virtual size_t length() const { return data_.length(); }
+ virtual const char* data() const { return data_.start(); }
+ private:
+ i::Vector<const char> data_;
+};
+
+
+class UC16VectorResource : public v8::String::ExternalStringResource {
+ public:
+ explicit UC16VectorResource(i::Vector<const i::uc16> vector)
+ : data_(vector) {}
+ virtual ~UC16VectorResource() {}
+ virtual size_t length() const { return data_.length(); }
+ virtual const i::uc16* data() const { return data_.start(); }
+ private:
+ i::Vector<const i::uc16> data_;
+};
+
+
+static void MorphAString(i::String* string,
+ AsciiVectorResource* ascii_resource,
+ UC16VectorResource* uc16_resource) {
+ CHECK(i::StringShape(string).IsExternal());
+ if (string->IsAsciiRepresentation()) {
+ // Check old map is not symbol or long.
+ CHECK(string->map() == i::Heap::short_external_ascii_string_map() ||
+ string->map() == i::Heap::medium_external_ascii_string_map());
+ // Morph external string to be TwoByte string.
+ if (string->length() <= i::String::kMaxShortStringSize) {
+ string->set_map(i::Heap::short_external_string_map());
+ } else {
+ string->set_map(i::Heap::medium_external_string_map());
+ }
+ i::ExternalTwoByteString* morphed =
+ i::ExternalTwoByteString::cast(string);
+ morphed->set_resource(uc16_resource);
+ } else {
+ // Check old map is not symbol or long.
+ CHECK(string->map() == i::Heap::short_external_string_map() ||
+ string->map() == i::Heap::medium_external_string_map());
+ // Morph external string to be ASCII string.
+ if (string->length() <= i::String::kMaxShortStringSize) {
+ string->set_map(i::Heap::short_external_ascii_string_map());
+ } else {
+ string->set_map(i::Heap::medium_external_ascii_string_map());
+ }
+ i::ExternalAsciiString* morphed =
+ i::ExternalAsciiString::cast(string);
+ morphed->set_resource(ascii_resource);
+ }
+}
+
+
+// Test that we can still flatten a string if the components it is built up
+// from have been turned into 16 bit strings in the mean time.
+THREADED_TEST(MorphCompositeStringTest) {
+ const char* c_string = "Now is the time for all good men"
+ " to come to the aid of the party";
+ uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
+ {
+ v8::HandleScope scope;
+ LocalContext env;
+ AsciiVectorResource ascii_resource(
+ i::Vector<const char>(c_string, strlen(c_string)));
+ UC16VectorResource uc16_resource(
+ i::Vector<const uint16_t>(two_byte_string, strlen(c_string)));
+
+ Local<String> lhs(v8::Utils::ToLocal(
+ i::Factory::NewExternalStringFromAscii(&ascii_resource)));
+ Local<String> rhs(v8::Utils::ToLocal(
+ i::Factory::NewExternalStringFromAscii(&ascii_resource)));
+
+ env->Global()->Set(v8_str("lhs"), lhs);
+ env->Global()->Set(v8_str("rhs"), rhs);
+
+ CompileRun(
+ "var cons = lhs + rhs;"
+ "var slice = lhs.substring(1, lhs.length - 1);"
+ "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
+
+ MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource);
+ MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource);
+
+ // Now do some stuff to make sure the strings are flattened, etc.
+ CompileRun(
+ "/[^a-z]/.test(cons);"
+ "/[^a-z]/.test(slice);"
+ "/[^a-z]/.test(slice_on_cons);");
+ const char* expected_cons =
+ "Now is the time for all good men to come to the aid of the party"
+ "Now is the time for all good men to come to the aid of the party";
+ const char* expected_slice =
+ "ow is the time for all good men to come to the aid of the part";
+ const char* expected_slice_on_cons =
+ "ow is the time for all good men to come to the aid of the party"
+ "Now is the time for all good men to come to the aid of the part";
+ CHECK_EQ(String::New(expected_cons),
+ env->Global()->Get(v8_str("cons")));
+ CHECK_EQ(String::New(expected_slice),
+ env->Global()->Get(v8_str("slice")));
+ CHECK_EQ(String::New(expected_slice_on_cons),
+ env->Global()->Get(v8_str("slice_on_cons")));
+ }
+}
+
+
class RegExpStringModificationTest {
public:
RegExpStringModificationTest()
@@ -6041,26 +6348,6 @@ class RegExpStringModificationTest {
}
private:
- class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
- public:
- explicit AsciiVectorResource(i::Vector<const char> vector)
- : data_(vector) {}
- virtual ~AsciiVectorResource() {}
- virtual size_t length() const { return data_.length(); }
- virtual const char* data() const { return data_.start(); }
- private:
- i::Vector<const char> data_;
- };
- class UC16VectorResource : public v8::String::ExternalStringResource {
- public:
- explicit UC16VectorResource(i::Vector<const i::uc16> vector)
- : data_(vector) {}
- virtual ~UC16VectorResource() {}
- virtual size_t length() const { return data_.length(); }
- virtual const i::uc16* data() const { return data_.start(); }
- private:
- i::Vector<const i::uc16> data_;
- };
// Number of string modifications required.
static const int kRequiredModifications = 5;
static const int kMaxModifications = 100;
@@ -6084,25 +6371,7 @@ class RegExpStringModificationTest {
v8::Locker lock;
// Swap string between ascii and two-byte representation.
i::String* string = *input_;
- CHECK(i::StringShape(string).IsExternal());
- if (i::StringShape(string).IsAsciiRepresentation()) {
- // Morph external string to be TwoByte string.
- i::ExternalAsciiString* ext_string =
- i::ExternalAsciiString::cast(string);
- i::ExternalTwoByteString* morphed =
- reinterpret_cast<i::ExternalTwoByteString*>(ext_string);
- morphed->map()->set_instance_type(i::SHORT_EXTERNAL_STRING_TYPE);
- morphed->set_resource(&uc16_resource_);
- } else {
- // Morph external string to be ASCII string.
- i::ExternalTwoByteString* ext_string =
- i::ExternalTwoByteString::cast(string);
- i::ExternalAsciiString* morphed =
- reinterpret_cast<i::ExternalAsciiString*>(ext_string);
- morphed->map()->set_instance_type(
- i::SHORT_EXTERNAL_ASCII_STRING_TYPE);
- morphed->set_resource(&ascii_resource_);
- }
+ MorphAString(string, &ascii_resource_, &uc16_resource_);
morphs_++;
}
i::OS::Sleep(1);
@@ -6187,3 +6456,118 @@ TEST(ReadOnlyPropertyInGlobalProto) {
res = CompileRun("function f() { with (this) { y = 42 }; return y; }; f()");
CHECK_EQ(v8::Integer::New(42), res);
}
+
+static int force_set_set_count = 0;
+static int force_set_get_count = 0;
+bool pass_on_get = false;
+
+static v8::Handle<v8::Value> ForceSetGetter(v8::Local<v8::String> name,
+ const v8::AccessorInfo& info) {
+ force_set_get_count++;
+ if (pass_on_get) {
+ return v8::Handle<v8::Value>();
+ } else {
+ return v8::Int32::New(3);
+ }
+}
+
+static void ForceSetSetter(v8::Local<v8::String> name,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo& info) {
+ force_set_set_count++;
+}
+
+static v8::Handle<v8::Value> ForceSetInterceptSetter(
+ v8::Local<v8::String> name,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo& info) {
+ force_set_set_count++;
+ return v8::Undefined();
+}
+
+TEST(ForceSet) {
+ force_set_get_count = 0;
+ force_set_set_count = 0;
+ pass_on_get = false;
+
+ v8::HandleScope scope;
+ v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
+ v8::Handle<v8::String> access_property = v8::String::New("a");
+ templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
+ LocalContext context(NULL, templ);
+ v8::Handle<v8::Object> global = context->Global();
+
+ // Ordinary properties
+ v8::Handle<v8::String> simple_property = v8::String::New("p");
+ global->Set(simple_property, v8::Int32::New(4), v8::ReadOnly);
+ CHECK_EQ(4, global->Get(simple_property)->Int32Value());
+ // This should fail because the property is read-only
+ global->Set(simple_property, v8::Int32::New(5));
+ CHECK_EQ(4, global->Get(simple_property)->Int32Value());
+ // This should succeed even though the property is read-only
+ global->ForceSet(simple_property, v8::Int32::New(6));
+ CHECK_EQ(6, global->Get(simple_property)->Int32Value());
+
+ // Accessors
+ CHECK_EQ(0, force_set_set_count);
+ CHECK_EQ(0, force_set_get_count);
+ CHECK_EQ(3, global->Get(access_property)->Int32Value());
+ // CHECK_EQ the property shouldn't override it, just call the setter
+ // which in this case does nothing.
+ global->Set(access_property, v8::Int32::New(7));
+ CHECK_EQ(3, global->Get(access_property)->Int32Value());
+ CHECK_EQ(1, force_set_set_count);
+ CHECK_EQ(2, force_set_get_count);
+ // Forcing the property to be set should override the accessor without
+ // calling it
+ global->ForceSet(access_property, v8::Int32::New(8));
+ CHECK_EQ(8, global->Get(access_property)->Int32Value());
+ CHECK_EQ(1, force_set_set_count);
+ CHECK_EQ(2, force_set_get_count);
+}
+
+TEST(ForceSetWithInterceptor) {
+ force_set_get_count = 0;
+ force_set_set_count = 0;
+ pass_on_get = false;
+
+ v8::HandleScope scope;
+ v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
+ templ->SetNamedPropertyHandler(ForceSetGetter, ForceSetInterceptSetter);
+ LocalContext context(NULL, templ);
+ v8::Handle<v8::Object> global = context->Global();
+
+ v8::Handle<v8::String> some_property = v8::String::New("a");
+ CHECK_EQ(0, force_set_set_count);
+ CHECK_EQ(0, force_set_get_count);
+ CHECK_EQ(3, global->Get(some_property)->Int32Value());
+ // Setting the property shouldn't override it, just call the setter
+ // which in this case does nothing.
+ global->Set(some_property, v8::Int32::New(7));
+ CHECK_EQ(3, global->Get(some_property)->Int32Value());
+ CHECK_EQ(1, force_set_set_count);
+ CHECK_EQ(2, force_set_get_count);
+ // Getting the property when the interceptor returns an empty handle
+ // should yield undefined, since the property isn't present on the
+ // object itself yet.
+ pass_on_get = true;
+ CHECK(global->Get(some_property)->IsUndefined());
+ CHECK_EQ(1, force_set_set_count);
+ CHECK_EQ(3, force_set_get_count);
+ // Forcing the property to be set should cause the value to be
+ // set locally without calling the interceptor.
+ global->ForceSet(some_property, v8::Int32::New(8));
+ CHECK_EQ(8, global->Get(some_property)->Int32Value());
+ CHECK_EQ(1, force_set_set_count);
+ CHECK_EQ(4, force_set_get_count);
+ // Reenabling the interceptor should cause it to take precedence over
+ // the property
+ pass_on_get = false;
+ CHECK_EQ(3, global->Get(some_property)->Int32Value());
+ CHECK_EQ(1, force_set_set_count);
+ CHECK_EQ(5, force_set_get_count);
+ // The interceptor should also work for other properties
+ CHECK_EQ(3, global->Get(v8::String::New("b"))->Int32Value());
+ CHECK_EQ(1, force_set_set_count);
+ CHECK_EQ(6, force_set_get_count);
+}
diff --git a/deps/v8/test/cctest/test-assembler-arm.cc b/deps/v8/test/cctest/test-assembler-arm.cc
index bd75a04cc..fe1621c2a 100644
--- a/deps/v8/test/cctest/test-assembler-arm.cc
+++ b/deps/v8/test/cctest/test-assembler-arm.cc
@@ -29,8 +29,8 @@
#include "disassembler.h"
#include "factory.h"
-#include "simulator-arm.h"
-#include "assembler-arm-inl.h"
+#include "arm/simulator-arm.h"
+#include "arm/assembler-arm-inl.h"
#include "cctest.h"
using namespace v8::internal;
diff --git a/deps/v8/test/cctest/test-debug.cc b/deps/v8/test/cctest/test-debug.cc
index e482c7f1c..288efbaed 100644
--- a/deps/v8/test/cctest/test-debug.cc
+++ b/deps/v8/test/cctest/test-debug.cc
@@ -45,10 +45,13 @@ using ::v8::internal::JSGlobalProxy;
using ::v8::internal::Code;
using ::v8::internal::Debug;
using ::v8::internal::Debugger;
+using ::v8::internal::CommandMessage;
+using ::v8::internal::CommandMessageQueue;
using ::v8::internal::StepAction;
using ::v8::internal::StepIn; // From StepAction enum
using ::v8::internal::StepNext; // From StepAction enum
using ::v8::internal::StepOut; // From StepAction enum
+using ::v8::internal::Vector;
// Size of temp buffer for formatting small strings.
@@ -164,11 +167,22 @@ static v8::Local<v8::Function> CompileFunction(DebugLocalContext* env,
(*env)->Global()->Get(v8::String::New(function_name)));
}
+
+// Compile and run the supplied source and return the requested function.
+static v8::Local<v8::Function> CompileFunction(const char* source,
+ const char* function_name) {
+ v8::Script::Compile(v8::String::New(source))->Run();
+ return v8::Local<v8::Function>::Cast(
+ v8::Context::GetCurrent()->Global()->Get(v8::String::New(function_name)));
+}
+
+
// Helper function that compiles and runs the source.
static v8::Local<v8::Value> CompileRun(const char* source) {
return v8::Script::Compile(v8::String::New(source))->Run();
}
+
// Is there any debug info for the function?
static bool HasDebugInfo(v8::Handle<v8::Function> fun) {
Handle<v8::internal::JSFunction> f = v8::Utils::OpenHandle(*fun);
@@ -229,7 +243,7 @@ static int SetScriptBreakPointByIdFromJS(int script_id, int line, int column) {
v8::TryCatch try_catch;
v8::Handle<v8::String> str = v8::String::New(buffer.start());
v8::Handle<v8::Value> value = v8::Script::Compile(str)->Run();
- ASSERT(!try_catch.HasCaught());
+ CHECK(!try_catch.HasCaught());
return value->Int32Value();
}
}
@@ -256,7 +270,7 @@ static int SetScriptBreakPointByNameFromJS(const char* script_name,
v8::TryCatch try_catch;
v8::Handle<v8::String> str = v8::String::New(buffer.start());
v8::Handle<v8::Value> value = v8::Script::Compile(str)->Run();
- ASSERT(!try_catch.HasCaught());
+ CHECK(!try_catch.HasCaught());
return value->Int32Value();
}
}
@@ -525,6 +539,24 @@ const char* frame_source_column_source =
v8::Local<v8::Function> frame_source_column;
+// Source for The JavaScript function which picks out the script name for the
+// top frame.
+const char* frame_script_name_source =
+ "function frame_script_name(exec_state) {"
+ " return exec_state.frame(0).func().script().name();"
+ "}";
+v8::Local<v8::Function> frame_script_name;
+
+
+// Source for The JavaScript function which picks out the script data for the
+// top frame.
+const char* frame_script_data_source =
+ "function frame_script_data(exec_state) {"
+ " return exec_state.frame(0).func().script().data();"
+ "}";
+v8::Local<v8::Function> frame_script_data;
+
+
// Source for The JavaScript function which returns the number of frames.
static const char* frame_count_source =
"function frame_count(exec_state) {"
@@ -536,6 +568,11 @@ v8::Handle<v8::Function> frame_count;
// Global variable to store the last function hit - used by some tests.
char last_function_hit[80];
+// Global variable to store the name and data for last script hit - used by some
+// tests.
+char last_script_name_hit[80];
+char last_script_data_hit[80];
+
// Global variables to store the last source position - used by some tests.
int last_source_line = -1;
int last_source_column = -1;
@@ -586,6 +623,37 @@ static void DebugEventBreakPointHitCount(v8::DebugEvent event,
CHECK(result->IsNumber());
last_source_column = result->Int32Value();
}
+
+ if (!frame_script_name.IsEmpty()) {
+ // Get the script name of the function script.
+ const int argc = 1;
+ v8::Handle<v8::Value> argv[argc] = { exec_state };
+ v8::Handle<v8::Value> result = frame_script_name->Call(exec_state,
+ argc, argv);
+ if (result->IsUndefined()) {
+ last_script_name_hit[0] = '\0';
+ } else {
+ CHECK(result->IsString());
+ v8::Handle<v8::String> script_name(result->ToString());
+ script_name->WriteAscii(last_script_name_hit);
+ }
+ }
+
+ if (!frame_script_data.IsEmpty()) {
+ // Get the script data of the function script.
+ const int argc = 1;
+ v8::Handle<v8::Value> argv[argc] = { exec_state };
+ v8::Handle<v8::Value> result = frame_script_data->Call(exec_state,
+ argc, argv);
+ if (result->IsUndefined()) {
+ last_script_data_hit[0] = '\0';
+ } else {
+ result = result->ToString();
+ CHECK(result->IsString());
+ v8::Handle<v8::String> script_data(result->ToString());
+ script_data->WriteAscii(last_script_data_hit);
+ }
+ }
}
}
@@ -2120,6 +2188,53 @@ TEST(DebugStepLinear) {
}
+// Test of the stepping mechanism for keyed load in a loop.
+TEST(DebugStepKeyedLoadLoop) {
+ v8::HandleScope scope;
+ DebugLocalContext env;
+
+ // Create a function for testing stepping of keyed load. The statement 'y=1'
+ // is there to have more than one breakable statement in the loop, TODO(315).
+ v8::Local<v8::Function> foo = CompileFunction(
+ &env,
+ "function foo(a) {\n"
+ " var x;\n"
+ " var len = a.length;\n"
+ " for (var i = 0; i < len; i++) {\n"
+ " y = 1;\n"
+ " x = a[i];\n"
+ " }\n"
+ "}\n",
+ "foo");
+
+ // Create array [0,1,2,3,4,5,6,7,8,9]
+ v8::Local<v8::Array> a = v8::Array::New(10);
+ for (int i = 0; i < 10; i++) {
+ a->Set(v8::Number::New(i), v8::Number::New(i));
+ }
+
+ // Call function without any break points to ensure inlining is in place.
+ const int kArgc = 1;
+ v8::Handle<v8::Value> args[kArgc] = { a };
+ foo->Call(env->Global(), kArgc, args);
+
+ // Register a debug event listener which steps and counts.
+ v8::Debug::SetDebugEventListener(DebugEventStep);
+
+ // Setup break point and step through the function.
+ SetBreakPoint(foo, 3);
+ step_action = StepNext;
+ break_point_hit_count = 0;
+ foo->Call(env->Global(), kArgc, args);
+
+ // With stepping all break locations are hit.
+ CHECK_EQ(22, break_point_hit_count);
+
+ v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
+}
+
+
// Test the stepping mechanism with different ICs.
TEST(DebugStepLinearMixedICs) {
v8::HandleScope scope;
@@ -2841,9 +2956,11 @@ TEST(DebugBreak) {
v8::HandleScope scope;
DebugLocalContext env;
- // This test should be run with option --verify-heap. This is an ASSERT and
- // not a CHECK as --verify-heap is only available in debug mode.
- ASSERT(v8::internal::FLAG_verify_heap);
+ // This test should be run with option --verify-heap. As --verify-heap is
+ // only available in debug mode only check for it in that case.
+#ifdef DEBUG
+ CHECK(v8::internal::FLAG_verify_heap);
+#endif
// Register a debug event listener which sets the break flag and counts.
v8::Debug::SetDebugEventListener(DebugEventBreak);
@@ -3257,7 +3374,7 @@ ThreadBarrier::~ThreadBarrier() {
void ThreadBarrier::Wait() {
lock_->Lock();
- ASSERT(!invalid_);
+ CHECK(!invalid_);
if (num_blocked_ == num_threads_ - 1) {
// Signal and unblock all waiting threads.
for (int i = 0; i < num_threads_ - 1; ++i) {
@@ -3321,7 +3438,8 @@ class MessageQueueDebuggerThread : public v8::internal::Thread {
void Run();
};
-static void MessageHandler(const uint16_t* message, int length, void *data) {
+static void MessageHandler(const uint16_t* message, int length,
+ v8::Debug::ClientData* client_data) {
static char print_buffer[1000];
Utf16ToAscii(message, length, print_buffer);
if (IsBreakEventMessage(print_buffer)) {
@@ -3329,6 +3447,7 @@ static void MessageHandler(const uint16_t* message, int length, void *data) {
// Signals when a break is reported.
message_queue_barriers.semaphore_2->Signal();
}
+
// Allow message handler to block on a semaphore, to test queueing of
// messages while blocked.
message_queue_barriers.semaphore_1->Wait();
@@ -3336,7 +3455,6 @@ static void MessageHandler(const uint16_t* message, int length, void *data) {
fflush(stdout);
}
-
void MessageQueueDebuggerThread::Run() {
const int kBufferSize = 1000;
uint16_t buffer_1[kBufferSize];
@@ -3368,6 +3486,7 @@ void MessageQueueDebuggerThread::Run() {
/* Interleaved sequence of actions by the two threads:*/
// Main thread compiles and runs source_1
+ message_queue_barriers.semaphore_1->Signal();
message_queue_barriers.barrier_1.Wait();
// Post 6 commands, filling the command queue and making it expand.
// These calls return immediately, but the commands stay on the queue
@@ -3381,22 +3500,39 @@ void MessageQueueDebuggerThread::Run() {
v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_3, buffer_2));
message_queue_barriers.barrier_2.Wait();
// Main thread compiles and runs source_2.
- // Queued commands are executed at the start of compilation of source_2.
- message_queue_barriers.barrier_3.Wait();
- // Free the message handler to process all the messages from the queue.
- for (int i = 0; i < 20 ; ++i) {
+ // Queued commands are executed at the start of compilation of source_2(
+ // beforeCompile event).
+ // Free the message handler to process all the messages from the queue. 7
+ // messages are expected: 2 afterCompile events and 5 responses.
+ // All the commands added so far will fail to execute as long as call stack
+ // is empty on beforeCompile event.
+ for (int i = 0; i < 6 ; ++i) {
message_queue_barriers.semaphore_1->Signal();
}
+ message_queue_barriers.barrier_3.Wait();
// Main thread compiles and runs source_3.
+ // Don't stop in the afterCompile handler.
+ message_queue_barriers.semaphore_1->Signal();
// source_3 includes a debugger statement, which causes a break event.
// Wait on break event from hitting "debugger" statement
message_queue_barriers.semaphore_2->Wait();
// These should execute after the "debugger" statement in source_2
+ v8::Debug::SendCommand(buffer_1, AsciiToUtf16(command_1, buffer_1));
+ v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_2, buffer_2));
+ v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_3, buffer_2));
v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_single_step, buffer_2));
+ // Run after 2 break events, 4 responses.
+ for (int i = 0; i < 6 ; ++i) {
+ message_queue_barriers.semaphore_1->Signal();
+ }
// Wait on break event after a single step executes.
message_queue_barriers.semaphore_2->Wait();
v8::Debug::SendCommand(buffer_1, AsciiToUtf16(command_2, buffer_1));
v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_continue, buffer_2));
+ // Run after 2 responses.
+ for (int i = 0; i < 2 ; ++i) {
+ message_queue_barriers.semaphore_1->Signal();
+ }
// Main thread continues running source_3 to end, waits for this thread.
}
@@ -3427,6 +3563,117 @@ TEST(MessageQueues) {
fflush(stdout);
}
+
+class TestClientData : public v8::Debug::ClientData {
+ public:
+ TestClientData() {
+ constructor_call_counter++;
+ }
+ virtual ~TestClientData() {
+ destructor_call_counter++;
+ }
+
+ static void ResetCounters() {
+ constructor_call_counter = 0;
+ destructor_call_counter = 0;
+ }
+
+ static int constructor_call_counter;
+ static int destructor_call_counter;
+};
+
+int TestClientData::constructor_call_counter = 0;
+int TestClientData::destructor_call_counter = 0;
+
+
+// Tests that MessageQueue doesn't destroy client data when expands and
+// does destroy when it dies.
+TEST(MessageQueueExpandAndDestroy) {
+ TestClientData::ResetCounters();
+ { // Create a scope for the queue.
+ CommandMessageQueue queue(1);
+ queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
+ new TestClientData()));
+ queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
+ new TestClientData()));
+ queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
+ new TestClientData()));
+ CHECK_EQ(0, TestClientData::destructor_call_counter);
+ queue.Get().Dispose();
+ CHECK_EQ(1, TestClientData::destructor_call_counter);
+ queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
+ new TestClientData()));
+ queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
+ new TestClientData()));
+ queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
+ new TestClientData()));
+ queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
+ new TestClientData()));
+ queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
+ new TestClientData()));
+ CHECK_EQ(1, TestClientData::destructor_call_counter);
+ queue.Get().Dispose();
+ CHECK_EQ(2, TestClientData::destructor_call_counter);
+ }
+ // All the client data should be destroyed when the queue is destroyed.
+ CHECK_EQ(TestClientData::destructor_call_counter,
+ TestClientData::destructor_call_counter);
+}
+
+
+static int handled_client_data_instances_count = 0;
+static void MessageHandlerCountingClientData(
+ const v8::Debug::Message& message) {
+ if (message.GetClientData() != NULL) {
+ handled_client_data_instances_count++;
+ }
+}
+
+
+// Tests that all client data passed to the debugger are sent to the handler.
+TEST(SendClientDataToHandler) {
+ // Create a V8 environment
+ v8::HandleScope scope;
+ DebugLocalContext env;
+ TestClientData::ResetCounters();
+ handled_client_data_instances_count = 0;
+ v8::Debug::SetMessageHandler2(MessageHandlerCountingClientData);
+ const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5;";
+ const int kBufferSize = 1000;
+ uint16_t buffer[kBufferSize];
+ const char* command_1 =
+ "{\"seq\":117,"
+ "\"type\":\"request\","
+ "\"command\":\"evaluate\","
+ "\"arguments\":{\"expression\":\"1+2\"}}";
+ const char* command_2 =
+ "{\"seq\":118,"
+ "\"type\":\"request\","
+ "\"command\":\"evaluate\","
+ "\"arguments\":{\"expression\":\"1+a\"}}";
+ const char* command_continue =
+ "{\"seq\":106,"
+ "\"type\":\"request\","
+ "\"command\":\"continue\"}";
+
+ v8::Debug::SendCommand(buffer, AsciiToUtf16(command_1, buffer),
+ new TestClientData());
+ v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer), NULL);
+ v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer),
+ new TestClientData());
+ v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer),
+ new TestClientData());
+ // All the messages will be processed on beforeCompile event.
+ CompileRun(source_1);
+ v8::Debug::SendCommand(buffer, AsciiToUtf16(command_continue, buffer));
+ CHECK_EQ(3, TestClientData::constructor_call_counter);
+ CHECK_EQ(TestClientData::constructor_call_counter,
+ handled_client_data_instances_count);
+ CHECK_EQ(TestClientData::constructor_call_counter,
+ TestClientData::destructor_call_counter);
+}
+
+
/* Test ThreadedDebugging */
/* This test interrupts a running infinite loop that is
* occupying the v8 thread by a break command from the
@@ -3453,10 +3700,10 @@ static v8::Handle<v8::Value> ThreadedAtBarrier1(const v8::Arguments& args) {
}
-static void ThreadedMessageHandler(const uint16_t* message, int length,
- void *data) {
+static void ThreadedMessageHandler(const v8::Debug::Message& message) {
static char print_buffer[1000];
- Utf16ToAscii(message, length, print_buffer);
+ v8::String::Value json(message.GetJSON());
+ Utf16ToAscii(*json, json.length(), print_buffer);
if (IsBreakEventMessage(print_buffer)) {
threaded_debugging_barriers.barrier_2.Wait();
}
@@ -3487,7 +3734,7 @@ void V8Thread::Run() {
v8::HandleScope scope;
DebugLocalContext env;
- v8::Debug::SetMessageHandler(&ThreadedMessageHandler);
+ v8::Debug::SetMessageHandler2(&ThreadedMessageHandler);
v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
global_template->Set(v8::String::New("ThreadedAtBarrier1"),
v8::FunctionTemplate::New(ThreadedAtBarrier1));
@@ -3550,11 +3797,10 @@ class BreakpointsDebuggerThread : public v8::internal::Thread {
Barriers* breakpoints_barriers;
-static void BreakpointsMessageHandler(const uint16_t* message,
- int length,
- void *data) {
+static void BreakpointsMessageHandler(const v8::Debug::Message& message) {
static char print_buffer[1000];
- Utf16ToAscii(message, length, print_buffer);
+ v8::String::Value json(message.GetJSON());
+ Utf16ToAscii(*json, json.length(), print_buffer);
printf("%s\n", print_buffer);
fflush(stdout);
@@ -3588,7 +3834,7 @@ void BreakpointsV8Thread::Run() {
v8::HandleScope scope;
DebugLocalContext env;
- v8::Debug::SetMessageHandler(&BreakpointsMessageHandler);
+ v8::Debug::SetMessageHandler2(&BreakpointsMessageHandler);
CompileRun(source_1);
breakpoints_barriers->barrier_1.Wait();
@@ -3697,13 +3943,12 @@ TEST(SetDebugEventListenerOnUninitializedVM) {
}
-static void DummyMessageHandler(const uint16_t* message,
- int length, void *data) {
+static void DummyMessageHandler(const v8::Debug::Message& message) {
}
TEST(SetMessageHandlerOnUninitializedVM) {
- v8::Debug::SetMessageHandler(DummyMessageHandler);
+ v8::Debug::SetMessageHandler2(DummyMessageHandler);
}
@@ -3923,8 +4168,7 @@ TEST(DebuggerUnload) {
// Debugger message handler which counts the number of times it is called.
static int message_handler_hit_count = 0;
-static void MessageHandlerHitCount(const uint16_t* message,
- int length, void* data) {
+static void MessageHandlerHitCount(const v8::Debug::Message& message) {
message_handler_hit_count++;
const int kBufferSize = 1000;
@@ -3947,7 +4191,7 @@ TEST(DebuggerClearMessageHandler) {
CheckDebuggerUnloaded();
// Set a debug message handler.
- v8::Debug::SetMessageHandler(MessageHandlerHitCount);
+ v8::Debug::SetMessageHandler2(MessageHandlerHitCount);
// Run code to throw a unhandled exception. This should end up in the message
// handler.
@@ -3972,9 +4216,8 @@ TEST(DebuggerClearMessageHandler) {
// Debugger message handler which clears the message handler while active.
-static void MessageHandlerClearingMessageHandler(const uint16_t* message,
- int length,
- void* data) {
+static void MessageHandlerClearingMessageHandler(
+ const v8::Debug::Message& message) {
message_handler_hit_count++;
// Clear debug message handler.
@@ -3991,7 +4234,7 @@ TEST(DebuggerClearMessageHandlerWhileActive) {
CheckDebuggerUnloaded();
// Set a debug message handler.
- v8::Debug::SetMessageHandler(MessageHandlerClearingMessageHandler);
+ v8::Debug::SetMessageHandler2(MessageHandlerClearingMessageHandler);
// Run code to throw a unhandled exception. This should end up in the message
// handler.
@@ -4004,54 +4247,106 @@ TEST(DebuggerClearMessageHandlerWhileActive) {
}
-int host_dispatch_hit_count = 0;
-static void HostDispatchHandlerHitCount(void* dispatch, void *data) {
- host_dispatch_hit_count++;
+/* Test DebuggerHostDispatch */
+/* In this test, the debugger waits for a command on a breakpoint
+ * and is dispatching host commands while in the infinite loop.
+ */
+
+class HostDispatchV8Thread : public v8::internal::Thread {
+ public:
+ void Run();
+};
+
+class HostDispatchDebuggerThread : public v8::internal::Thread {
+ public:
+ void Run();
+};
+
+Barriers* host_dispatch_barriers;
+
+static void HostDispatchMessageHandler(const v8::Debug::Message& message) {
+ static char print_buffer[1000];
+ v8::String::Value json(message.GetJSON());
+ Utf16ToAscii(*json, json.length(), print_buffer);
+ printf("%s\n", print_buffer);
+ fflush(stdout);
}
-// Test that clearing the debug event listener actually clears all break points
-// and related information.
-TEST(DebuggerHostDispatch) {
- i::FLAG_debugger_auto_break = true;
+static void HostDispatchDispatchHandler() {
+ host_dispatch_barriers->semaphore_1->Signal();
+}
+
+
+void HostDispatchV8Thread::Run() {
+ const char* source_1 = "var y_global = 3;\n"
+ "function cat( new_value ) {\n"
+ " var x = new_value;\n"
+ " y_global = 4;\n"
+ " x = 3 * x + 1;\n"
+ " y_global = 5;\n"
+ " return x;\n"
+ "}\n"
+ "\n";
+ const char* source_2 = "cat(17);\n";
v8::HandleScope scope;
DebugLocalContext env;
- const int kBufferSize = 1000;
- uint16_t buffer[kBufferSize];
- const char* command_continue =
- "{\"seq\":0,"
- "\"type\":\"request\","
- "\"command\":\"continue\"}";
+ // Setup message and host dispatch handlers.
+ v8::Debug::SetMessageHandler2(HostDispatchMessageHandler);
+ v8::Debug::SetHostDispatchHandler(HostDispatchDispatchHandler, 10 /* ms */);
- // Create an empty function to call for processing debug commands
- v8::Local<v8::Function> empty =
- CompileFunction(&env, "function empty(){}", "empty");
+ CompileRun(source_1);
+ host_dispatch_barriers->barrier_1.Wait();
+ host_dispatch_barriers->barrier_2.Wait();
+ CompileRun(source_2);
+}
- // Setup message and host dispatch handlers.
- v8::Debug::SetMessageHandler(DummyMessageHandler);
- v8::Debug::SetHostDispatchHandler(HostDispatchHandlerHitCount,
- NULL);
- // Send a host dispatch by itself.
- v8::Debug::SendHostDispatch(NULL);
- empty->Call(env->Global(), 0, NULL); // Run JavaScript to activate debugger.
- CHECK_EQ(1, host_dispatch_hit_count);
+void HostDispatchDebuggerThread::Run() {
+ const int kBufSize = 1000;
+ uint16_t buffer[kBufSize];
- // Fill a host dispatch and a continue command on the command queue.
- v8::Debug::SendHostDispatch(NULL);
- v8::Debug::SendCommand(buffer, AsciiToUtf16(command_continue, buffer));
- empty->Call(env->Global(), 0, NULL); // Run JavaScript to activate debugger.
+ const char* command_1 = "{\"seq\":101,"
+ "\"type\":\"request\","
+ "\"command\":\"setbreakpoint\","
+ "\"arguments\":{\"type\":\"function\",\"target\":\"cat\",\"line\":3}}";
+ const char* command_2 = "{\"seq\":102,"
+ "\"type\":\"request\","
+ "\"command\":\"continue\"}";
- // Fill a continue command and a host dispatch on the command queue.
- v8::Debug::SendCommand(buffer, AsciiToUtf16(command_continue, buffer));
- v8::Debug::SendHostDispatch(NULL);
- empty->Call(env->Global(), 0, NULL); // Run JavaScript to activate debugger.
- empty->Call(env->Global(), 0, NULL); // Run JavaScript to activate debugger.
+ // v8 thread initializes, runs source_1
+ host_dispatch_barriers->barrier_1.Wait();
+ // 1: Set breakpoint in cat().
+ v8::Debug::SendCommand(buffer, AsciiToUtf16(command_1, buffer));
+
+ host_dispatch_barriers->barrier_2.Wait();
+ // v8 thread starts compiling source_2.
+ // Break happens, to run queued commands and host dispatches.
+ // Wait for host dispatch to be processed.
+ host_dispatch_barriers->semaphore_1->Wait();
+ // 2: Continue evaluation
+ v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer));
+}
+
+HostDispatchDebuggerThread host_dispatch_debugger_thread;
+HostDispatchV8Thread host_dispatch_v8_thread;
+
+
+TEST(DebuggerHostDispatch) {
+ i::FLAG_debugger_auto_break = true;
+
+ // Create a V8 environment
+ Barriers stack_allocated_host_dispatch_barriers;
+ stack_allocated_host_dispatch_barriers.Initialize();
+ host_dispatch_barriers = &stack_allocated_host_dispatch_barriers;
- // All the host dispatch callback should be called.
- CHECK_EQ(3, host_dispatch_hit_count);
+ host_dispatch_v8_thread.Start();
+ host_dispatch_debugger_thread.Start();
+
+ host_dispatch_v8_thread.Join();
+ host_dispatch_debugger_thread.Join();
}
@@ -4249,3 +4544,139 @@ TEST(DebugGetLoadedScripts) {
// Must not crash while accessing line_ends.
i::FLAG_allow_natives_syntax = allow_natives_syntax;
}
+
+
+// Test script break points set on lines.
+TEST(ScriptNameAndData) {
+ v8::HandleScope scope;
+ DebugLocalContext env;
+ env.ExposeDebug();
+
+ // Create functions for retrieving script name and data for the function on
+ // the top frame when hitting a break point.
+ frame_script_name = CompileFunction(&env,
+ frame_script_name_source,
+ "frame_script_name");
+ frame_script_data = CompileFunction(&env,
+ frame_script_data_source,
+ "frame_script_data");
+
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+ v8::Undefined());
+
+ // Test function source.
+ v8::Local<v8::String> script = v8::String::New(
+ "function f() {\n"
+ " debugger;\n"
+ "}\n");
+
+ v8::ScriptOrigin origin1 = v8::ScriptOrigin(v8::String::New("name"));
+ v8::Handle<v8::Script> script1 = v8::Script::Compile(script, &origin1);
+ script1->SetData(v8::String::New("data"));
+ script1->Run();
+ v8::Script::Compile(script, &origin1)->Run();
+ v8::Local<v8::Function> f;
+ f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+
+ f->Call(env->Global(), 0, NULL);
+ CHECK_EQ(1, break_point_hit_count);
+ CHECK_EQ("name", last_script_name_hit);
+ CHECK_EQ("data", last_script_data_hit);
+
+ v8::Local<v8::String> data_obj_source = v8::String::New(
+ "({ a: 'abc',\n"
+ " b: 123,\n"
+ " toString: function() { return this.a + ' ' + this.b; }\n"
+ "})\n");
+ v8::Local<v8::Value> data_obj = v8::Script::Compile(data_obj_source)->Run();
+ v8::ScriptOrigin origin2 = v8::ScriptOrigin(v8::String::New("new name"));
+ v8::Handle<v8::Script> script2 = v8::Script::Compile(script, &origin2);
+ script2->Run();
+ script2->SetData(data_obj);
+ f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+ f->Call(env->Global(), 0, NULL);
+ CHECK_EQ(2, break_point_hit_count);
+ CHECK_EQ("new name", last_script_name_hit);
+ CHECK_EQ("abc 123", last_script_data_hit);
+}
+
+
+static v8::Persistent<v8::Context> expected_context;
+static v8::Handle<v8::Value> expected_context_data;
+
+
+// Check that the expected context is the one generating the debug event.
+static void ContextCheckMessageHandler(const v8::Debug::Message& message) {
+ CHECK(message.GetEventContext() == expected_context);
+ CHECK(message.GetEventContext()->GetData()->StrictEquals(
+ expected_context_data));
+ message_handler_hit_count++;
+
+ const int kBufferSize = 1000;
+ uint16_t buffer[kBufferSize];
+ const char* command_continue =
+ "{\"seq\":0,"
+ "\"type\":\"request\","
+ "\"command\":\"continue\"}";
+
+ // Send a continue command for break events.
+ if (message.GetEvent() == v8::Break) {
+ v8::Debug::SendCommand(buffer, AsciiToUtf16(command_continue, buffer));
+ }
+}
+
+
+// Test which creates two contexts and sets different embedder data on each.
+// Checks that this data is set correctly and that when the debug message
+// handler is called the expected context is the one active.
+TEST(ContextData) {
+ v8::HandleScope scope;
+
+ v8::Debug::SetMessageHandler2(ContextCheckMessageHandler);
+
+ // Create two contexts.
+ v8::Persistent<v8::Context> context_1;
+ v8::Persistent<v8::Context> context_2;
+ v8::Handle<v8::ObjectTemplate> global_template =
+ v8::Handle<v8::ObjectTemplate>();
+ v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>();
+ context_1 = v8::Context::New(NULL, global_template, global_object);
+ context_2 = v8::Context::New(NULL, global_template, global_object);
+
+ // Default data value is undefined.
+ CHECK(context_1->GetData()->IsUndefined());
+ CHECK(context_2->GetData()->IsUndefined());
+
+ // Set and check different data values.
+ v8::Handle<v8::Value> data_1 = v8::Number::New(1);
+ v8::Handle<v8::Value> data_2 = v8::String::New("2");
+ context_1->SetData(data_1);
+ context_2->SetData(data_2);
+ CHECK(context_1->GetData()->StrictEquals(data_1));
+ CHECK(context_2->GetData()->StrictEquals(data_2));
+
+ // Simple test function which causes a break.
+ const char* source = "function f() { debugger; }";
+
+ // Enter and run function in the first context.
+ {
+ v8::Context::Scope context_scope(context_1);
+ expected_context = context_1;
+ expected_context_data = data_1;
+ v8::Local<v8::Function> f = CompileFunction(source, "f");
+ f->Call(context_1->Global(), 0, NULL);
+ }
+
+
+ // Enter and run function in the second context.
+ {
+ v8::Context::Scope context_scope(context_2);
+ expected_context = context_2;
+ expected_context_data = data_2;
+ v8::Local<v8::Function> f = CompileFunction(source, "f");
+ f->Call(context_2->Global(), 0, NULL);
+ }
+
+ // Two times compile event and two times break event.
+ CHECK_GT(message_handler_hit_count, 4);
+}
diff --git a/deps/v8/test/cctest/test-decls.cc b/deps/v8/test/cctest/test-decls.cc
index e798fee9b..ecdad2e7d 100644
--- a/deps/v8/test/cctest/test-decls.cc
+++ b/deps/v8/test/cctest/test-decls.cc
@@ -389,7 +389,7 @@ class AppearingPropertyContext: public DeclarationContext {
state_ = UNKNOWN;
return True();
default:
- ASSERT(state_ == UNKNOWN);
+ CHECK(state_ == UNKNOWN);
break;
}
// Do the lookup in the object.
@@ -479,7 +479,7 @@ class ReappearingPropertyContext: public DeclarationContext {
state_ = UNKNOWN;
return False();
default:
- ASSERT(state_ == UNKNOWN);
+ CHECK(state_ == UNKNOWN);
break;
}
// Do the lookup in the object.
diff --git a/deps/v8/test/cctest/test-func-name-inference.cc b/deps/v8/test/cctest/test-func-name-inference.cc
index 505862984..d91f75fa0 100644
--- a/deps/v8/test/cctest/test-func-name-inference.cc
+++ b/deps/v8/test/cctest/test-func-name-inference.cc
@@ -221,3 +221,30 @@ TEST(AsParameter) {
CheckFunctionName(script, "return 2", "");
CheckFunctionName(script, "return 3", "");
}
+
+
+TEST(MultipleFuncsConditional) {
+ InitializeVM();
+ v8::HandleScope scope;
+
+ v8::Handle<v8::Script> script = Compile(
+ "fun1 = 0 ?\n"
+ " function() { return 1; } :\n"
+ " function() { return 2; }");
+ CheckFunctionName(script, "return 1", "fun1");
+ CheckFunctionName(script, "return 2", "fun1");
+}
+
+
+TEST(MultipleFuncsInLiteral) {
+ InitializeVM();
+ v8::HandleScope scope;
+
+ v8::Handle<v8::Script> script = Compile(
+ "function MyClass() {}\n"
+ "MyClass.prototype = {\n"
+ " method1: 0 ? function() { return 1; } :\n"
+ " function() { return 2; } }");
+ CheckFunctionName(script, "return 1", "MyClass.method1");
+ CheckFunctionName(script, "return 2", "MyClass.method1");
+}
diff --git a/deps/v8/test/cctest/test-hashmap.cc b/deps/v8/test/cctest/test-hashmap.cc
index 4918d5d52..954dbe103 100644
--- a/deps/v8/test/cctest/test-hashmap.cc
+++ b/deps/v8/test/cctest/test-hashmap.cc
@@ -43,7 +43,7 @@ class IntSet {
IntSet() : map_(DefaultMatchFun) {}
void Insert(int x) {
- ASSERT(x != 0); // 0 corresponds to (void*)NULL - illegal key value
+ CHECK_NE(0, x); // 0 corresponds to (void*)NULL - illegal key value
HashMap::Entry* p = map_.Lookup(reinterpret_cast<void*>(x), Hash(x), true);
CHECK(p != NULL); // insert is set!
CHECK_EQ(reinterpret_cast<void*>(x), p->key);
diff --git a/deps/v8/test/cctest/test-list.cc b/deps/v8/test/cctest/test-list.cc
index d10cdd7de..838a45d0d 100644
--- a/deps/v8/test/cctest/test-list.cc
+++ b/deps/v8/test/cctest/test-list.cc
@@ -63,5 +63,5 @@ TEST(ListAdd) {
// Add an existing element, the backing store should have to grow.
list.Add(list[0]);
- ASSERT(list[4] == 1);
+ CHECK_EQ(1, list[4]);
}
diff --git a/deps/v8/test/cctest/test-log-ia32.cc b/deps/v8/test/cctest/test-log-ia32.cc
index b171339c2..43cb294b1 100644
--- a/deps/v8/test/cctest/test-log-ia32.cc
+++ b/deps/v8/test/cctest/test-log-ia32.cc
@@ -8,9 +8,11 @@
#include "v8.h"
+#include "codegen.h"
#include "log.h"
#include "top.h"
#include "cctest.h"
+#include "disassembler.h"
using v8::Function;
using v8::Local;
@@ -20,12 +22,15 @@ using v8::String;
using v8::Value;
using v8::internal::byte;
+using v8::internal::Address;
using v8::internal::Handle;
using v8::internal::JSFunction;
using v8::internal::StackTracer;
using v8::internal::TickSample;
using v8::internal::Top;
+namespace i = v8::internal;
+
static v8::Persistent<v8::Context> env;
@@ -42,8 +47,8 @@ static void InitTraceEnv(StackTracer* tracer, TickSample* sample) {
}
-static void DoTrace(unsigned int fp) {
- trace_env.sample->fp = fp;
+static void DoTrace(Address fp) {
+ trace_env.sample->fp = reinterpret_cast<uintptr_t>(fp);
// sp is only used to define stack high bound
trace_env.sample->sp =
reinterpret_cast<unsigned int>(trace_env.sample) - 10240;
@@ -53,7 +58,7 @@ static void DoTrace(unsigned int fp) {
// Hide c_entry_fp to emulate situation when sampling is done while
// pure JS code is being executed
-static void DoTraceHideCEntryFPAddress(unsigned int fp) {
+static void DoTraceHideCEntryFPAddress(Address fp) {
v8::internal::Address saved_c_frame_fp = *(Top::c_entry_fp_address());
CHECK(saved_c_frame_fp);
*(Top::c_entry_fp_address()) = 0;
@@ -63,10 +68,10 @@ static void DoTraceHideCEntryFPAddress(unsigned int fp) {
static void CheckRetAddrIsInFunction(const char* func_name,
- unsigned int ret_addr,
- unsigned int func_start_addr,
+ Address ret_addr,
+ Address func_start_addr,
unsigned int func_len) {
- printf("CheckRetAddrIsInFunction \"%s\": %08x %08x %08x\n",
+ printf("CheckRetAddrIsInFunction \"%s\": %p %p %p\n",
func_name, func_start_addr, ret_addr, func_start_addr + func_len);
CHECK_GE(ret_addr, func_start_addr);
CHECK_GE(func_start_addr + func_len, ret_addr);
@@ -74,12 +79,12 @@ static void CheckRetAddrIsInFunction(const char* func_name,
static void CheckRetAddrIsInJSFunction(const char* func_name,
- unsigned int ret_addr,
+ Address ret_addr,
Handle<JSFunction> func) {
v8::internal::Code* func_code = func->code();
CheckRetAddrIsInFunction(
func_name, ret_addr,
- reinterpret_cast<unsigned int>(func_code->instruction_start()),
+ func_code->instruction_start(),
func_code->ExecutableSize());
}
@@ -94,7 +99,7 @@ class TraceExtension : public v8::Extension {
static v8::Handle<v8::Value> Trace(const v8::Arguments& args);
static v8::Handle<v8::Value> JSTrace(const v8::Arguments& args);
private:
- static unsigned int GetFP(const v8::Arguments& args);
+ static Address GetFP(const v8::Arguments& args);
static const char* kSource;
};
@@ -117,10 +122,10 @@ v8::Handle<v8::FunctionTemplate> TraceExtension::GetNativeFunction(
}
-unsigned int TraceExtension::GetFP(const v8::Arguments& args) {
+Address TraceExtension::GetFP(const v8::Arguments& args) {
CHECK_EQ(1, args.Length());
- unsigned int fp = args[0]->Int32Value() << 2;
- printf("Trace: %08x\n", fp);
+ Address fp = reinterpret_cast<Address>(args[0]->Int32Value() << 2);
+ printf("Trace: %p\n", fp);
return fp;
}
@@ -177,7 +182,7 @@ static Handle<JSFunction> GetGlobalJSFunction(const char* name) {
static void CheckRetAddrIsInJSFunction(const char* func_name,
- unsigned int ret_addr) {
+ Address ret_addr) {
CheckRetAddrIsInJSFunction(func_name, ret_addr,
GetGlobalJSFunction(func_name));
}
@@ -188,47 +193,59 @@ static void SetGlobalProperty(const char* name, Local<Value> value) {
}
-static bool Patch(byte* from,
- size_t num,
- byte* original,
- byte* patch,
- size_t patch_len) {
- byte* to = from + num;
- do {
- from = static_cast<byte*>(memchr(from, *original, to - from));
- CHECK(from != NULL);
- if (memcmp(original, from, patch_len) == 0) {
- memcpy(from, patch, patch_len);
- return true;
- } else {
- from++;
- }
- } while (to - from > 0);
- return false;
+static Handle<v8::internal::String> NewString(const char* s) {
+ return i::Factory::NewStringFromAscii(i::CStrVector(s));
}
+namespace v8 { namespace internal {
+
+class CodeGeneratorPatcher {
+ public:
+ CodeGeneratorPatcher() {
+ CodeGenerator::InlineRuntimeLUT genGetFramePointer =
+ {&CodeGenerator::GenerateGetFramePointer, "_GetFramePointer"};
+ // _FastCharCodeAt is not used in our tests.
+ bool result = CodeGenerator::PatchInlineRuntimeEntry(
+ NewString("_FastCharCodeAt"),
+ genGetFramePointer, &oldInlineEntry);
+ CHECK(result);
+ }
+
+ ~CodeGeneratorPatcher() {
+ CHECK(CodeGenerator::PatchInlineRuntimeEntry(
+ NewString("_GetFramePointer"),
+ oldInlineEntry, NULL));
+ }
+
+ private:
+ CodeGenerator::InlineRuntimeLUT oldInlineEntry;
+};
+
+} } // namespace v8::internal
+
+
// Creates a global function named 'func_name' that calls the tracing
// function 'trace_func_name' with an actual EBP register value,
// shifted right to be presented as Smi.
static void CreateTraceCallerFunction(const char* func_name,
const char* trace_func_name) {
- ::v8::internal::EmbeddedVector<char, 256> trace_call_buf;
- ::v8::internal::OS::SNPrintF(trace_call_buf, "%s(0x6666);", trace_func_name);
+ i::EmbeddedVector<char, 256> trace_call_buf;
+ i::OS::SNPrintF(trace_call_buf, "%s(%%_GetFramePointer());", trace_func_name);
+
+ // Compile the script.
+ i::CodeGeneratorPatcher patcher;
+ bool allow_natives_syntax = i::FLAG_allow_natives_syntax;
+ i::FLAG_allow_natives_syntax = true;
Handle<JSFunction> func = CompileFunction(trace_call_buf.start());
CHECK(!func.is_null());
+ i::FLAG_allow_natives_syntax = allow_natives_syntax;
+
+#ifdef DEBUG
v8::internal::Code* func_code = func->code();
CHECK(func_code->IsCode());
-
- // push 0xcccc (= 0x6666 << 1)
- byte original[] = { 0x68, 0xcc, 0xcc, 0x00, 0x00 };
- // mov eax,ebp; shr eax; push eax;
- byte patch[] = { 0x89, 0xe8, 0xd1, 0xe8, 0x50 };
- // Patch generated code to replace pushing of a constant with
- // pushing of ebp contents in a Smi
- CHECK(Patch(func_code->instruction_start(),
- func_code->instruction_size(),
- original, patch, sizeof(patch)));
+ func_code->Print();
+#endif
SetGlobalProperty(func_name, v8::ToApi<Value>(func));
}
@@ -236,7 +253,7 @@ static void CreateTraceCallerFunction(const char* func_name,
TEST(CFromJSStackTrace) {
TickSample sample;
- StackTracer tracer(reinterpret_cast<unsigned int>(&sample));
+ StackTracer tracer(reinterpret_cast<uintptr_t>(&sample));
InitTraceEnv(&tracer, &sample);
InitializeVM();
@@ -244,21 +261,21 @@ TEST(CFromJSStackTrace) {
CreateTraceCallerFunction("JSFuncDoTrace", "trace");
CompileRun(
"function JSTrace() {"
- " JSFuncDoTrace();"
+ " JSFuncDoTrace();"
"};\n"
"JSTrace();");
CHECK_GT(sample.frames_count, 1);
// Stack sampling will start from the first JS function, i.e. "JSFuncDoTrace"
CheckRetAddrIsInJSFunction("JSFuncDoTrace",
- reinterpret_cast<unsigned int>(sample.stack[0]));
+ sample.stack[0]);
CheckRetAddrIsInJSFunction("JSTrace",
- reinterpret_cast<unsigned int>(sample.stack[1]));
+ sample.stack[1]);
}
TEST(PureJSStackTrace) {
TickSample sample;
- StackTracer tracer(reinterpret_cast<unsigned int>(&sample));
+ StackTracer tracer(reinterpret_cast<uintptr_t>(&sample));
InitTraceEnv(&tracer, &sample);
InitializeVM();
@@ -266,25 +283,25 @@ TEST(PureJSStackTrace) {
CreateTraceCallerFunction("JSFuncDoTrace", "js_trace");
CompileRun(
"function JSTrace() {"
- " JSFuncDoTrace();"
+ " JSFuncDoTrace();"
"};\n"
"function OuterJSTrace() {"
- " JSTrace();"
+ " JSTrace();"
"};\n"
"OuterJSTrace();");
CHECK_GT(sample.frames_count, 1);
// Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace"
CheckRetAddrIsInJSFunction("JSTrace",
- reinterpret_cast<unsigned int>(sample.stack[0]));
+ sample.stack[0]);
CheckRetAddrIsInJSFunction("OuterJSTrace",
- reinterpret_cast<unsigned int>(sample.stack[1]));
+ sample.stack[1]);
}
static void CFuncDoTrace() {
- unsigned int fp;
+ Address fp;
#ifdef __GNUC__
- fp = reinterpret_cast<unsigned int>(__builtin_frame_address(0));
+ fp = reinterpret_cast<Address>(__builtin_frame_address(0));
#elif defined _MSC_VER
__asm mov [fp], ebp // NOLINT
#endif
@@ -304,7 +321,7 @@ static int CFunc(int depth) {
TEST(PureCStackTrace) {
TickSample sample;
- StackTracer tracer(reinterpret_cast<unsigned int>(&sample));
+ StackTracer tracer(reinterpret_cast<uintptr_t>(&sample));
InitTraceEnv(&tracer, &sample);
// Check that sampler doesn't crash
CHECK_EQ(10, CFunc(10));
diff --git a/deps/v8/test/cctest/test-log.cc b/deps/v8/test/cctest/test-log.cc
new file mode 100644
index 000000000..6a7e54f1d
--- /dev/null
+++ b/deps/v8/test/cctest/test-log.cc
@@ -0,0 +1,117 @@
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
+//
+// Tests of logging functions from log.h
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+
+#include "v8.h"
+
+#include "log.h"
+
+#include "cctest.h"
+
+using v8::internal::Logger;
+
+static void SetUp() {
+ // Log to memory buffer.
+ v8::internal::FLAG_logfile = "*";
+ v8::internal::FLAG_log = true;
+ Logger::Setup();
+}
+
+static void TearDown() {
+ Logger::TearDown();
+}
+
+
+TEST(EmptyLog) {
+ SetUp();
+ CHECK_EQ(0, Logger::GetLogLines(0, NULL, 0));
+ CHECK_EQ(0, Logger::GetLogLines(100, NULL, 0));
+ CHECK_EQ(0, Logger::GetLogLines(0, NULL, 100));
+ CHECK_EQ(0, Logger::GetLogLines(100, NULL, 100));
+ TearDown();
+}
+
+
+TEST(GetMessages) {
+ SetUp();
+ Logger::StringEvent("aaa", "bbb");
+ Logger::StringEvent("cccc", "dddd");
+ CHECK_EQ(0, Logger::GetLogLines(0, NULL, 0));
+ char log_lines[100];
+ memset(log_lines, 0, sizeof(log_lines));
+ // Requesting data size which is smaller than first log message length.
+ CHECK_EQ(0, Logger::GetLogLines(0, log_lines, 3));
+ // See Logger::StringEvent.
+ const char* line_1 = "aaa,\"bbb\"\n";
+ const int line_1_len = strlen(line_1);
+ // Still smaller than log message length.
+ CHECK_EQ(0, Logger::GetLogLines(0, log_lines, line_1_len - 1));
+ // The exact size.
+ CHECK_EQ(line_1_len, Logger::GetLogLines(0, log_lines, line_1_len));
+ CHECK_EQ(line_1, log_lines);
+ memset(log_lines, 0, sizeof(log_lines));
+ // A bit more than the first line length.
+ CHECK_EQ(line_1_len, Logger::GetLogLines(0, log_lines, line_1_len + 3));
+ CHECK_EQ(line_1, log_lines);
+ memset(log_lines, 0, sizeof(log_lines));
+ const char* line_2 = "cccc,\"dddd\"\n";
+ const int line_2_len = strlen(line_2);
+ // Now start with line_2 beginning.
+ CHECK_EQ(0, Logger::GetLogLines(line_1_len, log_lines, 0));
+ CHECK_EQ(0, Logger::GetLogLines(line_1_len, log_lines, 3));
+ CHECK_EQ(0, Logger::GetLogLines(line_1_len, log_lines, line_2_len - 1));
+ CHECK_EQ(line_2_len, Logger::GetLogLines(line_1_len, log_lines, line_2_len));
+ CHECK_EQ(line_2, log_lines);
+ memset(log_lines, 0, sizeof(log_lines));
+ CHECK_EQ(line_2_len,
+ Logger::GetLogLines(line_1_len, log_lines, line_2_len + 3));
+ CHECK_EQ(line_2, log_lines);
+ memset(log_lines, 0, sizeof(log_lines));
+ // Now get entire buffer contents.
+ const char* all_lines = "aaa,\"bbb\"\ncccc,\"dddd\"\n";
+ const int all_lines_len = strlen(all_lines);
+ CHECK_EQ(all_lines_len, Logger::GetLogLines(0, log_lines, all_lines_len));
+ CHECK_EQ(all_lines, log_lines);
+ memset(log_lines, 0, sizeof(log_lines));
+ CHECK_EQ(all_lines_len, Logger::GetLogLines(0, log_lines, all_lines_len + 3));
+ CHECK_EQ(all_lines, log_lines);
+ memset(log_lines, 0, sizeof(log_lines));
+ TearDown();
+}
+
+
+TEST(BeyondWritePosition) {
+ SetUp();
+ Logger::StringEvent("aaa", "bbb");
+ Logger::StringEvent("cccc", "dddd");
+ // See Logger::StringEvent.
+ const char* all_lines = "aaa,\"bbb\"\ncccc,\"dddd\"\n";
+ const int all_lines_len = strlen(all_lines);
+ CHECK_EQ(0, Logger::GetLogLines(all_lines_len, NULL, 1));
+ CHECK_EQ(0, Logger::GetLogLines(all_lines_len, NULL, 100));
+ CHECK_EQ(0, Logger::GetLogLines(all_lines_len + 1, NULL, 1));
+ CHECK_EQ(0, Logger::GetLogLines(all_lines_len + 1, NULL, 100));
+ CHECK_EQ(0, Logger::GetLogLines(all_lines_len + 100, NULL, 1));
+ CHECK_EQ(0, Logger::GetLogLines(all_lines_len + 100, NULL, 100));
+ CHECK_EQ(0, Logger::GetLogLines(10 * 1024 * 1024, NULL, 1));
+ CHECK_EQ(0, Logger::GetLogLines(10 * 1024 * 1024, NULL, 100));
+ TearDown();
+}
+
+
+TEST(MemoryLoggingTurnedOff) {
+ // Log to stdout
+ v8::internal::FLAG_logfile = "-";
+ v8::internal::FLAG_log = true;
+ Logger::Setup();
+ CHECK_EQ(0, Logger::GetLogLines(0, NULL, 0));
+ CHECK_EQ(0, Logger::GetLogLines(100, NULL, 0));
+ CHECK_EQ(0, Logger::GetLogLines(0, NULL, 100));
+ CHECK_EQ(0, Logger::GetLogLines(100, NULL, 100));
+ Logger::TearDown();
+}
+
+
+#endif // ENABLE_LOGGING_AND_PROFILING
diff --git a/deps/v8/test/cctest/test-regexp.cc b/deps/v8/test/cctest/test-regexp.cc
index afd967900..8761cf51b 100644
--- a/deps/v8/test/cctest/test-regexp.cc
+++ b/deps/v8/test/cctest/test-regexp.cc
@@ -27,7 +27,6 @@
#include <stdlib.h>
-#include <set>
#include "v8.h"
@@ -39,11 +38,15 @@
#include "jsregexp-inl.h"
#include "regexp-macro-assembler.h"
#include "regexp-macro-assembler-irregexp.h"
-#ifdef ARM
-#include "regexp-macro-assembler-arm.h"
-#else // IA32
-#include "macro-assembler-ia32.h"
-#include "regexp-macro-assembler-ia32.h"
+#ifdef V8_TARGET_ARCH_ARM
+#include "arm/regexp-macro-assembler-arm.h"
+#endif
+#ifdef V8_TARGET_ARCH_X64
+// No X64-implementation yet.
+#endif
+#ifdef V8_TARGET_ARCH_IA32
+#include "ia32/macro-assembler-ia32.h"
+#include "ia32/regexp-macro-assembler-ia32.h"
#endif
#include "interpreter-irregexp.h"
@@ -499,24 +502,25 @@ const int TestConfig::kNoKey = 0;
const int TestConfig::kNoValue = 0;
-static int PseudoRandom(int i, int j) {
+static unsigned PseudoRandom(int i, int j) {
return ~(~((i * 781) ^ (j * 329)));
}
TEST(SplayTreeSimple) {
- static const int kLimit = 1000;
+ static const unsigned kLimit = 1000;
ZoneScope zone_scope(DELETE_ON_EXIT);
ZoneSplayTree<TestConfig> tree;
- std::set<int> seen;
+ bool seen[kLimit];
+ for (unsigned i = 0; i < kLimit; i++) seen[i] = false;
#define CHECK_MAPS_EQUAL() do { \
- for (int k = 0; k < kLimit; k++) \
- CHECK_EQ(seen.find(k) != seen.end(), tree.Find(k, &loc)); \
+ for (unsigned k = 0; k < kLimit; k++) \
+ CHECK_EQ(seen[k], tree.Find(k, &loc)); \
} while (false)
for (int i = 0; i < 50; i++) {
for (int j = 0; j < 50; j++) {
- int next = PseudoRandom(i, j) % kLimit;
- if (seen.find(next) != seen.end()) {
+ unsigned next = PseudoRandom(i, j) % kLimit;
+ if (seen[next]) {
// We've already seen this one. Check the value and remove
// it.
ZoneSplayTree<TestConfig>::Locator loc;
@@ -524,7 +528,7 @@ TEST(SplayTreeSimple) {
CHECK_EQ(next, loc.key());
CHECK_EQ(3 * next, loc.value());
tree.Remove(next);
- seen.erase(next);
+ seen[next] = false;
CHECK_MAPS_EQUAL();
} else {
// Check that it wasn't there already and then add it.
@@ -533,26 +537,22 @@ TEST(SplayTreeSimple) {
CHECK(tree.Insert(next, &loc));
CHECK_EQ(next, loc.key());
loc.set_value(3 * next);
- seen.insert(next);
+ seen[next] = true;
CHECK_MAPS_EQUAL();
}
int val = PseudoRandom(j, i) % kLimit;
- for (int k = val; k >= 0; k--) {
- if (seen.find(val) != seen.end()) {
- ZoneSplayTree<TestConfig>::Locator loc;
- CHECK(tree.FindGreatestLessThan(val, &loc));
- CHECK_EQ(loc.key(), val);
- break;
- }
+ if (seen[val]) {
+ ZoneSplayTree<TestConfig>::Locator loc;
+ CHECK(tree.FindGreatestLessThan(val, &loc));
+ CHECK_EQ(loc.key(), val);
+ break;
}
val = PseudoRandom(i + j, i - j) % kLimit;
- for (int k = val; k < kLimit; k++) {
- if (seen.find(val) != seen.end()) {
- ZoneSplayTree<TestConfig>::Locator loc;
- CHECK(tree.FindLeastGreaterThan(val, &loc));
- CHECK_EQ(loc.key(), val);
- break;
- }
+ if (seen[val]) {
+ ZoneSplayTree<TestConfig>::Locator loc;
+ CHECK(tree.FindLeastGreaterThan(val, &loc));
+ CHECK_EQ(loc.key(), val);
+ break;
}
}
}
@@ -661,7 +661,7 @@ TEST(MacroAssembler) {
}
-#ifndef ARM // IA32 only tests.
+#ifdef V8_TARGET_ARCH_IA32 // IA32 only tests.
class ContextInitializer {
public:
diff --git a/deps/v8/test/cctest/test-serialize.cc b/deps/v8/test/cctest/test-serialize.cc
index 56727dca4..36f051f57 100644
--- a/deps/v8/test/cctest/test-serialize.cc
+++ b/deps/v8/test/cctest/test-serialize.cc
@@ -26,8 +26,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <signal.h>
-#include <map>
-#include <string>
#include "sys/stat.h"
#include "v8.h"
@@ -42,20 +40,40 @@
using namespace v8::internal;
-static int local_counters[256];
-static int counter_count = 0;
-static std::map<std::string, int> counter_table;
+static const unsigned kCounters = 256;
+static int local_counters[kCounters];
+static const char* local_counter_names[kCounters];
+
+
+static unsigned CounterHash(const char* s) {
+ unsigned hash = 0;
+ while (*++s) {
+ hash |= hash << 5;
+ hash += *s;
+ }
+ return hash;
+}
// Callback receiver to track counters in test.
static int* counter_function(const char* name) {
- std::string counter(name);
- if (counter_table.find(counter) == counter_table.end()) {
- local_counters[counter_count] = 0;
- counter_table[counter] = counter_count++;
+ unsigned hash = CounterHash(name) % kCounters;
+ unsigned original_hash = hash;
+ USE(original_hash);
+ while (true) {
+ if (local_counter_names[hash] == name) {
+ return &local_counters[hash];
+ }
+ if (local_counter_names[hash] == 0) {
+ local_counter_names[hash] = name;
+ return &local_counters[hash];
+ }
+ if (strcmp(local_counter_names[hash], name) == 0) {
+ return &local_counters[hash];
+ }
+ hash = (hash + 1) % kCounters;
+ ASSERT(hash != original_hash); // Hash table has been filled up.
}
-
- return &local_counters[counter_table[counter]];
}
diff --git a/deps/v8/test/cctest/test-strings.cc b/deps/v8/test/cctest/test-strings.cc
index 3be5d6292..3065ba12b 100644
--- a/deps/v8/test/cctest/test-strings.cc
+++ b/deps/v8/test/cctest/test-strings.cc
@@ -9,6 +9,7 @@
#include "v8.h"
+#include "api.h"
#include "factory.h"
#include "cctest.h"
#include "zone-inl.h"
@@ -154,7 +155,7 @@ static Handle<String> ConstructBalancedHelper(
Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
int from,
int to) {
- ASSERT(to > from);
+ CHECK(to > from);
if (to - from == 1) {
return building_blocks[from % NUMBER_OF_BUILDING_BLOCKS];
}
@@ -279,7 +280,7 @@ static Handle<String> ConstructSliceTree(
Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
int from,
int to) {
- ASSERT(to > from);
+ CHECK(to > from);
if (to - from <= 1)
return SliceOf(building_blocks[from % NUMBER_OF_BUILDING_BLOCKS]);
if (to - from == 2) {
@@ -391,9 +392,17 @@ TEST(Utf8Conversion) {
class TwoByteResource: public v8::String::ExternalStringResource {
public:
- explicit TwoByteResource(const uint16_t* data, size_t length)
- : data_(data), length_(length) { }
- virtual ~TwoByteResource() { }
+ TwoByteResource(const uint16_t* data, size_t length, bool* destructed)
+ : data_(data), length_(length), destructed_(destructed) {
+ CHECK_NE(destructed, NULL);
+ *destructed_ = false;
+ }
+
+ virtual ~TwoByteResource() {
+ CHECK_NE(destructed_, NULL);
+ CHECK(!*destructed_);
+ *destructed_ = true;
+ }
const uint16_t* data() const { return data_; }
size_t length() const { return length_; }
@@ -401,46 +410,107 @@ class TwoByteResource: public v8::String::ExternalStringResource {
private:
const uint16_t* data_;
size_t length_;
+ bool* destructed_;
};
-TEST(ExternalCrBug9746) {
+// Regression test case for http://crbug.com/9746. The problem was
+// that when we marked objects reachable only through weak pointers,
+// we ended up keeping a sliced symbol alive, even though we already
+// invoked the weak callback on the underlying external string thus
+// deleting its resource.
+TEST(Regress9746) {
InitializeVM();
- v8::HandleScope handle_scope;
- // This set of tests verifies that the workaround for Chromium bug 9746
- // works correctly. In certain situations the external resource of a symbol
- // is collected while the symbol is still part of the symbol table.
- static uint16_t two_byte_data[] = {
- 't', 'w', 'o', '-', 'b', 'y', 't', 'e', ' ', 'd', 'a', 't', 'a'
- };
- static size_t two_byte_length =
- sizeof(two_byte_data) / sizeof(two_byte_data[0]);
- static const char* one_byte_data = "two-byte data";
-
- // Allocate an external string resource and external string.
- TwoByteResource* resource = new TwoByteResource(two_byte_data,
- two_byte_length);
- Handle<String> string = Factory::NewExternalStringFromTwoByte(resource);
- Vector<const char> one_byte_vec = CStrVector(one_byte_data);
- Handle<String> compare = Factory::NewStringFromAscii(one_byte_vec);
-
- // Verify the correct behaviour before "collecting" the external resource.
- CHECK(string->IsEqualTo(one_byte_vec));
- CHECK(string->Equals(*compare));
-
- // "Collect" the external resource manually by setting the external resource
- // pointer to NULL. Then redo the comparisons, they should not match AND
- // not crash.
- Handle<ExternalTwoByteString> external(ExternalTwoByteString::cast(*string));
- external->set_resource(NULL);
- CHECK_EQ(false, string->IsEqualTo(one_byte_vec));
-#if !defined(DEBUG)
- // These tests only work in non-debug as there are ASSERTs in the code that
- // do prevent the ability to even get into the broken code when running the
- // debug version of V8.
- CHECK_EQ(false, string->Equals(*compare));
- CHECK_EQ(false, compare->Equals(*string));
- CHECK_EQ(false, string->Equals(Heap::empty_string()));
-#endif // !defined(DEBUG)
+ // Setup lengths that guarantee we'll get slices instead of simple
+ // flat strings.
+ static const int kFullStringLength = String::kMinNonFlatLength * 2;
+ static const int kSliceStringLength = String::kMinNonFlatLength + 1;
+
+ uint16_t* source = new uint16_t[kFullStringLength];
+ for (int i = 0; i < kFullStringLength; i++) source[i] = '1';
+ char* key = new char[kSliceStringLength];
+ for (int i = 0; i < kSliceStringLength; i++) key[i] = '1';
+ Vector<const char> key_vector(key, kSliceStringLength);
+
+ // Allocate an external string resource that keeps track of when it
+ // is destructed.
+ bool resource_destructed = false;
+ TwoByteResource* resource =
+ new TwoByteResource(source, kFullStringLength, &resource_destructed);
+
+ {
+ v8::HandleScope scope;
+
+ // Allocate an external string resource and external string. We
+ // have to go through the API to get the weak handle and the
+ // automatic destruction going.
+ Handle<String> string =
+ v8::Utils::OpenHandle(*v8::String::NewExternal(resource));
+
+ // Create a slice of the external string.
+ Handle<String> slice =
+ Factory::NewStringSlice(string, 0, kSliceStringLength);
+ CHECK_EQ(kSliceStringLength, slice->length());
+ CHECK(StringShape(*slice).IsSliced());
+
+ // Make sure the slice ends up in old space so we can morph it
+ // into a symbol.
+ while (Heap::InNewSpace(*slice)) {
+ Heap::PerformScavenge();
+ }
+
+ // Force the slice into the symbol table.
+ slice = Factory::SymbolFromString(slice);
+ CHECK(slice->IsSymbol());
+ CHECK(StringShape(*slice).IsSliced());
+
+ Handle<String> buffer(Handle<SlicedString>::cast(slice)->buffer());
+ CHECK(StringShape(*buffer).IsExternal());
+ CHECK(buffer->IsTwoByteRepresentation());
+
+ // Finally, base a script on the slice of the external string and
+ // get its wrapper. This allocates yet another weak handle that
+ // indirectly refers to the external string.
+ Handle<Script> script = Factory::NewScript(slice);
+ Handle<JSObject> wrapper = GetScriptWrapper(script);
+ }
+
+ // When we collect all garbage, we cannot get rid of the sliced
+ // symbol entry in the symbol table because it is used by the script
+ // kept alive by the weak wrapper. Make sure we don't destruct the
+ // external string.
+ Heap::CollectAllGarbage();
+ CHECK(!resource_destructed);
+
+ {
+ v8::HandleScope scope;
+
+ // Make sure the sliced symbol is still in the table.
+ Handle<String> symbol = Factory::LookupSymbol(key_vector);
+ CHECK(StringShape(*symbol).IsSliced());
+
+ // Make sure the buffer is still a two-byte external string.
+ Handle<String> buffer(Handle<SlicedString>::cast(symbol)->buffer());
+ CHECK(StringShape(*buffer).IsExternal());
+ CHECK(buffer->IsTwoByteRepresentation());
+ }
+
+ // Forcing another garbage collection should let us get rid of the
+ // slice from the symbol table. The external string remains in the
+ // heap until the next GC.
+ Heap::CollectAllGarbage();
+ CHECK(!resource_destructed);
+ v8::HandleScope scope;
+ Handle<String> key_string = Factory::NewStringFromAscii(key_vector);
+ String* out;
+ CHECK(!Heap::LookupSymbolIfExists(*key_string, &out));
+
+ // Forcing yet another garbage collection must allow us to finally
+ // get rid of the external string.
+ Heap::CollectAllGarbage();
+ CHECK(resource_destructed);
+
+ delete[] source;
+ delete[] key;
}
diff --git a/deps/v8/test/cctest/test-version.cc b/deps/v8/test/cctest/test-version.cc
new file mode 100644
index 000000000..0b93fbf8c
--- /dev/null
+++ b/deps/v8/test/cctest/test-version.cc
@@ -0,0 +1,88 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#include "version.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+
+namespace v8 { namespace internal {
+
+void SetVersion(int major, int minor, int build, int patch,
+ bool candidate, const char* soname) {
+ Version::major_ = major;
+ Version::minor_ = minor;
+ Version::build_ = build;
+ Version::patch_ = patch;
+ Version::candidate_ = candidate;
+ Version::soname_ = soname;
+}
+
+} } // namespace v8::internal
+
+
+static void CheckVersion(int major, int minor, int build,
+ int patch, bool candidate,
+ const char* expected_version_string,
+ const char* expected_generic_soname) {
+ static v8::internal::EmbeddedVector<char, 128> version_str;
+ static v8::internal::EmbeddedVector<char, 128> soname_str;
+
+ // Test version without specific SONAME.
+ SetVersion(major, minor, build, patch, candidate, "");
+ Version::GetString(version_str);
+ CHECK_EQ(expected_version_string, version_str.start());
+ Version::GetSONAME(soname_str);
+ CHECK_EQ(expected_generic_soname, soname_str.start());
+
+ // Test version with specific SONAME.
+ const char* soname = "libv8.so.1";
+ SetVersion(major, minor, build, patch, candidate, soname);
+ Version::GetString(version_str);
+ CHECK_EQ(expected_version_string, version_str.start());
+ Version::GetSONAME(soname_str);
+ CHECK_EQ(soname, soname_str.start());
+}
+
+
+TEST(VersionString) {
+ CheckVersion(0, 0, 0, 0, false, "0.0.0", "libv8-0.0.0.so");
+ CheckVersion(0, 0, 0, 0, true,
+ "0.0.0 (candidate)", "libv8-0.0.0-candidate.so");
+ CheckVersion(1, 0, 0, 0, false, "1.0.0", "libv8-1.0.0.so");
+ CheckVersion(1, 0, 0, 0, true,
+ "1.0.0 (candidate)", "libv8-1.0.0-candidate.so");
+ CheckVersion(1, 0, 0, 1, false, "1.0.0.1", "libv8-1.0.0.1.so");
+ CheckVersion(1, 0, 0, 1, true,
+ "1.0.0.1 (candidate)", "libv8-1.0.0.1-candidate.so");
+ CheckVersion(2, 5, 10, 7, false, "2.5.10.7", "libv8-2.5.10.7.so");
+ CheckVersion(2, 5, 10, 7, true,
+ "2.5.10.7 (candidate)", "libv8-2.5.10.7-candidate.so");
+}
diff --git a/deps/v8/test/mjsunit/array-reduce.js b/deps/v8/test/mjsunit/array-reduce.js
new file mode 100644
index 000000000..e476e1cb0
--- /dev/null
+++ b/deps/v8/test/mjsunit/array-reduce.js
@@ -0,0 +1,514 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/**
+ * @fileoverview Test reduce and reduceRight
+ */
+
+function clone(v) {
+ // Shallow-copies arrays, returns everything else verbatim.
+ if (v instanceof Array) {
+ // Shallow-copy an array.
+ var newArray = new Array(v.length);
+ for (var i in v) {
+ newArray[i] = v[i];
+ }
+ return newArray;
+ }
+ return v;
+}
+
+
+// Creates a callback function for reduce/reduceRight that tests the number
+// of arguments and otherwise behaves as "func", but which also
+// records all calls in an array on the function (as arrays of arguments
+// followed by result).
+function makeRecorder(func, testName) {
+ var record = [];
+ var f = function recorder(a, b, i, s) {
+ assertEquals(4, arguments.length,
+ testName + "(number of arguments: " + arguments.length + ")");
+ assertEquals("number", typeof(i), testName + "(index must be number)");
+ assertEquals(s[i], b, testName + "(current argument is at index)");
+ if (record.length > 0) {
+ var prevRecord = record[record.length - 1];
+ var prevResult = prevRecord[prevRecord.length - 1];
+ assertEquals(prevResult, a,
+ testName + "(prev result -> current input)");
+ }
+ var args = [clone(a), clone(b), i, clone(s)];
+ var result = func.apply(this, arguments);
+ args.push(clone(result));
+ record.push(args);
+ return result;
+ };
+ f.record = record;
+ return f;
+}
+
+
+function testReduce(type,
+ testName,
+ expectedResult,
+ expectedCalls,
+ array,
+ combine,
+ init) {
+ var rec = makeRecorder(combine);
+ var result;
+ var performsCall;
+ if (arguments.length > 6) {
+ result = array[type](rec, init);
+ } else {
+ result = array[type](rec);
+ }
+ var calls = rec.record;
+ assertEquals(expectedCalls.length, calls.length,
+ testName + " (number of calls)");
+ for (var i = 0; i < expectedCalls.length; i++) {
+ assertEquals(expectedCalls[i], calls[i],
+ testName + " (call " + (i + 1) + ")");
+ }
+ assertEquals(expectedResult, result, testName + " (result)");
+}
+
+
+function sum(a, b) { return a + b; }
+function prod(a, b) { return a * b; }
+function dec(a, b, i, arr) { return a + b * Math.pow(10, arr.length - i - 1); }
+function accumulate(acc, elem, i) { acc[i] = elem; return acc; }
+
+// ---- Test Reduce[Left]
+
+var simpleArray = [2,4,6]
+
+testReduce("reduce", "SimpleReduceSum", 12,
+ [[0, 2, 0, simpleArray, 2],
+ [2, 4, 1, simpleArray, 6],
+ [6, 6, 2, simpleArray, 12]],
+ simpleArray, sum, 0);
+
+testReduce("reduce", "SimpleReduceProd", 48,
+ [[1, 2, 0, simpleArray, 2],
+ [2, 4, 1, simpleArray, 8],
+ [8, 6, 2, simpleArray, 48]],
+ simpleArray, prod, 1);
+
+testReduce("reduce", "SimpleReduceDec", 246,
+ [[0, 2, 0, simpleArray, 200],
+ [200, 4, 1, simpleArray, 240],
+ [240, 6, 2, simpleArray, 246]],
+ simpleArray, dec, 0);
+
+testReduce("reduce", "SimpleReduceAccumulate", simpleArray,
+ [[[], 2, 0, simpleArray, [2]],
+ [[2], 4, 1, simpleArray, [2, 4]],
+ [[2,4], 6, 2, simpleArray, simpleArray]],
+ simpleArray, accumulate, []);
+
+
+testReduce("reduce", "EmptyReduceSum", 0, [], [], sum, 0);
+testReduce("reduce", "EmptyReduceProd", 1, [], [], prod, 1);
+testReduce("reduce", "EmptyReduceDec", 0, [], [], dec, 0);
+testReduce("reduce", "EmptyReduceAccumulate", [], [], [], accumulate, []);
+
+testReduce("reduce", "EmptyReduceSumNoInit", 0, [], [0], sum);
+testReduce("reduce", "EmptyReduceProdNoInit", 1, [], [1], prod);
+testReduce("reduce", "EmptyReduceDecNoInit", 0, [], [0], dec);
+testReduce("reduce", "EmptyReduceAccumulateNoInit", [], [], [[]], accumulate);
+
+
+var simpleSparseArray = [,,,2,,4,,6,,];
+testReduce("reduce", "SimpleSparseReduceSum", 12,
+ [[0, 2, 3, simpleSparseArray, 2],
+ [2, 4, 5, simpleSparseArray, 6],
+ [6, 6, 7, simpleSparseArray, 12]],
+ simpleSparseArray, sum, 0);
+
+testReduce("reduce", "SimpleSparseReduceProd", 48,
+ [[1, 2, 3, simpleSparseArray, 2],
+ [2, 4, 5, simpleSparseArray, 8],
+ [8, 6, 7, simpleSparseArray, 48]],
+ simpleSparseArray, prod, 1);
+
+testReduce("reduce", "SimpleSparseReduceDec", 204060,
+ [[0, 2, 3, simpleSparseArray, 200000],
+ [200000, 4, 5, simpleSparseArray, 204000],
+ [204000, 6, 7, simpleSparseArray, 204060]],
+ simpleSparseArray, dec, 0);
+
+testReduce("reduce", "SimpleSparseReduceAccumulate", [,,,2,,4,,6],
+ [[[], 2, 3, simpleSparseArray, [,,,2]],
+ [[,,,2], 4, 5, simpleSparseArray, [,,,2,,4]],
+ [[,,,2,,4], 6, 7, simpleSparseArray, [,,,2,,4,,6]]],
+ simpleSparseArray, accumulate, []);
+
+
+testReduce("reduce", "EmptySparseReduceSumNoInit", 0, [], [,,0,,], sum);
+testReduce("reduce", "EmptySparseReduceProdNoInit", 1, [], [,,1,,], prod);
+testReduce("reduce", "EmptySparseReduceDecNoInit", 0, [], [,,0,,], dec);
+testReduce("reduce", "EmptySparseReduceAccumulateNoInit",
+ [], [], [,,[],,], accumulate);
+
+
+var verySparseArray = [];
+verySparseArray.length = 10000;
+verySparseArray[2000] = 2;
+verySparseArray[5000] = 4;
+verySparseArray[9000] = 6;
+var verySparseSlice2 = verySparseArray.slice(0, 2001);
+var verySparseSlice4 = verySparseArray.slice(0, 5001);
+var verySparseSlice6 = verySparseArray.slice(0, 9001);
+
+testReduce("reduce", "VerySparseReduceSum", 12,
+ [[0, 2, 2000, verySparseArray, 2],
+ [2, 4, 5000, verySparseArray, 6],
+ [6, 6, 9000, verySparseArray, 12]],
+ verySparseArray, sum, 0);
+
+testReduce("reduce", "VerySparseReduceProd", 48,
+ [[1, 2, 2000, verySparseArray, 2],
+ [2, 4, 5000, verySparseArray, 8],
+ [8, 6, 9000, verySparseArray, 48]],
+ verySparseArray, prod, 1);
+
+testReduce("reduce", "VerySparseReduceDec", Infinity,
+ [[0, 2, 2000, verySparseArray, Infinity],
+ [Infinity, 4, 5000, verySparseArray, Infinity],
+ [Infinity, 6, 9000, verySparseArray, Infinity]],
+ verySparseArray, dec, 0);
+
+testReduce("reduce", "VerySparseReduceAccumulate",
+ verySparseSlice6,
+ [[[], 2, 2000, verySparseArray, verySparseSlice2],
+ [verySparseSlice2, 4, 5000, verySparseArray, verySparseSlice4],
+ [verySparseSlice4, 6, 9000, verySparseArray, verySparseSlice6]],
+ verySparseArray, accumulate, []);
+
+
+testReduce("reduce", "VerySparseReduceSumNoInit", 12,
+ [[2, 4, 5000, verySparseArray, 6],
+ [6, 6, 9000, verySparseArray, 12]],
+ verySparseArray, sum);
+
+testReduce("reduce", "VerySparseReduceProdNoInit", 48,
+ [[2, 4, 5000, verySparseArray, 8],
+ [8, 6, 9000, verySparseArray, 48]],
+ verySparseArray, prod);
+
+testReduce("reduce", "VerySparseReduceDecNoInit", Infinity,
+ [[2, 4, 5000, verySparseArray, Infinity],
+ [Infinity, 6, 9000, verySparseArray, Infinity]],
+ verySparseArray, dec);
+
+testReduce("reduce", "SimpleSparseReduceAccumulateNoInit",
+ 2,
+ [[2, 4, 5000, verySparseArray, 2],
+ [2, 6, 9000, verySparseArray, 2]],
+ verySparseArray, accumulate);
+
+
+// ---- Test ReduceRight
+
+testReduce("reduceRight", "SimpleReduceRightSum", 12,
+ [[0, 6, 2, simpleArray, 6],
+ [6, 4, 1, simpleArray, 10],
+ [10, 2, 0, simpleArray, 12]],
+ simpleArray, sum, 0);
+
+testReduce("reduceRight", "SimpleReduceRightProd", 48,
+ [[1, 6, 2, simpleArray, 6],
+ [6, 4, 1, simpleArray, 24],
+ [24, 2, 0, simpleArray, 48]],
+ simpleArray, prod, 1);
+
+testReduce("reduceRight", "SimpleReduceRightDec", 246,
+ [[0, 6, 2, simpleArray, 6],
+ [6, 4, 1, simpleArray, 46],
+ [46, 2, 0, simpleArray, 246]],
+ simpleArray, dec, 0);
+
+testReduce("reduceRight", "SimpleReduceRightAccumulate", simpleArray,
+ [[[], 6, 2, simpleArray, [,,6]],
+ [[,,6], 4, 1, simpleArray, [,4,6]],
+ [[,4,6], 2, 0, simpleArray, simpleArray]],
+ simpleArray, accumulate, []);
+
+
+testReduce("reduceRight", "EmptyReduceRightSum", 0, [], [], sum, 0);
+testReduce("reduceRight", "EmptyReduceRightProd", 1, [], [], prod, 1);
+testReduce("reduceRight", "EmptyReduceRightDec", 0, [], [], dec, 0);
+testReduce("reduceRight", "EmptyReduceRightAccumulate", [],
+ [], [], accumulate, []);
+
+testReduce("reduceRight", "EmptyReduceRightSumNoInit", 0, [], [0], sum);
+testReduce("reduceRight", "EmptyReduceRightProdNoInit", 1, [], [1], prod);
+testReduce("reduceRight", "EmptyReduceRightDecNoInit", 0, [], [0], dec);
+testReduce("reduceRight", "EmptyReduceRightAccumulateNoInit",
+ [], [], [[]], accumulate);
+
+
+testReduce("reduceRight", "SimpleSparseReduceRightSum", 12,
+ [[0, 6, 7, simpleSparseArray, 6],
+ [6, 4, 5, simpleSparseArray, 10],
+ [10, 2, 3, simpleSparseArray, 12]],
+ simpleSparseArray, sum, 0);
+
+testReduce("reduceRight", "SimpleSparseReduceRightProd", 48,
+ [[1, 6, 7, simpleSparseArray, 6],
+ [6, 4, 5, simpleSparseArray, 24],
+ [24, 2, 3, simpleSparseArray, 48]],
+ simpleSparseArray, prod, 1);
+
+testReduce("reduceRight", "SimpleSparseReduceRightDec", 204060,
+ [[0, 6, 7, simpleSparseArray, 60],
+ [60, 4, 5, simpleSparseArray, 4060],
+ [4060, 2, 3, simpleSparseArray, 204060]],
+ simpleSparseArray, dec, 0);
+
+testReduce("reduceRight", "SimpleSparseReduceRightAccumulate", [,,,2,,4,,6],
+ [[[], 6, 7, simpleSparseArray, [,,,,,,,6]],
+ [[,,,,,,,6], 4, 5, simpleSparseArray, [,,,,,4,,6]],
+ [[,,,,,4,,6], 2, 3, simpleSparseArray, [,,,2,,4,,6]]],
+ simpleSparseArray, accumulate, []);
+
+
+testReduce("reduceRight", "EmptySparseReduceRightSumNoInit",
+ 0, [], [,,0,,], sum);
+testReduce("reduceRight", "EmptySparseReduceRightProdNoInit",
+ 1, [], [,,1,,], prod);
+testReduce("reduceRight", "EmptySparseReduceRightDecNoInit",
+ 0, [], [,,0,,], dec);
+testReduce("reduceRight", "EmptySparseReduceRightAccumulateNoInit",
+ [], [], [,,[],,], accumulate);
+
+
+var verySparseSuffix6 = [];
+verySparseSuffix6[9000] = 6;
+var verySparseSuffix4 = [];
+verySparseSuffix4[5000] = 4;
+verySparseSuffix4[9000] = 6;
+var verySparseSuffix2 = verySparseSlice6;
+
+
+testReduce("reduceRight", "VerySparseReduceRightSum", 12,
+ [[0, 6, 9000, verySparseArray, 6],
+ [6, 4, 5000, verySparseArray, 10],
+ [10, 2, 2000, verySparseArray, 12]],
+ verySparseArray, sum, 0);
+
+testReduce("reduceRight", "VerySparseReduceRightProd", 48,
+ [[1, 6, 9000, verySparseArray, 6],
+ [6, 4, 5000, verySparseArray, 24],
+ [24, 2, 2000, verySparseArray, 48]],
+ verySparseArray, prod, 1);
+
+testReduce("reduceRight", "VerySparseReduceRightDec", Infinity,
+ [[0, 6, 9000, verySparseArray, Infinity],
+ [Infinity, 4, 5000, verySparseArray, Infinity],
+ [Infinity, 2, 2000, verySparseArray, Infinity]],
+ verySparseArray, dec, 0);
+
+testReduce("reduceRight", "VerySparseReduceRightAccumulate",
+ verySparseSuffix2,
+ [[[], 6, 9000, verySparseArray, verySparseSuffix6],
+ [verySparseSuffix6, 4, 5000, verySparseArray, verySparseSuffix4],
+ [verySparseSuffix4, 2, 2000, verySparseArray, verySparseSuffix2]],
+ verySparseArray, accumulate, []);
+
+
+testReduce("reduceRight", "VerySparseReduceRightSumNoInit", 12,
+ [[6, 4, 5000, verySparseArray, 10],
+ [10, 2, 2000, verySparseArray, 12]],
+ verySparseArray, sum);
+
+testReduce("reduceRight", "VerySparseReduceRightProdNoInit", 48,
+ [[6, 4, 5000, verySparseArray, 24],
+ [24, 2, 2000, verySparseArray, 48]],
+ verySparseArray, prod);
+
+testReduce("reduceRight", "VerySparseReduceRightDecNoInit", Infinity,
+ [[6, 4, 5000, verySparseArray, Infinity],
+ [Infinity, 2, 2000, verySparseArray, Infinity]],
+ verySparseArray, dec);
+
+testReduce("reduceRight", "SimpleSparseReduceRightAccumulateNoInit",
+ 6,
+ [[6, 4, 5000, verySparseArray, 6],
+ [6, 2, 2000, verySparseArray, 6]],
+ verySparseArray, accumulate);
+
+
+// undefined is an element
+var undefArray = [,,undefined,,undefined,,];
+
+testReduce("reduce", "SparseUndefinedReduceAdd", NaN,
+ [[0, undefined, 2, undefArray, NaN],
+ [NaN, undefined, 4, undefArray, NaN],
+ ],
+ undefArray, sum, 0);
+
+testReduce("reduceRight", "SparseUndefinedReduceRightAdd", NaN,
+ [[0, undefined, 4, undefArray, NaN],
+ [NaN, undefined, 2, undefArray, NaN],
+ ], undefArray, sum, 0);
+
+testReduce("reduce", "SparseUndefinedReduceAddNoInit", NaN,
+ [[undefined, undefined, 4, undefArray, NaN],
+ ], undefArray, sum);
+
+testReduce("reduceRight", "SparseUndefinedReduceRightAddNoInit", NaN,
+ [[undefined, undefined, 2, undefArray, NaN],
+ ], undefArray, sum);
+
+
+// Ignore non-array properties:
+
+var arrayPlus = [1,2,,3];
+arrayPlus[-1] = NaN;
+arrayPlus[Math.pow(2,32)] = NaN;
+arrayPlus[NaN] = NaN;
+arrayPlus["00"] = NaN;
+arrayPlus["02"] = NaN;
+arrayPlus["-0"] = NaN;
+
+testReduce("reduce", "ArrayWithNonElementPropertiesReduce", 6,
+ [[0, 1, 0, arrayPlus, 1],
+ [1, 2, 1, arrayPlus, 3],
+ [3, 3, 3, arrayPlus, 6],
+ ], arrayPlus, sum, 0);
+
+testReduce("reduceRight", "ArrayWithNonElementPropertiesReduceRight", 6,
+ [[0, 3, 3, arrayPlus, 3],
+ [3, 2, 1, arrayPlus, 5],
+ [5, 1, 0, arrayPlus, 6],
+ ], arrayPlus, sum, 0);
+
+
+// Test error conditions:
+
+try {
+ [1].reduce("not a function");
+ fail("Reduce callback not a function not throwing");
+} catch (e) {
+ assertTrue(e instanceof TypeError,
+ "reduce callback not a function not throwing TypeError");
+ assertEquals("called_non_callable", e.type,
+ "reduce non function TypeError type");
+}
+
+try {
+ [1].reduceRight("not a function");
+ fail("ReduceRight callback not a function not throwing");
+} catch (e) {
+ assertTrue(e instanceof TypeError,
+ "reduceRight callback not a function not throwing TypeError");
+ assertEquals("called_non_callable", e.type,
+ "reduceRight non function TypeError type");
+}
+
+
+try {
+ [].reduce(sum);
+ fail("Reduce no initial value not throwing");
+} catch (e) {
+ assertTrue(e instanceof TypeError,
+ "reduce no initial value not throwing TypeError");
+ assertEquals("reduce_no_initial", e.type,
+ "reduce no initial TypeError type");
+}
+
+try {
+ [].reduceRight(sum);
+ fail("ReduceRight no initial value not throwing");
+} catch (e) {
+ assertTrue(e instanceof TypeError,
+ "reduceRight no initial value not throwing TypeError");
+ assertEquals("reduce_no_initial", e.type,
+ "reduceRight no initial TypeError type");
+}
+
+
+try {
+ [,,,].reduce(sum);
+ fail("Reduce sparse no initial value not throwing");
+} catch (e) {
+ assertTrue(e instanceof TypeError,
+ "reduce sparse no initial value not throwing TypeError");
+ assertEquals("reduce_no_initial", e.type,
+ "reduce no initial TypeError type");
+}
+
+try {
+ [,,,].reduceRight(sum);
+ fail("ReduceRight sparse no initial value not throwing");
+} catch (e) {
+ assertTrue(e instanceof TypeError,
+ "reduceRight sparse no initial value not throwing TypeError");
+ assertEquals("reduce_no_initial", e.type,
+ "reduceRight no initial TypeError type");
+}
+
+
+// Array changing length
+
+function manipulator(a, b, i, s) {
+ if (s.length % 2) {
+ s[s.length * 3] = i;
+ } else {
+ s.length = s.length >> 1;
+ }
+ return a + b;
+}
+
+var arr = [1, 2, 3, 4];
+testReduce("reduce", "ArrayManipulationShort", 3,
+ [[0, 1, 0, [1, 2, 3, 4], 1],
+ [1, 2, 1, [1, 2], 3],
+ ], arr, manipulator, 0);
+
+var arr = [1, 2, 3, 4, 5];
+testReduce("reduce", "ArrayManipulationLonger", 10,
+ [[0, 1, 0, [1, 2, 3, 4, 5], 1],
+ [1, 2, 1, [1, 2, 3, 4, 5,,,,,,,,,,, 0], 3],
+ [3, 3, 2, [1, 2, 3, 4, 5,,,,], 6],
+ [6, 4, 3, [1, 2, 3, 4], 10],
+ ], arr, manipulator, 0);
+
+function extender(a, b, i, s) {
+ s[s.length] = s.length;
+ return a + b;
+}
+
+var arr = [1, 2, 3, 4];
+testReduce("reduce", "ArrayManipulationExtender", 10,
+ [[0, 1, 0, [1, 2, 3, 4], 1],
+ [1, 2, 1, [1, 2, 3, 4, 4], 3],
+ [3, 3, 2, [1, 2, 3, 4, 4, 5], 6],
+ [6, 4, 3, [1, 2, 3, 4, 4, 5, 6], 10],
+ ], arr, extender, 0);
+
diff --git a/deps/v8/test/mjsunit/array-sort.js b/deps/v8/test/mjsunit/array-sort.js
index dfa45906e..ef75dcc29 100644
--- a/deps/v8/test/mjsunit/array-sort.js
+++ b/deps/v8/test/mjsunit/array-sort.js
@@ -152,3 +152,191 @@ function TestArraySortingWithUnsoundComparisonFunction() {
}
TestArraySortingWithUnsoundComparisonFunction();
+
+
+function TestSparseNonArraySorting(length) {
+ assertTrue(length > 101);
+ var obj = {length: length};
+ obj[0] = 42;
+ obj[10] = 37;
+ obj[100] = undefined;
+ obj[length - 1] = null;
+ Array.prototype.sort.call(obj);
+ assertEquals(length, obj.length, "objsort length unaffected");
+ assertEquals(37, obj[0], "objsort smallest number");
+ assertEquals(42, obj[1], "objsort largest number");
+ assertEquals(null, obj[2], "objsort null");
+ assertEquals(undefined, obj[3], "objsort undefined");
+ assertTrue(3 in obj, "objsort undefined retained");
+ assertFalse(4 in obj, "objsort non-existing retained");
+}
+
+TestSparseNonArraySorting(5000);
+TestSparseNonArraySorting(500000);
+TestSparseNonArraySorting(Math.pow(2, 31) + 1);
+
+
+function TestArrayLongerLength(length) {
+ var x = new Array(4);
+ x[0] = 42;
+ x[2] = 37;
+ x.length = length;
+ Array.prototype.sort.call(x);
+ assertEquals(length, x.length, "longlength length");
+ assertEquals(37, x[0], "longlength first");
+ assertEquals(42, x[1], "longlength second");
+ assertFalse(2 in x,"longlength third");
+}
+
+TestArrayLongerLength(4);
+TestArrayLongerLength(10);
+TestArrayLongerLength(1000);
+TestArrayLongerLength(500000);
+TestArrayLongerLength(Math.pow(2,32) - 1);
+
+
+function TestNonArrayLongerLength(length) {
+ var x = {};
+ x[0] = 42;
+ x[2] = 37;
+ x.length = length;
+ Array.prototype.sort.call(x);
+ assertEquals(length, x.length, "longlength length");
+ assertEquals(37, x[0], "longlength first");
+ assertEquals(42, x[1], "longlength second");
+ assertFalse(2 in x,"longlength third");
+}
+
+TestNonArrayLongerLength(4);
+TestNonArrayLongerLength(10);
+TestNonArrayLongerLength(1000);
+TestNonArrayLongerLength(500000);
+TestNonArrayLongerLength(Math.pow(2,32) - 1);
+
+
+function TestInheritedElementSort(depth) {
+ var length = depth * 2 + 3;
+ var obj = {length: length};
+ obj[depth * 2 + 1] = 0;
+ for (var i = 0; i < depth; i++) {
+ var newObj = {};
+ newObj.__proto__ = obj;
+ obj[i] = undefined;
+ obj[i + depth + 1] = depth - i;
+ obj = newObj;
+ }
+ // expected (inherited) object: [undef1,...undefdepth,hole,1,...,depth,0,hole]
+
+ Array.prototype.sort.call(obj, function(a,b) { return (b < a) - (a < b); });
+ // expected result: [0,1,...,depth,undef1,...,undefdepth,undef,hole]
+ var name = "SortInherit("+depth+")-";
+
+ assertEquals(length, obj.length, name+"length");
+ for (var i = 0; i <= depth; i++) {
+ assertTrue(obj.hasOwnProperty(i), name + "hasvalue" + i);
+ assertEquals(i, obj[i], name + "value" + i);
+ }
+ for (var i = depth + 1; i <= depth * 2 + 1; i++) {
+ assertEquals(undefined, obj[i], name + "undefined" + i);
+ assertTrue(obj.hasOwnProperty(i), name + "hasundefined" + i);
+ }
+ assertTrue(!obj.hasOwnProperty(depth * 2 + 2), name + "hashole");
+}
+
+TestInheritedElementSort(5);
+TestInheritedElementSort(15);
+
+function TestSparseInheritedElementSort(scale) {
+ var length = scale * 10;
+ var x = {length: length};
+ var y = {};
+ y.__proto__ = x;
+
+ for (var i = 0; i < 5; i++) {
+ x[i * 2 * scale] = 2 * (4 - i);
+ y[(i * 2 + 1) * scale] = 2 * (4 - i) + 1;
+ }
+
+ var name = "SparseSortInherit(" + scale + ")-";
+
+ Array.prototype.sort.call(y);
+
+ assertEquals(length, y.length, name +"length");
+
+ for (var i = 0; i < 10; i++) {
+ assertTrue(y.hasOwnProperty(i), name + "hasvalue" + i);
+ assertEquals(i, y[i], name + "value" + i);
+ }
+ for (var i = 10; i < length; i++) {
+ assertEquals(x.hasOwnProperty(i), y.hasOwnProperty(i),
+ name + "hasundef" + i);
+ assertEquals(undefined, y[i], name+"undefined"+i);
+ if (x.hasOwnProperty(i)) {
+ assertTrue(0 == i % (2 * scale), name + "new_x" + i);
+ }
+ }
+}
+
+TestSparseInheritedElementSort(10);
+TestSparseInheritedElementSort(100);
+TestSparseInheritedElementSort(1000);
+
+function TestSpecialCasesInheritedElementSort() {
+
+ var x = {
+ 1:"d1",
+ 2:"c1",
+ 3:"b1",
+ 4: undefined,
+ __proto__: {
+ length: 10000,
+ 1: "e2",
+ 10: "a2",
+ 100: "b2",
+ 1000: "c2",
+ 2000: undefined,
+ 8000: "d2",
+ 12000: "XX",
+ __proto__: {
+ 0: "e3",
+ 1: "d3",
+ 2: "c3",
+ 3: "b3",
+ 4: "f3",
+ 5: "a3",
+ 6: undefined,
+ }
+ }
+ };
+ Array.prototype.sort.call(x);
+
+ var name = "SpecialInherit-";
+
+ assertEquals(10000, x.length, name + "length");
+ var sorted = ["a2", "a3", "b1", "b2", "c1", "c2", "d1", "d2", "e3",
+ undefined, undefined, undefined];
+ for (var i = 0; i < sorted.length; i++) {
+ assertTrue(x.hasOwnProperty(i), name + "has" + i)
+ assertEquals(sorted[i], x[i], name + i);
+ }
+ assertFalse(x.hasOwnProperty(sorted.length), name + "haspost");
+ assertFalse(sorted.length in x, name + "haspost2");
+
+ assertTrue(x.hasOwnProperty(10), name + "hasundefined10");
+ assertEquals(undefined, x[10], name + "undefined10");
+ assertTrue(x.hasOwnProperty(100), name + "hasundefined100");
+ assertEquals(undefined, x[100], name + "undefined100");
+ assertTrue(x.hasOwnProperty(1000), name + "hasundefined1000");
+ assertEquals(undefined, x[1000], name + "undefined1000");
+ assertTrue(x.hasOwnProperty(2000), name + "hasundefined2000");
+ assertEquals(undefined, x[2000], name + "undefined2000");
+ assertTrue(x.hasOwnProperty(8000), name + "hasundefined8000");
+ assertEquals(undefined, x[8000], name + "undefined8000");
+
+ assertFalse(x.hasOwnProperty(12000), name + "has12000");
+ assertEquals("XX", x[12000], name + "XX12000");
+
+}
+
+TestSpecialCasesInheritedElementSort();
+
diff --git a/deps/v8/test/mjsunit/bugs/bug-334.js b/deps/v8/test/mjsunit/bugs/bug-334.js
new file mode 100644
index 000000000..024fc9e85
--- /dev/null
+++ b/deps/v8/test/mjsunit/bugs/bug-334.js
@@ -0,0 +1,90 @@
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+// Test for http://code.google.com/p/v8/issues/detail?id=334
+
+var READ_ONLY = 1;
+var DONT_ENUM = 2;
+var DONT_DELETE = 4;
+
+function func1(){}
+function func2(){}
+
+var object = {__proto__:{}};
+%SetProperty(object, "foo", func1, DONT_ENUM | DONT_DELETE);
+%SetProperty(object, "bar", func1, DONT_ENUM | READ_ONLY);
+%SetProperty(object, "baz", func1, DONT_DELETE | READ_ONLY);
+%SetProperty(object.__proto__, "bif", func1, DONT_ENUM | DONT_DELETE | READ_ONLY);
+object.bif = func2;
+
+function enumerable(obj) {
+ var res = [];
+ for (var i in obj) {
+ res.push(i);
+ }
+ res.sort();
+ return res;
+}
+
+// Sanity check: expected initial state.
+assertArrayEquals(["baz", "bif"], enumerable(object), "enum0");
+assertFalse(delete object.foo, "delete foo");
+assertFalse(delete object.baz, "delete baz");
+assertEquals(func1, object.foo, "read foo");
+assertEquals(func1, object.bar, "read bar");
+assertEquals(func1, object.baz, "read baz");
+assertEquals(func2, object.bif, "read bif");
+
+// Can't assign to READ_ONLY.
+object.bar = "NO WAY";
+assertEquals(func1, object.bar, "read bar 2");
+assertArrayEquals(["baz", "bif"], enumerable(object), "enum1");
+
+// Assignment to non-readonly. Assignment shouldn't change attributes!
+object.foo = func2;
+assertArrayEquals(["baz", "bif"], enumerable(object), "enum2");
+assertFalse(delete object.foo, "delete foo 2");
+
+// Delete should erase attributes if value set again.
+assertTrue(delete object.bar, "delete bar");
+assertFalse("bar" in object, "has bar");
+object.bar = func2;
+assertTrue("bar" in object, "has bar 2");
+assertEquals(func2, object.bar, "read bar 3");
+
+assertArrayEquals(["bar", "baz", "bif"], enumerable(object), "enum3");
+
+// Unshadowing a prototype property exposes its attributes.
+assertTrue(delete object.bif, "delete bif");
+assertArrayEquals(["bar", "baz"], enumerable(object), "enum4");
+assertEquals(func1, object.bif, "read bif 2");
+// Can't delete prototype property.
+assertTrue(delete object.bif, "delete bif 2");
+assertArrayEquals(["bar", "baz"], enumerable(object), "enum5");
+assertEquals(func1, object.bif, "read bif3");
diff --git a/deps/v8/test/mjsunit/codegen_coverage.js b/deps/v8/test/mjsunit/codegen_coverage.js
new file mode 100644
index 000000000..d5e7769d7
--- /dev/null
+++ b/deps/v8/test/mjsunit/codegen_coverage.js
@@ -0,0 +1,91 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test the paths in the code generator where values in specific
+// registers get moved around so that the shift operation can use
+// register ECX on ia32 for the shift amount. Other codegen coverage
+// tests should go here too.
+
+
+
+function identity(x) {
+ return x;
+}
+
+function cover_codegen_paths() {
+ var x = 1;
+ var a; // Register EAX
+ var b; // Register EBX
+ var c; // Register ECX
+ var d; // Register EDX
+ // Register ESI is already used.
+ var di; // Register EDI
+
+ while (x == 1) {
+ x = identity(1);
+ a = x + 1;
+ c = x + 1;
+ d = x + 1;
+ b = x + 1;
+ di = x + 1;
+ // Locals are in the corresponding registers here.
+ assertEquals(c << a, 8);
+
+ x = identity(1);
+ a = x + 1;
+ c = x + 1;
+ d = x + 1;
+ b = x + 1;
+ di = x + 1;
+ // Locals are in the corresponding registers here.
+ assertEquals(a << c, 8);
+
+ x = identity(1);
+ a = x + 1;
+ c = x + 1;
+ d = x + 1;
+ b = x + 1;
+ di = x + 1;
+ // Locals are in the corresponding registers here.
+ c = 0; // Free register ecx.
+ assertEquals(a << d, 8);
+
+ x = identity(1);
+ a = x + 1;
+ c = x + 1;
+ d = x + 1;
+ b = x + 1;
+ di = x + 1;
+ // Locals are in the corresponding registers here.
+ b = 0; // Free register ebx.
+ assertEquals(a << d, 8);
+
+ x = 3;
+ }
+}
+
+cover_codegen_paths();
diff --git a/deps/v8/test/mjsunit/constant-folding.js b/deps/v8/test/mjsunit/constant-folding.js
index 41b632f7f..4deb43cd3 100644
--- a/deps/v8/test/mjsunit/constant-folding.js
+++ b/deps/v8/test/mjsunit/constant-folding.js
@@ -168,4 +168,65 @@ function test() {
assertEquals(17, j, "switch with constant value");
}
+
+function TrueToString() {
+ return true.toString();
+}
+
+
+function FalseToString() {
+ return false.toString();
+}
+
+
+function BoolTest() {
+ assertEquals("true", TrueToString());
+ assertEquals("true", TrueToString());
+ assertEquals("true", TrueToString());
+ assertEquals("false", FalseToString());
+ assertEquals("false", FalseToString());
+ assertEquals("false", FalseToString());
+ Boolean.prototype.toString = function() { return "foo"; }
+ assertEquals("foo", TrueToString());
+ assertEquals("foo", FalseToString());
+}
+
+
+// Some tests of shifts that get into the corners in terms of coverage.
+// We generate different code for the case where the operand is a constant.
+function ShiftTest() {
+ var x = 123;
+ assertEquals(x, x >> 0);
+ assertEquals(x, x << 0);
+ assertEquals(x, x >>> 0);
+ assertEquals(61, x >> 1);
+ assertEquals(246, x << 1);
+ assertEquals(61, x >>> 1);
+ x = -123;
+ assertEquals(x, x >> 0);
+ assertEquals(x, x << 0);
+ assertEquals(0x10000 * 0x10000 + x, x >>> 0);
+ assertEquals(-62, x >> 1);
+ assertEquals(-246, x << 1);
+ assertEquals(0x10000 * 0x8000 - 62, x >>> 1);
+ // Answer is non-Smi so the subtraction is not folded in the code
+ // generator.
+ assertEquals(-0x40000001, -0x3fffffff - 2);
+
+ x = 123;
+ assertEquals(0, x & 0);
+
+ // Answer is non-smi and lhs of << is a temporary heap number that we can
+ // overwrite.
+ x = 123.0001;
+ assertEquals(1073741824, (x * x) << 30);
+ x = 123;
+ // Answer is non-smi and lhs of << is a temporary heap number that we think
+ // we can overwrite (but we can't because it's a Smi).
+ assertEquals(1073741824, (x * x) << 30);
+}
+
+
test();
+BoolTest();
+ShiftTest();
diff --git a/deps/v8/test/mjsunit/debug-backtrace.js b/deps/v8/test/mjsunit/debug-backtrace.js
index 940c4cb4b..f08f6390e 100644
--- a/deps/v8/test/mjsunit/debug-backtrace.js
+++ b/deps/v8/test/mjsunit/debug-backtrace.js
@@ -32,10 +32,14 @@ function f(x, y) {
a=1;
};
-function g() {
+var m = function() {
new f(1);
};
+function g() {
+ m();
+};
+
// Get the Debug object exposed from the debug context global object.
Debug = debug.Debug
@@ -90,22 +94,26 @@ function listener(event, exec_state, event_data, data) {
// Get the backtrace.
var json;
json = '{"seq":0,"type":"request","command":"backtrace"}'
- response = new ParsedResponse(dcp.processDebugJSONRequest(json));
+ var resp = dcp.processDebugJSONRequest(json);
+ response = new ParsedResponse(resp);
backtrace = response.body();
assertEquals(0, backtrace.fromFrame);
- assertEquals(3, backtrace.toFrame);
- assertEquals(3, backtrace.totalFrames);
+ assertEquals(4, backtrace.toFrame);
+ assertEquals(4, backtrace.totalFrames);
var frames = backtrace.frames;
- assertEquals(3, frames.length);
+ assertEquals(4, frames.length);
for (var i = 0; i < frames.length; i++) {
assertEquals('frame', frames[i].type);
}
assertEquals(0, frames[0].index);
assertEquals("f", response.lookup(frames[0].func.ref).name);
assertEquals(1, frames[1].index);
- assertEquals("g", response.lookup(frames[1].func.ref).name);
+ assertEquals("", response.lookup(frames[1].func.ref).name);
+ assertEquals("m", response.lookup(frames[1].func.ref).inferredName);
assertEquals(2, frames[2].index);
- assertEquals("", response.lookup(frames[2].func.ref).name);
+ assertEquals("g", response.lookup(frames[2].func.ref).name);
+ assertEquals(3, frames[3].index);
+ assertEquals("", response.lookup(frames[3].func.ref).name);
// Get backtrace with two frames.
json = '{"seq":0,"type":"request","command":"backtrace","arguments":{"fromFrame":1,"toFrame":3}}'
@@ -113,16 +121,17 @@ function listener(event, exec_state, event_data, data) {
backtrace = response.body();
assertEquals(1, backtrace.fromFrame);
assertEquals(3, backtrace.toFrame);
- assertEquals(3, backtrace.totalFrames);
+ assertEquals(4, backtrace.totalFrames);
var frames = backtrace.frames;
assertEquals(2, frames.length);
for (var i = 0; i < frames.length; i++) {
assertEquals('frame', frames[i].type);
}
assertEquals(1, frames[0].index);
- assertEquals("g", response.lookup(frames[0].func.ref).name);
+ assertEquals("", response.lookup(frames[0].func.ref).name);
+ assertEquals("m", response.lookup(frames[0].func.ref).inferredName);
assertEquals(2, frames[1].index);
- assertEquals("", response.lookup(frames[1].func.ref).name);
+ assertEquals("g", response.lookup(frames[1].func.ref).name);
// Get the individual frames.
json = '{"seq":0,"type":"request","command":"frame"}'
@@ -158,16 +167,17 @@ function listener(event, exec_state, event_data, data) {
response = new ParsedResponse(dcp.processDebugJSONRequest(json));
frame = response.body();
assertEquals(1, frame.index);
- assertEquals("g", response.lookup(frame.func.ref).name);
+ assertEquals("", response.lookup(frame.func.ref).name);
+ assertEquals("m", response.lookup(frame.func.ref).inferredName);
assertFalse(frame.constructCall);
assertEquals(35, frame.line);
assertEquals(2, frame.column);
assertEquals(0, frame.arguments.length);
- json = '{"seq":0,"type":"request","command":"frame","arguments":{"number":2}}'
+ json = '{"seq":0,"type":"request","command":"frame","arguments":{"number":3}}'
response = new ParsedResponse(dcp.processDebugJSONRequest(json));
frame = response.body();
- assertEquals(2, frame.index);
+ assertEquals(3, frame.index);
assertEquals("", response.lookup(frame.func.ref).name);
// Source slices for the individual frames (they all refer to this script).
diff --git a/deps/v8/test/mjsunit/debug-handle.js b/deps/v8/test/mjsunit/debug-handle.js
index 64a68a86e..c7ab76af4 100644
--- a/deps/v8/test/mjsunit/debug-handle.js
+++ b/deps/v8/test/mjsunit/debug-handle.js
@@ -95,8 +95,8 @@ function listener(event, exec_state, event_data, data) {
// Test some illegal lookup requests.
lookupRequest(dcp, void 0, false);
- lookupRequest(dcp, '{"handle":"a"}', false);
- lookupRequest(dcp, '{"handle":-1}', false);
+ lookupRequest(dcp, '{"handles":["a"]}', false);
+ lookupRequest(dcp, '{"handles":[-1]}', false);
// Evaluate and get some handles.
var handle_o = evaluateRequest(dcp, '{"expression":"o"}');
@@ -109,24 +109,28 @@ function listener(event, exec_state, event_data, data) {
var response;
var count;
- response = lookupRequest(dcp, '{"handle":' + handle_o + '}', true);
- assertEquals(handle_o, response.body.handle);
+ response = lookupRequest(dcp, '{"handles":[' + handle_o + ']}', true);
+ var obj = response.body[handle_o];
+ assertTrue(!!obj, 'Object not found: ' + handle_o);
+ assertEquals(handle_o, obj.handle);
count = 0;
- for (i in response.body.properties) {
- switch (response.body.properties[i].name) {
+ for (i in obj.properties) {
+ switch (obj.properties[i].name) {
case 'o':
- response.body.properties[i].ref = handle_o;
+ obj.properties[i].ref = handle_o;
count++;
break;
case 'p':
- response.body.properties[i].ref = handle_p;
+ obj.properties[i].ref = handle_p;
count++;
break;
}
}
assertEquals(2, count, 'Either "o" or "p" not found');
- response = lookupRequest(dcp, '{"handle":' + handle_p + '}', true);
- assertEquals(handle_p, response.body.handle);
+ response = lookupRequest(dcp, '{"handles":[' + handle_p + ']}', true);
+ obj = response.body[handle_p];
+ assertTrue(!!obj, 'Object not found: ' + handle_p);
+ assertEquals(handle_p, obj.handle);
// Check handles for functions on the stack.
var handle_f = evaluateRequest(dcp, '{"expression":"f"}');
@@ -136,28 +140,31 @@ function listener(event, exec_state, event_data, data) {
assertFalse(handle_f == handle_g, "f and g have he same handle");
assertEquals(handle_g, handle_caller, "caller for f should be g");
- response = lookupRequest(dcp, '{"handle":' + handle_f + '}', true);
- assertEquals(handle_f, response.body.handle);
+ response = lookupRequest(dcp, '{"handles":[' + handle_f + ']}', true);
+ obj = response.body[handle_f];
+ assertEquals(handle_f, obj.handle);
+
count = 0;
- for (i in response.body.properties) {
- var arguments = '{"handle":' + response.body.properties[i].ref + '}'
- switch (response.body.properties[i].name) {
+ for (i in obj.properties) {
+ var ref = obj.properties[i].ref;
+ var arguments = '{"handles":[' + ref + ']}';
+ switch (obj.properties[i].name) {
case 'name':
var response_name;
response_name = lookupRequest(dcp, arguments, true);
- assertEquals('string', response_name.body.type);
- assertEquals("f", response_name.body.value);
+ assertEquals('string', response_name.body[ref].type);
+ assertEquals("f", response_name.body[ref].value);
count++;
break;
case 'length':
var response_length;
response_length = lookupRequest(dcp, arguments, true);
- assertEquals('number', response_length.body.type);
- assertEquals(1, response_length.body.value);
+ assertEquals('number', response_length.body[ref].type);
+ assertEquals(1, response_length.body[ref].value);
count++;
break;
case 'caller':
- assertEquals(handle_g, response.body.properties[i].ref);
+ assertEquals(handle_g, obj.properties[i].ref);
count++;
break;
}
@@ -165,6 +172,49 @@ function listener(event, exec_state, event_data, data) {
assertEquals(3, count, 'Either "name", "length" or "caller" not found');
+ // Resolve all at once.
+ var refs = [];
+ for (i in obj.properties) {
+ refs.push(obj.properties[i].ref);
+ }
+
+ var arguments = '{"handles":[' + refs.join(',') + ']}';
+ response = lookupRequest(dcp, arguments, true);
+ count = 0;
+ for (i in obj.properties) {
+ var ref = obj.properties[i].ref;
+ var val = response.body[ref];
+ assertTrue(!!val, 'Failed to lookup "' + obj.properties[i].name + '"');
+ switch (obj.properties[i].name) {
+ case 'name':
+ assertEquals('string', val.type);
+ assertEquals("f", val.value);
+ count++;
+ break;
+ case 'length':
+ assertEquals('number', val.type);
+ assertEquals(1, val.value);
+ count++;
+ break;
+ case 'caller':
+ assertEquals('function', val.type);
+ assertEquals(handle_g, ref);
+ count++;
+ break;
+ }
+ }
+ assertEquals(3, count, 'Either "name", "length" or "caller" not found');
+
+ count = 0;
+ for (var handle in response.body) {
+ assertTrue(refs.indexOf(parseInt(handle)) != -1,
+ 'Handle not in the request: ' + handle);
+ count++;
+ }
+ assertEquals(count, obj.properties.length,
+ 'Unexpected number of resolved objects');
+
+
// Indicate that all was processed.
listenerComplete = true;
}
@@ -195,5 +245,5 @@ p.p = p;
g(o);
// Make sure that the debug event listener vas invoked.
-assertTrue(listenerComplete, "listener did not run to completion");
+assertTrue(listenerComplete, "listener did not run to completion: " + exception);
assertFalse(exception, "exception in listener")
diff --git a/deps/v8/test/mjsunit/debug-setbreakpoint.js b/deps/v8/test/mjsunit/debug-setbreakpoint.js
index 904ec187f..f8d9b157b 100644
--- a/deps/v8/test/mjsunit/debug-setbreakpoint.js
+++ b/deps/v8/test/mjsunit/debug-setbreakpoint.js
@@ -54,14 +54,14 @@ function testArguments(dcp, arguments, success, is_script) {
var json_response = dcp.processDebugJSONRequest(request);
var response = safeEval(json_response);
if (success) {
- assertTrue(response.success, json_response);
+ assertTrue(response.success, request + ' -> ' + json_response);
if (is_script) {
- assertEquals('scriptName', response.body.type, json_response);
+ assertEquals('scriptName', response.body.type, request + ' -> ' + json_response);
} else {
- assertEquals('scriptId', response.body.type, json_response);
+ assertEquals('scriptId', response.body.type, request + ' -> ' + json_response);
}
} else {
- assertFalse(response.success, json_response);
+ assertFalse(response.success, request + ' -> ' + json_response);
}
}
@@ -75,6 +75,8 @@ function listener(event, exec_state, event_data, data) {
var request = '{' + base_request + '}'
var response = safeEval(dcp.processDebugJSONRequest(request));
assertFalse(response.success);
+
+ var mirror;
testArguments(dcp, '{}', false);
testArguments(dcp, '{"type":"xx"}', false);
@@ -86,6 +88,9 @@ function listener(event, exec_state, event_data, data) {
testArguments(dcp, '{"type":"function","target":"f","line":-1}', false);
testArguments(dcp, '{"type":"function","target":"f","column":-1}', false);
testArguments(dcp, '{"type":"function","target":"f","ignoreCount":-1}', false);
+ testArguments(dcp, '{"type":"handle","target":"-1"}', false);
+ mirror = debug.MakeMirror(o);
+ testArguments(dcp, '{"type":"handle","target":' + mirror.handle() + '}', false);
// Test some legal setbreakpoint requests.
testArguments(dcp, '{"type":"function","target":"f"}', true, false);
@@ -106,6 +111,11 @@ function listener(event, exec_state, event_data, data) {
testArguments(dcp, '{"type":"scriptId","target":' + g_script_id + ',"line":' + g_line + '}', true, false);
testArguments(dcp, '{"type":"scriptId","target":' + h_script_id + ',"line":' + h_line + '}', true, false);
+ mirror = debug.MakeMirror(f);
+ testArguments(dcp, '{"type":"handle","target":' + mirror.handle() + '}', true, false);
+ mirror = debug.MakeMirror(o.a);
+ testArguments(dcp, '{"type":"handle","target":' + mirror.handle() + '}', true, false);
+
// Indicate that all was processed.
listenerComplete = true;
}
@@ -127,6 +137,8 @@ function g() {
eval('function h(){}');
+o = {a:function(){},b:function(){}}
+
// Check the script ids for the test functions.
f_script_id = Debug.findScript(f).id;
g_script_id = Debug.findScript(g).id;
diff --git a/deps/v8/test/mjsunit/enumeration-order.js b/deps/v8/test/mjsunit/enumeration-order.js
index 699a636cc..a328121d7 100644
--- a/deps/v8/test/mjsunit/enumeration-order.js
+++ b/deps/v8/test/mjsunit/enumeration-order.js
@@ -26,17 +26,17 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function check_enumeration_order(obj) {
- var value = 0;
+ var value = 0;
for (var name in obj) assertTrue(value < obj[name]);
value = obj[name];
}
function make_object(size) {
var a = new Object();
-
+
for (var i = 0; i < size; i++) a["a_" + i] = i + 1;
check_enumeration_order(a);
-
+
for (var i = 0; i < size; i +=3) delete a["a_" + i];
check_enumeration_order(a);
}
@@ -51,9 +51,59 @@ function make_literal_object(size) {
code += "a_" + (size - 1) + " : " + size;
code += " }";
eval("var a = " + code);
- check_enumeration_order(a);
+ check_enumeration_order(a);
}
-// Validate the enumeration order for object literals up to 100 named properties.
+// Validate the enumeration order for object literals up to 100 named
+// properties.
for (var j = 1; j< 100; j++) make_literal_object(j);
+// We enumerate indexed properties in numerical order followed by
+// named properties in insertion order, followed by indexed properties
+// of the prototype object in numerical order, followed by named
+// properties of the prototype object in insertion order, and so on.
+//
+// This enumeration order is not required by the specification, so
+// this just documents our choice.
+var proto2 = {};
+proto2[140000] = 0;
+proto2.a = 0;
+proto2[2] = 0;
+proto2[3] = 0; // also on the 'proto1' object
+proto2.b = 0;
+proto2[4294967295] = 0;
+proto2.c = 0;
+proto2[4294967296] = 0;
+
+var proto1 = {};
+proto1[5] = 0;
+proto1.d = 0;
+proto1[3] = 0;
+proto1.e = 0;
+proto1.f = 0; // also on the 'o' object
+
+var o = {};
+o[-23] = 0;
+o[300000000000] = 0;
+o[23] = 0;
+o.f = 0;
+o.g = 0;
+o[-4] = 0;
+o[42] = 0;
+
+o.__proto__ = proto1;
+proto1.__proto__ = proto2;
+
+var expected = ['23', '42', // indexed from 'o'
+ '-23', '300000000000', 'f', 'g', '-4', // named from 'o'
+ '3', '5', // indexed from 'proto1'
+ 'd', 'e', // named from 'proto1'
+ '2', '140000', '4294967295', // indexed from 'proto2'
+ 'a', 'b', 'c', '4294967296']; // named from 'proto2'
+var actual = [];
+for (var p in o) actual.push(p);
+assertArrayEquals(expected, actual);
+
+
+
+
diff --git a/deps/v8/test/mjsunit/eval-enclosing-function-name.js b/deps/v8/test/mjsunit/eval-enclosing-function-name.js
new file mode 100644
index 000000000..422f03f37
--- /dev/null
+++ b/deps/v8/test/mjsunit/eval-enclosing-function-name.js
@@ -0,0 +1,76 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// From within 'eval', the name of the enclosing function should be
+// visible.
+
+var f = function y() { return typeof y; };
+assertEquals("function", f());
+
+
+f = function y() { return eval('typeof y'); };
+assertEquals("function", f());
+
+
+f = function y() { y = 3; return typeof y; };
+assertEquals("function", f());
+
+
+f = function y() { y += 3; return typeof y; };
+assertEquals("function", f());
+
+
+f = function y() { y &= y; return typeof y; };
+assertEquals("function", f());
+
+
+f = function y() { y = 3; return eval('typeof y'); }
+assertEquals("function", f());
+
+
+f = function y() { var y = 3; return typeof y; }
+assertEquals("number", f());
+
+
+f = function y() { var y = 3; return eval('typeof y'); }
+assertEquals("number", f());
+
+
+f = function y() { eval('y = 3'); return typeof y; }
+assertEquals("function", f());
+
+
+f = function y() { eval('y = 3'); return eval('typeof y'); }
+assertEquals("function", f());
+
+
+f = function y() { eval('var y = 3'); return typeof y; }
+assertEquals("number", f());
+
+
+f = function y() { eval('var y = 3'); return eval('typeof y'); }
+assertEquals("number", f());
diff --git a/deps/v8/test/mjsunit/json.js b/deps/v8/test/mjsunit/json.js
new file mode 100644
index 000000000..47582643c
--- /dev/null
+++ b/deps/v8/test/mjsunit/json.js
@@ -0,0 +1,197 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+function GenericToJSONChecks(Constructor, value, alternative) {
+ var n1 = new Constructor(value);
+ n1.valueOf = function () { return alternative; };
+ assertEquals(alternative, n1.toJSON());
+ var n2 = new Constructor(value);
+ n2.valueOf = null;
+ assertThrows(function () { n2.toJSON(); }, TypeError);
+ var n3 = new Constructor(value);
+ n3.valueOf = function () { return {}; };
+ assertThrows(function () { n3.toJSON(); }, TypeError, 'result_not_primitive');
+ var n4 = new Constructor(value);
+ n4.valueOf = function () {
+ assertEquals(0, arguments.length);
+ assertEquals(this, n4);
+ return null;
+ };
+ assertEquals(null, n4.toJSON());
+}
+
+// Number toJSON
+assertEquals(3, (3).toJSON());
+assertEquals(3, (3).toJSON(true));
+assertEquals(4, (new Number(4)).toJSON());
+GenericToJSONChecks(Number, 5, 6);
+
+// Boolean toJSON
+assertEquals(true, (true).toJSON());
+assertEquals(true, (true).toJSON(false));
+assertEquals(false, (false).toJSON());
+assertEquals(true, (new Boolean(true)).toJSON());
+GenericToJSONChecks(Boolean, true, false);
+GenericToJSONChecks(Boolean, false, true);
+
+// String toJSON
+assertEquals("flot", "flot".toJSON());
+assertEquals("flot", "flot".toJSON(3));
+assertEquals("tolf", (new String("tolf")).toJSON());
+GenericToJSONChecks(String, "x", "y");
+
+// Date toJSON
+assertEquals("1970-01-01T00:00:00Z", new Date(0).toJSON());
+assertEquals("1979-01-11T08:00:00Z", new Date("1979-01-11 08:00 GMT").toJSON());
+assertEquals("2005-05-05T05:05:05Z", new Date("2005-05-05 05:05:05 GMT").toJSON());
+var n1 = new Date(10000);
+n1.toISOString = function () { return "foo"; };
+assertEquals("foo", n1.toJSON());
+var n2 = new Date(10001);
+n2.toISOString = null;
+assertThrows(function () { n2.toJSON(); }, TypeError);
+var n3 = new Date(10002);
+n3.toISOString = function () { return {}; };
+assertThrows(function () { n3.toJSON(); }, TypeError, "result_not_primitive");
+var n4 = new Date(10003);
+n4.toISOString = function () {
+ assertEquals(0, arguments.length);
+ assertEquals(this, n4);
+ return null;
+};
+assertEquals(null, n4.toJSON());
+
+assertEquals(Object.prototype, JSON.__proto__);
+assertEquals("[object JSON]", Object.prototype.toString.call(JSON));
+
+// DontEnum
+for (var p in this)
+ assertFalse(p == "JSON");
+
+// Parse
+
+assertEquals({}, JSON.parse("{}"));
+assertEquals(null, JSON.parse("null"));
+assertEquals(true, JSON.parse("true"));
+assertEquals(false, JSON.parse("false"));
+assertEquals("foo", JSON.parse('"foo"'));
+assertEquals("f\no", JSON.parse('"f\\no"'));
+assertEquals(1.1, JSON.parse("1.1"));
+assertEquals(1, JSON.parse("1.0"));
+assertEquals(0.0000000003, JSON.parse("3e-10"));
+assertEquals([], JSON.parse("[]"));
+assertEquals([1], JSON.parse("[1]"));
+assertEquals([1, "2", true, null], JSON.parse('[1, "2", true, null]'));
+
+function GetFilter(name) {
+ function Filter(key, value) {
+ return (key == name) ? undefined : value;
+ }
+ return Filter;
+}
+
+var pointJson = '{"x": 1, "y": 2}';
+assertEquals({'x': 1, 'y': 2}, JSON.parse(pointJson));
+assertEquals({'x': 1}, JSON.parse(pointJson, GetFilter('y')));
+assertEquals({'y': 2}, JSON.parse(pointJson, GetFilter('x')));
+assertEquals([1, 2, 3], JSON.parse("[1, 2, 3]"));
+assertEquals([1, undefined, 3], JSON.parse("[1, 2, 3]", GetFilter(1)));
+assertEquals([1, 2, undefined], JSON.parse("[1, 2, 3]", GetFilter(2)));
+
+function DoubleNumbers(key, value) {
+ return (typeof value == 'number') ? 2 * value : value;
+}
+
+var deepObject = '{"a": {"b": 1, "c": 2}, "d": {"e": {"f": 3}}}';
+assertEquals({"a": {"b": 1, "c": 2}, "d": {"e": {"f": 3}}},
+ JSON.parse(deepObject));
+assertEquals({"a": {"b": 2, "c": 4}, "d": {"e": {"f": 6}}},
+ JSON.parse(deepObject, DoubleNumbers));
+
+function TestInvalid(str) {
+ assertThrows(function () { JSON.parse(str); }, SyntaxError);
+}
+
+TestInvalid('abcdef');
+TestInvalid('isNaN()');
+TestInvalid('{"x": [1, 2, deepObject]}');
+TestInvalid('[1, [2, [deepObject], 3], 4]');
+TestInvalid('function () { return 0; }');
+
+TestInvalid("[1, 2");
+TestInvalid('{"x": 3');
+
+// Stringify
+
+assertEquals("true", JSON.stringify(true));
+assertEquals("false", JSON.stringify(false));
+assertEquals("null", JSON.stringify(null));
+assertEquals("false", JSON.stringify({toJSON: function () { return false; }}));
+assertEquals("4", JSON.stringify(4));
+assertEquals('"foo"', JSON.stringify("foo"));
+assertEquals("null", JSON.stringify(Infinity));
+assertEquals("null", JSON.stringify(-Infinity));
+assertEquals("null", JSON.stringify(NaN));
+assertEquals("4", JSON.stringify(new Number(4)));
+assertEquals('"bar"', JSON.stringify(new String("bar")));
+
+assertEquals('"foo\\u0000bar"', JSON.stringify("foo\0bar"));
+assertEquals('"f\\"o\'o\\\\b\\ba\\fr\\nb\\ra\\tz"',
+ JSON.stringify("f\"o\'o\\b\ba\fr\nb\ra\tz"));
+
+assertEquals("[1,2,3]", JSON.stringify([1, 2, 3]));
+assertEquals("[\n 1,\n 2,\n 3\n]", JSON.stringify([1, 2, 3], null, 1));
+assertEquals("[\n 1,\n 2,\n 3\n]", JSON.stringify([1, 2, 3], null, 2));
+assertEquals("[\n 1,\n 2,\n 3\n]",
+ JSON.stringify([1, 2, 3], null, new Number(2)));
+assertEquals("[\n^1,\n^2,\n^3\n]", JSON.stringify([1, 2, 3], null, "^"));
+assertEquals("[\n^1,\n^2,\n^3\n]",
+ JSON.stringify([1, 2, 3], null, new String("^")));
+assertEquals("[\n 1,\n 2,\n [\n 3,\n [\n 4\n ],\n 5\n ],\n 6,\n 7\n]",
+ JSON.stringify([1, 2, [3, [4], 5], 6, 7], null, 1));
+assertEquals("[]", JSON.stringify([], null, 1));
+assertEquals("[1,2,[3,[4],5],6,7]",
+ JSON.stringify([1, 2, [3, [4], 5], 6, 7], null));
+assertEquals("[2,4,[6,[8],10],12,14]",
+ JSON.stringify([1, 2, [3, [4], 5], 6, 7], DoubleNumbers));
+
+var circular = [1, 2, 3];
+circular[2] = circular;
+assertThrows(function () { JSON.stringify(circular); }, TypeError);
+
+var singleton = [];
+var multiOccurrence = [singleton, singleton, singleton];
+assertEquals("[[],[],[]]", JSON.stringify(multiOccurrence));
+
+assertEquals('{"x":5,"y":6}', JSON.stringify({x:5,y:6}));
+assertEquals('{"x":5}', JSON.stringify({x:5,y:6}, ['x']));
+assertEquals('{\n "a": "b",\n "c": "d"\n}',
+ JSON.stringify({a:"b",c:"d"}, null, 1));
+assertEquals('{"y":6,"x":5}', JSON.stringify({x:5,y:6}, ['y', 'x']));
+
+assertEquals(undefined, JSON.stringify(undefined));
+assertEquals(undefined, JSON.stringify(function () { }));
diff --git a/deps/v8/test/mjsunit/keyed-ic.js b/deps/v8/test/mjsunit/keyed-ic.js
index d37bd034c..a6726ed49 100644
--- a/deps/v8/test/mjsunit/keyed-ic.js
+++ b/deps/v8/test/mjsunit/keyed-ic.js
@@ -145,6 +145,35 @@ runTest();
// ----------------------------------------------------------------------
+// Indexed access.
+// ----------------------------------------------------------------------
+runTest = function() {
+ var o = [ 42, 43 ];
+
+ var initial_X = 0;
+ var X = initial_X;
+ var Y = 1;
+
+ function fieldTest(change_index) {
+ for (var i = 0; i < 10; i++) {
+ var property = o[X];
+ if (i <= change_index) {
+ assertEquals(42, property);
+ } else {
+ assertEquals(43, property);
+ }
+ if (i == change_index) X = Y;
+ }
+ X = initial_X;
+ };
+
+ for (var i = 0; i < 10; i++) fieldTest(i);
+}
+
+runTest();
+
+
+// ----------------------------------------------------------------------
// Constant function access.
// ----------------------------------------------------------------------
runTest = function() {
diff --git a/deps/v8/test/mjsunit/mirror-unresolved-function.js b/deps/v8/test/mjsunit/mirror-unresolved-function.js
index 21d0e561b..8d8ca37f8 100644
--- a/deps/v8/test/mjsunit/mirror-unresolved-function.js
+++ b/deps/v8/test/mjsunit/mirror-unresolved-function.js
@@ -57,6 +57,7 @@ assertEquals('function', mirror.type());
assertFalse(mirror.isPrimitive());
assertEquals("Function", mirror.className());
assertEquals("f", mirror.name());
+assertEquals('undefined', typeof mirror.inferredName());
assertFalse(mirror.resolved());
assertEquals(void 0, mirror.source());
assertEquals('undefined', mirror.constructorFunction().type());
@@ -75,4 +76,5 @@ assertEquals(mirror.prototypeObject().handle(), fromJSON.prototypeObject.ref, 'U
assertEquals('undefined', refs.lookup(fromJSON.prototypeObject.ref).type, 'Unexpected prototype object type in JSON');
assertFalse(fromJSON.resolved);
assertEquals("f", fromJSON.name);
+assertFalse('inferredName' in fromJSON);
assertEquals(void 0, fromJSON.source);
diff --git a/deps/v8/test/mjsunit/mjsunit.js b/deps/v8/test/mjsunit/mjsunit.js
index 3570d689c..2c52a31e6 100644
--- a/deps/v8/test/mjsunit/mjsunit.js
+++ b/deps/v8/test/mjsunit/mjsunit.js
@@ -51,8 +51,30 @@ function fail(expected, found, name_opt) {
}
+function deepObjectEquals(a, b) {
+ var aProps = [];
+ for (var key in a)
+ aProps.push(key);
+ var bProps = [];
+ for (var key in b)
+ bProps.push(key);
+ aProps.sort();
+ bProps.sort();
+ if (!deepEquals(aProps, bProps))
+ return false;
+ for (var i = 0; i < aProps.length; i++) {
+ if (!deepEquals(a[aProps[i]], b[aProps[i]]))
+ return false;
+ }
+ return true;
+}
+
+
function deepEquals(a, b) {
if (a == b) return true;
+ if (typeof a == "number" && typeof b == "number" && isNaN(a) && isNaN(b)) {
+ return true;
+ }
if ((typeof a) !== 'object' || (typeof b) !== 'object' ||
(a === null) || (b === null))
return false;
@@ -70,8 +92,9 @@ function deepEquals(a, b) {
}
}
return true;
+ } else {
+ return deepObjectEquals(a, b);
}
- return false;
}
@@ -113,12 +136,34 @@ function assertNaN(value, name_opt) {
}
-function assertThrows(code) {
+function assertNull(value, name_opt) {
+ if (value !== null) {
+ fail("null", value, name_opt);
+ }
+}
+
+
+function assertNotNull(value, name_opt) {
+ if (value === null) {
+ fail("not null", value, name_opt);
+ }
+}
+
+
+function assertThrows(code, type_opt, cause_opt) {
var threwException = true;
try {
- eval(code);
+ if (typeof code == 'function') {
+ code();
+ } else {
+ eval(code);
+ }
threwException = false;
} catch (e) {
+ if (typeof type_opt == 'function')
+ assertInstanceof(e, type_opt);
+ if (arguments.length >= 3)
+ assertEquals(e.type, cause_opt);
// Do nothing.
}
if (!threwException) assertTrue(false, "did not throw exception");
diff --git a/deps/v8/test/mjsunit/mjsunit.status b/deps/v8/test/mjsunit/mjsunit.status
index 5a7607872..4bb7c1652 100644
--- a/deps/v8/test/mjsunit/mjsunit.status
+++ b/deps/v8/test/mjsunit/mjsunit.status
@@ -48,19 +48,19 @@ unicode-test: PASS, (PASS || FAIL) if $mode == debug
# Bug number 1020483: Debug tests fail on ARM.
debug-constructor: CRASH, FAIL
debug-continue: SKIP
-debug-evaluate-recursive: CRASH, FAIL if $mode == debug
-debug-changebreakpoint: CRASH, FAIL if $mode == debug
-debug-clearbreakpoint: CRASH, FAIL if $mode == debug
-debug-conditional-breakpoints: CRASH, FAIL if $mode == debug
-debug-evaluate: CRASH, FAIL if $mode == debug
-debug-ignore-breakpoints: CRASH, FAIL if $mode == debug
-debug-multiple-breakpoints: CRASH, FAIL if $mode == debug
-debug-setbreakpoint: CRASH, FAIL if $mode == debug
+debug-evaluate-recursive: CRASH || FAIL
+debug-changebreakpoint: CRASH || FAIL
+debug-clearbreakpoint: CRASH || FAIL
+debug-conditional-breakpoints: FAIL
+debug-evaluate: CRASH || FAIL
+debug-ignore-breakpoints: CRASH || FAIL
+debug-multiple-breakpoints: CRASH || FAIL
+debug-setbreakpoint: CRASH || FAIL || PASS
debug-step-stub-callfunction: SKIP
debug-stepin-constructor: CRASH, FAIL
debug-step: SKIP
debug-breakpoints: PASS || FAIL
-debug-handle: CRASH, FAIL if $mode == debug
+debug-handle: CRASH || FAIL || PASS
regress/regress-269: SKIP
# Bug number 130 http://code.google.com/p/v8/issues/detail?id=130
diff --git a/deps/v8/test/mjsunit/negate.js b/deps/v8/test/mjsunit/negate.js
index 3bf411156..70daf2435 100644
--- a/deps/v8/test/mjsunit/negate.js
+++ b/deps/v8/test/mjsunit/negate.js
@@ -30,9 +30,9 @@ const SMI_MIN = -(1 << 30);
function testmulneg(a, b) {
var base = a * b;
- assertEquals(-base, a * -b);
- assertEquals(-base, -a * b);
- assertEquals(base, -a * -b);
+ assertEquals(-base, a * -b, "a * -b where a = " + a + ", b = " + b);
+ assertEquals(-base, -a * b, "-a * b where a = " + a + ", b = " + b);
+ assertEquals(base, -a * -b, "*-a * -b where a = " + a + ", b = " + b);
}
testmulneg(2, 3);
diff --git a/deps/v8/test/mjsunit/number-limits.js b/deps/v8/test/mjsunit/number-limits.js
index 1d9a1e558..99ed4e1b4 100644
--- a/deps/v8/test/mjsunit/number-limits.js
+++ b/deps/v8/test/mjsunit/number-limits.js
@@ -33,10 +33,14 @@ function testLimits() {
var addAboveMax = Number.MAX_VALUE + 1/eps;
var mulBelowMin = Number.MIN_VALUE * (1 - eps);
var addBelowMin = Number.MIN_VALUE - eps;
- assertTrue(mulAboveMax == Number.MAX_VALUE || mulAboveMax == Infinity);
- assertTrue(addAboveMax == Number.MAX_VALUE || addAboveMax == Infinity);
- assertTrue(mulBelowMin == Number.MIN_VALUE || mulBelowMin <= 0);
- assertTrue(addBelowMin == Number.MIN_VALUE || addBelowMin <= 0);
+ assertTrue(mulAboveMax == Number.MAX_VALUE ||
+ mulAboveMax == Infinity, "mul" + i);
+ assertTrue(addAboveMax == Number.MAX_VALUE ||
+ addAboveMax == Infinity, "add" + i);
+ assertTrue(mulBelowMin == Number.MIN_VALUE ||
+ mulBelowMin <= 0, "mul2" + i);
+ assertTrue(addBelowMin == Number.MIN_VALUE ||
+ addBelowMin <= 0, "add2" + i);
}
}
diff --git a/deps/v8/test/mjsunit/receiver-in-with-calls.js b/deps/v8/test/mjsunit/receiver-in-with-calls.js
new file mode 100644
index 000000000..5f2bdac20
--- /dev/null
+++ b/deps/v8/test/mjsunit/receiver-in-with-calls.js
@@ -0,0 +1,47 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// When invoking functions from within a 'with' statement, we must set
+// the receiver to the object where we found the function.
+
+(function () {
+ var x = { get_this: function() { return this; } };
+ assertTrue(x === x.get_this());
+ with (x) assertTrue(x === get_this());
+})();
+
+
+assertTrue({ f: function() {
+ function g() { return this; };
+ return eval("g")();
+} }.f() == this);
+
+
+assertTrue({ f: function() {
+ function g() { return this; };
+ return eval("g()");
+} }.f() == this);
diff --git a/deps/v8/test/mjsunit/regexp-multiline-stack-trace.js b/deps/v8/test/mjsunit/regexp-multiline-stack-trace.js
index aa2de8875..fc248ef6a 100644
--- a/deps/v8/test/mjsunit/regexp-multiline-stack-trace.js
+++ b/deps/v8/test/mjsunit/regexp-multiline-stack-trace.js
@@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// The flags below are to test the trace-calls functionality and the
+// preallocated meessage memory.
// Flags: --trace-calls --preallocate-message-memory
/**
diff --git a/deps/v8/test/mjsunit/regress/regress-318.js b/deps/v8/test/mjsunit/regress/regress-318.js
index 9e00b5fba..e94f1cba1 100644
--- a/deps/v8/test/mjsunit/regress/regress-318.js
+++ b/deps/v8/test/mjsunit/regress/regress-318.js
@@ -25,11 +25,11 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Should not raise an exception.
+// Should not crash or raise an exception.
function test(value) {
if (typeof(value) == 'boolean') value = value + '';
if (typeof(value) == 'number') value = value + '';
}
-assertDoesNotThrow(test(0));
+assertDoesNotThrow('test(0)');
diff --git a/deps/v8/test/mjsunit/regress/regress-326.js b/deps/v8/test/mjsunit/regress/regress-326.js
new file mode 100644
index 000000000..fcd102e13
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-326.js
@@ -0,0 +1,40 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Should not crash or raise an exception.
+// Should sort non-array into equivalent of [37,42,undefined,,0]
+
+var nonArray = { length: 4, 0: 42, 2: 37, 3: undefined, 4: 0 };
+Array.prototype.sort.call(nonArray);
+
+assertEquals(4, nonArray.length, "preserve length");
+assertEquals(37, nonArray[0], "sort smallest first");
+assertEquals(42, nonArray[1], "sort largest last");
+assertTrue(2 in nonArray, "don't delete undefined");
+assertEquals(undefined, nonArray[2], "sort undefined after largest");
+assertFalse(3 in nonArray, "don't create non-existing");
+assertEquals(0, nonArray[4], "don't affect after length.");
diff --git a/deps/v8/test/mjsunit/smi-ops.js b/deps/v8/test/mjsunit/smi-ops.js
index bdd7509c9..7e571369b 100644
--- a/deps/v8/test/mjsunit/smi-ops.js
+++ b/deps/v8/test/mjsunit/smi-ops.js
@@ -34,7 +34,7 @@ const OBJ_42 = new (function() {
this.valueOf = function() { return 42; };
})();
-assertEquals(42, OBJ_42.valueOf());
+assertEquals(42, OBJ_42.valueOf());
function Add1(x) {
@@ -100,3 +100,488 @@ assertEquals(SMI_MIN - ONE_HUNDRED, Sub100(SMI_MIN)); // overflow
assertEquals(ONE_HUNDRED - SMI_MIN, Sub100Reversed(SMI_MIN)); // overflow
assertEquals(42 - ONE_HUNDRED, Sub100(OBJ_42)); // non-smi
assertEquals(ONE_HUNDRED - 42, Sub100Reversed(OBJ_42)); // non-smi
+
+
+function Shr1(x) {
+ return x >>> 1;
+}
+
+function Shr100(x) {
+ return x >>> 100;
+}
+
+function Shr1Reversed(x) {
+ return 1 >>> x;
+}
+
+function Shr100Reversed(x) {
+ return 100 >>> x;
+}
+
+function Sar1(x) {
+ return x >> 1;
+}
+
+function Sar100(x) {
+ return x >> 100;
+}
+
+function Sar1Reversed(x) {
+ return 1 >> x;
+}
+
+function Sar100Reversed(x) {
+ return 100 >> x;
+}
+
+
+assertEquals(0, Shr1(1));
+assertEquals(0, Sar1(1));
+assertEquals(0, Shr1Reversed(2));
+assertEquals(0, Sar1Reversed(2));
+assertEquals(1610612736, Shr1(SMI_MIN));
+assertEquals(-536870912, Sar1(SMI_MIN));
+assertEquals(1, Shr1Reversed(SMI_MIN));
+assertEquals(1, Sar1Reversed(SMI_MIN));
+assertEquals(21, Shr1(OBJ_42));
+assertEquals(21, Sar1(OBJ_42));
+assertEquals(0, Shr1Reversed(OBJ_42));
+assertEquals(0, Sar1Reversed(OBJ_42));
+
+assertEquals(6, Shr100(100));
+assertEquals(6, Sar100(100));
+assertEquals(12, Shr100Reversed(99));
+assertEquals(12, Sar100Reversed(99));
+assertEquals(201326592, Shr100(SMI_MIN));
+assertEquals(-67108864, Sar100(SMI_MIN));
+assertEquals(100, Shr100Reversed(SMI_MIN));
+assertEquals(100, Sar100Reversed(SMI_MIN));
+assertEquals(2, Shr100(OBJ_42));
+assertEquals(2, Sar100(OBJ_42));
+assertEquals(0, Shr100Reversed(OBJ_42));
+assertEquals(0, Sar100Reversed(OBJ_42));
+
+
+function Xor1(x) {
+ return x ^ 1;
+}
+
+function Xor100(x) {
+ return x ^ 100;
+}
+
+function Xor1Reversed(x) {
+ return 1 ^ x;
+}
+
+function Xor100Reversed(x) {
+ return 100 ^ x;
+}
+
+
+assertEquals(0, Xor1(1));
+assertEquals(3, Xor1Reversed(2));
+assertEquals(SMI_MIN + 1, Xor1(SMI_MIN));
+assertEquals(SMI_MIN + 1, Xor1Reversed(SMI_MIN));
+assertEquals(43, Xor1(OBJ_42));
+assertEquals(43, Xor1Reversed(OBJ_42));
+
+assertEquals(0, Xor100(100));
+assertEquals(7, Xor100Reversed(99));
+assertEquals(-1073741724, Xor100(SMI_MIN));
+assertEquals(-1073741724, Xor100Reversed(SMI_MIN));
+assertEquals(78, Xor100(OBJ_42));
+assertEquals(78, Xor100Reversed(OBJ_42));
+
+var x = 0x23; var y = 0x35;
+assertEquals(0x16, x ^ y);
+
+// Test shift operators on non-smi inputs, giving smi and non-smi results.
+function testShiftNonSmis() {
+ var pos_non_smi = 2000000000;
+ var neg_non_smi = -pos_non_smi;
+ var pos_smi = 1000000000;
+ var neg_smi = -pos_smi;
+
+ // Begin block A
+ assertEquals(pos_non_smi, (pos_non_smi) >> 0);
+ assertEquals(pos_non_smi, (pos_non_smi) >>> 0);
+ assertEquals(pos_non_smi, (pos_non_smi) << 0);
+ assertEquals(neg_non_smi, (neg_non_smi) >> 0);
+ assertEquals(neg_non_smi + 0x100000000, (neg_non_smi) >>> 0);
+ assertEquals(neg_non_smi, (neg_non_smi) << 0);
+ assertEquals(pos_smi, (pos_smi) >> 0);
+ assertEquals(pos_smi, (pos_smi) >>> 0);
+ assertEquals(pos_smi, (pos_smi) << 0);
+ assertEquals(neg_smi, (neg_smi) >> 0);
+ assertEquals(neg_smi + 0x100000000, (neg_smi) >>> 0);
+ assertEquals(neg_smi, (neg_smi) << 0);
+
+ assertEquals(pos_non_smi / 2, (pos_non_smi) >> 1);
+ assertEquals(pos_non_smi / 2, (pos_non_smi) >>> 1);
+ assertEquals(-0x1194D800, (pos_non_smi) << 1);
+ assertEquals(pos_non_smi / 8, (pos_non_smi) >> 3);
+ assertEquals(pos_non_smi / 8, (pos_non_smi) >>> 3);
+ assertEquals(-0x46536000, (pos_non_smi) << 3);
+ assertEquals(0x73594000, (pos_non_smi) << 4);
+ assertEquals(pos_non_smi, (pos_non_smi + 0.5) >> 0);
+ assertEquals(pos_non_smi, (pos_non_smi + 0.5) >>> 0);
+ assertEquals(pos_non_smi, (pos_non_smi + 0.5) << 0);
+ assertEquals(pos_non_smi / 2, (pos_non_smi + 0.5) >> 1);
+ assertEquals(pos_non_smi / 2, (pos_non_smi + 0.5) >>> 1);
+ assertEquals(-0x1194D800, (pos_non_smi + 0.5) << 1);
+ assertEquals(pos_non_smi / 8, (pos_non_smi + 0.5) >> 3);
+ assertEquals(pos_non_smi / 8, (pos_non_smi + 0.5) >>> 3);
+ assertEquals(-0x46536000, (pos_non_smi + 0.5) << 3);
+ assertEquals(0x73594000, (pos_non_smi + 0.5) << 4);
+
+ assertEquals(neg_non_smi / 2, (neg_non_smi) >> 1);
+ assertEquals(neg_non_smi / 2 + 0x100000000 / 2, (neg_non_smi) >>> 1);
+ assertEquals(0x1194D800, (neg_non_smi) << 1);
+ assertEquals(neg_non_smi / 8, (neg_non_smi) >> 3);
+ assertEquals(neg_non_smi / 8 + 0x100000000 / 8, (neg_non_smi) >>> 3);
+ assertEquals(0x46536000, (neg_non_smi) << 3);
+ assertEquals(-0x73594000, (neg_non_smi) << 4);
+ assertEquals(neg_non_smi, (neg_non_smi - 0.5) >> 0);
+ assertEquals(neg_non_smi + 0x100000000, (neg_non_smi - 0.5) >>> 0);
+ assertEquals(neg_non_smi, (neg_non_smi - 0.5) << 0);
+ assertEquals(neg_non_smi / 2, (neg_non_smi - 0.5) >> 1);
+ assertEquals(neg_non_smi / 2 + 0x100000000 / 2, (neg_non_smi - 0.5) >>> 1);
+ assertEquals(0x1194D800, (neg_non_smi - 0.5) << 1);
+ assertEquals(neg_non_smi / 8, (neg_non_smi - 0.5) >> 3);
+ assertEquals(neg_non_smi / 8 + 0x100000000 / 8, (neg_non_smi - 0.5) >>> 3);
+ assertEquals(0x46536000, (neg_non_smi - 0.5) << 3);
+ assertEquals(-0x73594000, (neg_non_smi - 0.5) << 4);
+
+ assertEquals(pos_smi / 2, (pos_smi) >> 1);
+ assertEquals(pos_smi / 2, (pos_smi) >>> 1);
+ assertEquals(pos_non_smi, (pos_smi) << 1);
+ assertEquals(pos_smi / 8, (pos_smi) >> 3);
+ assertEquals(pos_smi / 8, (pos_smi) >>> 3);
+ assertEquals(-0x2329b000, (pos_smi) << 3);
+ assertEquals(0x73594000, (pos_smi) << 5);
+ assertEquals(pos_smi, (pos_smi + 0.5) >> 0);
+ assertEquals(pos_smi, (pos_smi + 0.5) >>> 0);
+ assertEquals(pos_smi, (pos_smi + 0.5) << 0);
+ assertEquals(pos_smi / 2, (pos_smi + 0.5) >> 1);
+ assertEquals(pos_smi / 2, (pos_smi + 0.5) >>> 1);
+ assertEquals(pos_non_smi, (pos_smi + 0.5) << 1);
+ assertEquals(pos_smi / 8, (pos_smi + 0.5) >> 3);
+ assertEquals(pos_smi / 8, (pos_smi + 0.5) >>> 3);
+ assertEquals(-0x2329b000, (pos_smi + 0.5) << 3);
+ assertEquals(0x73594000, (pos_smi + 0.5) << 5);
+
+ assertEquals(neg_smi / 2, (neg_smi) >> 1);
+ assertEquals(neg_smi / 2 + 0x100000000 / 2, (neg_smi) >>> 1);
+ assertEquals(neg_non_smi, (neg_smi) << 1);
+ assertEquals(neg_smi / 8, (neg_smi) >> 3);
+ assertEquals(neg_smi / 8 + 0x100000000 / 8, (neg_smi) >>> 3);
+ assertEquals(0x46536000, (neg_smi) << 4);
+ assertEquals(-0x73594000, (neg_smi) << 5);
+ assertEquals(neg_smi, (neg_smi - 0.5) >> 0);
+ assertEquals(neg_smi + 0x100000000, (neg_smi - 0.5) >>> 0);
+ assertEquals(neg_smi, (neg_smi - 0.5) << 0);
+ assertEquals(neg_smi / 2, (neg_smi - 0.5) >> 1);
+ assertEquals(neg_smi / 2 + 0x100000000 / 2, (neg_smi - 0.5) >>> 1);
+ assertEquals(neg_non_smi, (neg_smi - 0.5) << 1);
+ assertEquals(neg_smi / 8, (neg_smi - 0.5) >> 3);
+ assertEquals(neg_smi / 8 + 0x100000000 / 8, (neg_smi - 0.5) >>> 3);
+ assertEquals(0x46536000, (neg_smi - 0.5) << 4);
+ assertEquals(-0x73594000, (neg_smi - 0.5) << 5);
+ // End block A
+
+ // Repeat block A with 2^32 added to positive numbers and
+ // 2^32 subtracted from negative numbers.
+ // Begin block A repeat 1
+ var two_32 = 0x100000000;
+ var neg_32 = -two_32;
+ assertEquals(pos_non_smi, (two_32 + pos_non_smi) >> 0);
+ assertEquals(pos_non_smi, (two_32 + pos_non_smi) >>> 0);
+ assertEquals(pos_non_smi, (two_32 + pos_non_smi) << 0);
+ assertEquals(neg_non_smi, (neg_32 + neg_non_smi) >> 0);
+ assertEquals(neg_non_smi + 0x100000000, (neg_32 + neg_non_smi) >>> 0);
+ assertEquals(neg_non_smi, (neg_32 + neg_non_smi) << 0);
+ assertEquals(pos_smi, (two_32 + pos_smi) >> 0);
+ assertEquals(pos_smi, (two_32 + pos_smi) >>> 0);
+ assertEquals(pos_smi, (two_32 + pos_smi) << 0);
+ assertEquals(neg_smi, (neg_32 + neg_smi) >> 0);
+ assertEquals(neg_smi + 0x100000000, (neg_32 + neg_smi) >>> 0);
+ assertEquals(neg_smi, (neg_32 + neg_smi) << 0);
+
+ assertEquals(pos_non_smi / 2, (two_32 + pos_non_smi) >> 1);
+ assertEquals(pos_non_smi / 2, (two_32 + pos_non_smi) >>> 1);
+ assertEquals(-0x1194D800, (two_32 + pos_non_smi) << 1);
+ assertEquals(pos_non_smi / 8, (two_32 + pos_non_smi) >> 3);
+ assertEquals(pos_non_smi / 8, (two_32 + pos_non_smi) >>> 3);
+ assertEquals(-0x46536000, (two_32 + pos_non_smi) << 3);
+ assertEquals(0x73594000, (two_32 + pos_non_smi) << 4);
+ assertEquals(pos_non_smi, (two_32 + pos_non_smi + 0.5) >> 0);
+ assertEquals(pos_non_smi, (two_32 + pos_non_smi + 0.5) >>> 0);
+ assertEquals(pos_non_smi, (two_32 + pos_non_smi + 0.5) << 0);
+ assertEquals(pos_non_smi / 2, (two_32 + pos_non_smi + 0.5) >> 1);
+ assertEquals(pos_non_smi / 2, (two_32 + pos_non_smi + 0.5) >>> 1);
+ assertEquals(-0x1194D800, (two_32 + pos_non_smi + 0.5) << 1);
+ assertEquals(pos_non_smi / 8, (two_32 + pos_non_smi + 0.5) >> 3);
+ assertEquals(pos_non_smi / 8, (two_32 + pos_non_smi + 0.5) >>> 3);
+ assertEquals(-0x46536000, (two_32 + pos_non_smi + 0.5) << 3);
+ assertEquals(0x73594000, (two_32 + pos_non_smi + 0.5) << 4);
+
+ assertEquals(neg_non_smi / 2, (neg_32 + neg_non_smi) >> 1);
+ assertEquals(neg_non_smi / 2 + 0x100000000 / 2, (neg_32 + neg_non_smi) >>> 1);
+ assertEquals(0x1194D800, (neg_32 + neg_non_smi) << 1);
+ assertEquals(neg_non_smi / 8, (neg_32 + neg_non_smi) >> 3);
+ assertEquals(neg_non_smi / 8 + 0x100000000 / 8, (neg_32 + neg_non_smi) >>> 3);
+ assertEquals(0x46536000, (neg_32 + neg_non_smi) << 3);
+ assertEquals(-0x73594000, (neg_32 + neg_non_smi) << 4);
+ assertEquals(neg_non_smi, (neg_32 + neg_non_smi - 0.5) >> 0);
+ assertEquals(neg_non_smi + 0x100000000, (neg_32 + neg_non_smi - 0.5) >>> 0);
+ assertEquals(neg_non_smi, (neg_32 + neg_non_smi - 0.5) << 0);
+ assertEquals(neg_non_smi / 2, (neg_32 + neg_non_smi - 0.5) >> 1);
+ assertEquals(neg_non_smi / 2 + 0x100000000 / 2, (neg_32 + neg_non_smi - 0.5)
+ >>> 1);
+ assertEquals(0x1194D800, (neg_32 + neg_non_smi - 0.5) << 1);
+ assertEquals(neg_non_smi / 8, (neg_32 + neg_non_smi - 0.5) >> 3);
+ assertEquals(neg_non_smi / 8 + 0x100000000 / 8, (neg_32 + neg_non_smi - 0.5)
+ >>> 3);
+ assertEquals(0x46536000, (neg_32 + neg_non_smi - 0.5) << 3);
+ assertEquals(-0x73594000, (neg_32 + neg_non_smi - 0.5) << 4);
+
+ assertEquals(pos_smi / 2, (two_32 + pos_smi) >> 1);
+ assertEquals(pos_smi / 2, (two_32 + pos_smi) >>> 1);
+ assertEquals(pos_non_smi, (two_32 + pos_smi) << 1);
+ assertEquals(pos_smi / 8, (two_32 + pos_smi) >> 3);
+ assertEquals(pos_smi / 8, (two_32 + pos_smi) >>> 3);
+ assertEquals(-0x2329b000, (two_32 + pos_smi) << 3);
+ assertEquals(0x73594000, (two_32 + pos_smi) << 5);
+ assertEquals(pos_smi, (two_32 + pos_smi + 0.5) >> 0);
+ assertEquals(pos_smi, (two_32 + pos_smi + 0.5) >>> 0);
+ assertEquals(pos_smi, (two_32 + pos_smi + 0.5) << 0);
+ assertEquals(pos_smi / 2, (two_32 + pos_smi + 0.5) >> 1);
+ assertEquals(pos_smi / 2, (two_32 + pos_smi + 0.5) >>> 1);
+ assertEquals(pos_non_smi, (two_32 + pos_smi + 0.5) << 1);
+ assertEquals(pos_smi / 8, (two_32 + pos_smi + 0.5) >> 3);
+ assertEquals(pos_smi / 8, (two_32 + pos_smi + 0.5) >>> 3);
+ assertEquals(-0x2329b000, (two_32 + pos_smi + 0.5) << 3);
+ assertEquals(0x73594000, (two_32 + pos_smi + 0.5) << 5);
+
+ assertEquals(neg_smi / 2, (neg_32 + neg_smi) >> 1);
+ assertEquals(neg_smi / 2 + 0x100000000 / 2, (neg_32 + neg_smi) >>> 1);
+ assertEquals(neg_non_smi, (neg_32 + neg_smi) << 1);
+ assertEquals(neg_smi / 8, (neg_32 + neg_smi) >> 3);
+ assertEquals((neg_smi + 0x100000000) / 8, (neg_32 + neg_smi) >>> 3);
+ assertEquals(0x46536000, (neg_32 + neg_smi) << 4);
+ assertEquals(-0x73594000, (neg_32 + neg_smi) << 5);
+ assertEquals(neg_smi, (neg_32 + neg_smi - 0.5) >> 0);
+ assertEquals(neg_smi + 0x100000000, (neg_32 + neg_smi - 0.5) >>> 0);
+ assertEquals(neg_smi, (neg_32 + neg_smi - 0.5) << 0);
+ assertEquals(neg_smi / 2, (neg_32 + neg_smi - 0.5) >> 1);
+ assertEquals(neg_smi / 2 + 0x100000000 / 2, (neg_32 + neg_smi - 0.5) >>> 1);
+ assertEquals(neg_non_smi, (neg_32 + neg_smi - 0.5) << 1);
+ assertEquals(neg_smi / 8, (neg_32 + neg_smi - 0.5) >> 3);
+ assertEquals(neg_smi / 8 + 0x100000000 / 8, (neg_32 + neg_smi - 0.5) >>> 3);
+ assertEquals(0x46536000, (neg_32 + neg_smi - 0.5) << 4);
+ assertEquals(-0x73594000, (neg_32 + neg_smi - 0.5) << 5);
+ // End block A repeat 1
+ // Repeat block A with shift amounts in variables intialized with
+ // a constant.
+ var zero = 0;
+ var one = 1;
+ var three = 3;
+ var four = 4;
+ var five = 5;
+ // Begin block A repeat 2
+ assertEquals(pos_non_smi, (pos_non_smi) >> zero);
+ assertEquals(pos_non_smi, (pos_non_smi) >>> zero);
+ assertEquals(pos_non_smi, (pos_non_smi) << zero);
+ assertEquals(neg_non_smi, (neg_non_smi) >> zero);
+ assertEquals(neg_non_smi + 0x100000000, (neg_non_smi) >>> zero);
+ assertEquals(neg_non_smi, (neg_non_smi) << zero);
+ assertEquals(pos_smi, (pos_smi) >> zero);
+ assertEquals(pos_smi, (pos_smi) >>> zero);
+ assertEquals(pos_smi, (pos_smi) << zero);
+ assertEquals(neg_smi, (neg_smi) >> zero);
+ assertEquals(neg_smi + 0x100000000, (neg_smi) >>> zero);
+ assertEquals(neg_smi, (neg_smi) << zero);
+
+ assertEquals(pos_non_smi / 2, (pos_non_smi) >> one);
+ assertEquals(pos_non_smi / 2, (pos_non_smi) >>> one);
+ assertEquals(-0x1194D800, (pos_non_smi) << one);
+ assertEquals(pos_non_smi / 8, (pos_non_smi) >> three);
+ assertEquals(pos_non_smi / 8, (pos_non_smi) >>> three);
+ assertEquals(-0x46536000, (pos_non_smi) << three);
+ assertEquals(0x73594000, (pos_non_smi) << four);
+ assertEquals(pos_non_smi, (pos_non_smi + 0.5) >> zero);
+ assertEquals(pos_non_smi, (pos_non_smi + 0.5) >>> zero);
+ assertEquals(pos_non_smi, (pos_non_smi + 0.5) << zero);
+ assertEquals(pos_non_smi / 2, (pos_non_smi + 0.5) >> one);
+ assertEquals(pos_non_smi / 2, (pos_non_smi + 0.5) >>> one);
+ assertEquals(-0x1194D800, (pos_non_smi + 0.5) << one);
+ assertEquals(pos_non_smi / 8, (pos_non_smi + 0.5) >> three);
+ assertEquals(pos_non_smi / 8, (pos_non_smi + 0.5) >>> three);
+ assertEquals(-0x46536000, (pos_non_smi + 0.5) << three);
+ assertEquals(0x73594000, (pos_non_smi + 0.5) << four);
+
+ assertEquals(neg_non_smi / 2, (neg_non_smi) >> one);
+ assertEquals(neg_non_smi / 2 + 0x100000000 / 2, (neg_non_smi) >>> one);
+ assertEquals(0x1194D800, (neg_non_smi) << one);
+ assertEquals(neg_non_smi / 8, (neg_non_smi) >> three);
+ assertEquals(neg_non_smi / 8 + 0x100000000 / 8, (neg_non_smi) >>> three);
+ assertEquals(0x46536000, (neg_non_smi) << three);
+ assertEquals(-0x73594000, (neg_non_smi) << four);
+ assertEquals(neg_non_smi, (neg_non_smi - 0.5) >> zero);
+ assertEquals(neg_non_smi + 0x100000000, (neg_non_smi - 0.5) >>> zero);
+ assertEquals(neg_non_smi, (neg_non_smi - 0.5) << zero);
+ assertEquals(neg_non_smi / 2, (neg_non_smi - 0.5) >> one);
+ assertEquals(neg_non_smi / 2 + 0x100000000 / 2, (neg_non_smi - 0.5) >>> one);
+ assertEquals(0x1194D800, (neg_non_smi - 0.5) << one);
+ assertEquals(neg_non_smi / 8, (neg_non_smi - 0.5) >> three);
+ assertEquals(neg_non_smi / 8 + 0x100000000 / 8, (neg_non_smi - 0.5)
+ >>> three);
+ assertEquals(0x46536000, (neg_non_smi - 0.5) << three);
+ assertEquals(-0x73594000, (neg_non_smi - 0.5) << four);
+
+ assertEquals(pos_smi / 2, (pos_smi) >> one);
+ assertEquals(pos_smi / 2, (pos_smi) >>> one);
+ assertEquals(pos_non_smi, (pos_smi) << one);
+ assertEquals(pos_smi / 8, (pos_smi) >> three);
+ assertEquals(pos_smi / 8, (pos_smi) >>> three);
+ assertEquals(-0x2329b000, (pos_smi) << three);
+ assertEquals(0x73594000, (pos_smi) << five);
+ assertEquals(pos_smi, (pos_smi + 0.5) >> zero);
+ assertEquals(pos_smi, (pos_smi + 0.5) >>> zero);
+ assertEquals(pos_smi, (pos_smi + 0.5) << zero);
+ assertEquals(pos_smi / 2, (pos_smi + 0.5) >> one);
+ assertEquals(pos_smi / 2, (pos_smi + 0.5) >>> one);
+ assertEquals(pos_non_smi, (pos_smi + 0.5) << one);
+ assertEquals(pos_smi / 8, (pos_smi + 0.5) >> three);
+ assertEquals(pos_smi / 8, (pos_smi + 0.5) >>> three);
+ assertEquals(-0x2329b000, (pos_smi + 0.5) << three);
+ assertEquals(0x73594000, (pos_smi + 0.5) << five);
+
+ assertEquals(neg_smi / 2, (neg_smi) >> one);
+ assertEquals(neg_smi / 2 + 0x100000000 / 2, (neg_smi) >>> one);
+ assertEquals(neg_non_smi, (neg_smi) << one);
+ assertEquals(neg_smi / 8, (neg_smi) >> three);
+ assertEquals(neg_smi / 8 + 0x100000000 / 8, (neg_smi) >>> three);
+ assertEquals(0x46536000, (neg_smi) << four);
+ assertEquals(-0x73594000, (neg_smi) << five);
+ assertEquals(neg_smi, (neg_smi - 0.5) >> zero);
+ assertEquals(neg_smi + 0x100000000, (neg_smi - 0.5) >>> zero);
+ assertEquals(neg_smi, (neg_smi - 0.5) << zero);
+ assertEquals(neg_smi / 2, (neg_smi - 0.5) >> one);
+ assertEquals(neg_smi / 2 + 0x100000000 / 2, (neg_smi - 0.5) >>> one);
+ assertEquals(neg_non_smi, (neg_smi - 0.5) << one);
+ assertEquals(neg_smi / 8, (neg_smi - 0.5) >> three);
+ assertEquals(neg_smi / 8 + 0x100000000 / 8, (neg_smi - 0.5) >>> three);
+ assertEquals(0x46536000, (neg_smi - 0.5) << four);
+ assertEquals(-0x73594000, (neg_smi - 0.5) << five);
+ // End block A repeat 2
+
+ // Repeat previous block, with computed values in the shift variables.
+ five = 0;
+ while (five < 5 ) ++five;
+ four = five - one;
+ three = four - one;
+ one = four - three;
+ zero = one - one;
+
+ // Begin block A repeat 3
+ assertEquals(pos_non_smi, (pos_non_smi) >> zero);
+ assertEquals(pos_non_smi, (pos_non_smi) >>> zero);
+ assertEquals(pos_non_smi, (pos_non_smi) << zero);
+ assertEquals(neg_non_smi, (neg_non_smi) >> zero);
+ assertEquals(neg_non_smi + 0x100000000, (neg_non_smi) >>> zero);
+ assertEquals(neg_non_smi, (neg_non_smi) << zero);
+ assertEquals(pos_smi, (pos_smi) >> zero);
+ assertEquals(pos_smi, (pos_smi) >>> zero);
+ assertEquals(pos_smi, (pos_smi) << zero);
+ assertEquals(neg_smi, (neg_smi) >> zero);
+ assertEquals(neg_smi + 0x100000000, (neg_smi) >>> zero);
+ assertEquals(neg_smi, (neg_smi) << zero);
+
+ assertEquals(pos_non_smi / 2, (pos_non_smi) >> one);
+ assertEquals(pos_non_smi / 2, (pos_non_smi) >>> one);
+ assertEquals(-0x1194D800, (pos_non_smi) << one);
+ assertEquals(pos_non_smi / 8, (pos_non_smi) >> three);
+ assertEquals(pos_non_smi / 8, (pos_non_smi) >>> three);
+ assertEquals(-0x46536000, (pos_non_smi) << three);
+ assertEquals(0x73594000, (pos_non_smi) << four);
+ assertEquals(pos_non_smi, (pos_non_smi + 0.5) >> zero);
+ assertEquals(pos_non_smi, (pos_non_smi + 0.5) >>> zero);
+ assertEquals(pos_non_smi, (pos_non_smi + 0.5) << zero);
+ assertEquals(pos_non_smi / 2, (pos_non_smi + 0.5) >> one);
+ assertEquals(pos_non_smi / 2, (pos_non_smi + 0.5) >>> one);
+ assertEquals(-0x1194D800, (pos_non_smi + 0.5) << one);
+ assertEquals(pos_non_smi / 8, (pos_non_smi + 0.5) >> three);
+ assertEquals(pos_non_smi / 8, (pos_non_smi + 0.5) >>> three);
+ assertEquals(-0x46536000, (pos_non_smi + 0.5) << three);
+ assertEquals(0x73594000, (pos_non_smi + 0.5) << four);
+
+ assertEquals(neg_non_smi / 2, (neg_non_smi) >> one);
+ assertEquals(neg_non_smi / 2 + 0x100000000 / 2, (neg_non_smi) >>> one);
+ assertEquals(0x1194D800, (neg_non_smi) << one);
+ assertEquals(neg_non_smi / 8, (neg_non_smi) >> three);
+ assertEquals(neg_non_smi / 8 + 0x100000000 / 8, (neg_non_smi) >>> three);
+ assertEquals(0x46536000, (neg_non_smi) << three);
+ assertEquals(-0x73594000, (neg_non_smi) << four);
+ assertEquals(neg_non_smi, (neg_non_smi - 0.5) >> zero);
+ assertEquals(neg_non_smi + 0x100000000, (neg_non_smi - 0.5) >>> zero);
+ assertEquals(neg_non_smi, (neg_non_smi - 0.5) << zero);
+ assertEquals(neg_non_smi / 2, (neg_non_smi - 0.5) >> one);
+ assertEquals(neg_non_smi / 2 + 0x100000000 / 2, (neg_non_smi - 0.5) >>> one);
+ assertEquals(0x1194D800, (neg_non_smi - 0.5) << one);
+ assertEquals(neg_non_smi / 8, (neg_non_smi - 0.5) >> three);
+ assertEquals(neg_non_smi / 8 + 0x100000000 / 8, (neg_non_smi - 0.5)
+ >>> three);
+ assertEquals(0x46536000, (neg_non_smi - 0.5) << three);
+ assertEquals(-0x73594000, (neg_non_smi - 0.5) << four);
+
+ assertEquals(pos_smi / 2, (pos_smi) >> one);
+ assertEquals(pos_smi / 2, (pos_smi) >>> one);
+ assertEquals(pos_non_smi, (pos_smi) << one);
+ assertEquals(pos_smi / 8, (pos_smi) >> three);
+ assertEquals(pos_smi / 8, (pos_smi) >>> three);
+ assertEquals(-0x2329b000, (pos_smi) << three);
+ assertEquals(0x73594000, (pos_smi) << five);
+ assertEquals(pos_smi, (pos_smi + 0.5) >> zero);
+ assertEquals(pos_smi, (pos_smi + 0.5) >>> zero);
+ assertEquals(pos_smi, (pos_smi + 0.5) << zero);
+ assertEquals(pos_smi / 2, (pos_smi + 0.5) >> one);
+ assertEquals(pos_smi / 2, (pos_smi + 0.5) >>> one);
+ assertEquals(pos_non_smi, (pos_smi + 0.5) << one);
+ assertEquals(pos_smi / 8, (pos_smi + 0.5) >> three);
+ assertEquals(pos_smi / 8, (pos_smi + 0.5) >>> three);
+ assertEquals(-0x2329b000, (pos_smi + 0.5) << three);
+ assertEquals(0x73594000, (pos_smi + 0.5) << five);
+
+ assertEquals(neg_smi / 2, (neg_smi) >> one);
+ assertEquals(neg_smi / 2 + 0x100000000 / 2, (neg_smi) >>> one);
+ assertEquals(neg_non_smi, (neg_smi) << one);
+ assertEquals(neg_smi / 8, (neg_smi) >> three);
+ assertEquals(neg_smi / 8 + 0x100000000 / 8, (neg_smi) >>> three);
+ assertEquals(0x46536000, (neg_smi) << four);
+ assertEquals(-0x73594000, (neg_smi) << five);
+ assertEquals(neg_smi, (neg_smi - 0.5) >> zero);
+ assertEquals(neg_smi + 0x100000000, (neg_smi - 0.5) >>> zero);
+ assertEquals(neg_smi, (neg_smi - 0.5) << zero);
+ assertEquals(neg_smi / 2, (neg_smi - 0.5) >> one);
+ assertEquals(neg_smi / 2 + 0x100000000 / 2, (neg_smi - 0.5) >>> one);
+ assertEquals(neg_non_smi, (neg_smi - 0.5) << one);
+ assertEquals(neg_smi / 8, (neg_smi - 0.5) >> three);
+ assertEquals(neg_smi / 8 + 0x100000000 / 8, (neg_smi - 0.5) >>> three);
+ assertEquals(0x46536000, (neg_smi - 0.5) << four);
+ assertEquals(-0x73594000, (neg_smi - 0.5) << five);
+ // End block A repeat 3
+
+ // Test non-integer shift value
+ assertEquals(5, 20.5 >> 2.4);
+ assertEquals(5, 20.5 >> 2.7);
+ var shift = 2.4;
+ assertEquals(5, 20.5 >> shift);
+ assertEquals(5, 20.5 >> shift + 0.3);
+ shift = shift + zero;
+ assertEquals(5, 20.5 >> shift);
+ assertEquals(5, 20.5 >> shift + 0.3);
+}
+
+testShiftNonSmis();
diff --git a/deps/v8/test/mjsunit/tools/codemap.js b/deps/v8/test/mjsunit/tools/codemap.js
new file mode 100644
index 000000000..55b875883
--- /dev/null
+++ b/deps/v8/test/mjsunit/tools/codemap.js
@@ -0,0 +1,158 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Load Splay tree and CodeMap implementations from <project root>/tools.
+// Files: tools/splaytree.js tools/codemap.js
+
+
+function newCodeEntry(size, name) {
+ return new devtools.profiler.CodeMap.CodeEntry(size, name);
+};
+
+
+function assertEntry(codeMap, expected_name, addr) {
+ var entry = codeMap.findEntry(addr);
+ assertNotNull(entry, 'no entry at ' + addr.toString(16));
+ assertEquals(expected_name, entry.name, 'at ' + addr.toString(16));
+};
+
+
+function assertNoEntry(codeMap, addr) {
+ assertNull(codeMap.findEntry(addr), 'at ' + addr.toString(16));
+};
+
+
+(function testStaticCode() {
+ var codeMap = new devtools.profiler.CodeMap();
+ codeMap.addStaticCode(0x1500, newCodeEntry(0x3000, 'lib1'));
+ codeMap.addStaticCode(0x15500, newCodeEntry(0x5000, 'lib2'));
+ codeMap.addStaticCode(0x155500, newCodeEntry(0x10000, 'lib3'));
+ assertNoEntry(codeMap, 0);
+ assertNoEntry(codeMap, 0x1500 - 1);
+ assertEntry(codeMap, 'lib1', 0x1500);
+ assertEntry(codeMap, 'lib1', 0x1500 + 0x100);
+ assertEntry(codeMap, 'lib1', 0x1500 + 0x1000);
+ assertEntry(codeMap, 'lib1', 0x1500 + 0x3000 - 1);
+ assertNoEntry(codeMap, 0x1500 + 0x3000);
+ assertNoEntry(codeMap, 0x15500 - 1);
+ assertEntry(codeMap, 'lib2', 0x15500);
+ assertEntry(codeMap, 'lib2', 0x15500 + 0x100);
+ assertEntry(codeMap, 'lib2', 0x15500 + 0x1000);
+ assertEntry(codeMap, 'lib2', 0x15500 + 0x5000 - 1);
+ assertNoEntry(codeMap, 0x15500 + 0x5000);
+ assertNoEntry(codeMap, 0x155500 - 1);
+ assertEntry(codeMap, 'lib3', 0x155500);
+ assertEntry(codeMap, 'lib3', 0x155500 + 0x100);
+ assertEntry(codeMap, 'lib3', 0x155500 + 0x1000);
+ assertEntry(codeMap, 'lib3', 0x155500 + 0x10000 - 1);
+ assertNoEntry(codeMap, 0x155500 + 0x10000);
+ assertNoEntry(codeMap, 0xFFFFFFFF);
+})();
+
+
+(function testDynamicCode() {
+ var codeMap = new devtools.profiler.CodeMap();
+ codeMap.addCode(0x1500, newCodeEntry(0x200, 'code1'));
+ codeMap.addCode(0x1700, newCodeEntry(0x100, 'code2'));
+ codeMap.addCode(0x1900, newCodeEntry(0x50, 'code3'));
+ codeMap.addCode(0x1950, newCodeEntry(0x10, 'code4'));
+ assertNoEntry(codeMap, 0);
+ assertNoEntry(codeMap, 0x1500 - 1);
+ assertEntry(codeMap, 'code1', 0x1500);
+ assertEntry(codeMap, 'code1', 0x1500 + 0x100);
+ assertEntry(codeMap, 'code1', 0x1500 + 0x200 - 1);
+ assertEntry(codeMap, 'code2', 0x1700);
+ assertEntry(codeMap, 'code2', 0x1700 + 0x50);
+ assertEntry(codeMap, 'code2', 0x1700 + 0x100 - 1);
+ assertNoEntry(codeMap, 0x1700 + 0x100);
+ assertNoEntry(codeMap, 0x1900 - 1);
+ assertEntry(codeMap, 'code3', 0x1900);
+ assertEntry(codeMap, 'code3', 0x1900 + 0x28);
+ assertEntry(codeMap, 'code4', 0x1950);
+ assertEntry(codeMap, 'code4', 0x1950 + 0x7);
+ assertEntry(codeMap, 'code4', 0x1950 + 0x10 - 1);
+ assertNoEntry(codeMap, 0x1950 + 0x10);
+ assertNoEntry(codeMap, 0xFFFFFFFF);
+})();
+
+
+(function testCodeMovesAndDeletions() {
+ var codeMap = new devtools.profiler.CodeMap();
+ codeMap.addCode(0x1500, newCodeEntry(0x200, 'code1'));
+ codeMap.addCode(0x1700, newCodeEntry(0x100, 'code2'));
+ assertEntry(codeMap, 'code1', 0x1500);
+ assertEntry(codeMap, 'code2', 0x1700);
+ codeMap.moveCode(0x1500, 0x1800);
+ assertNoEntry(codeMap, 0x1500);
+ assertEntry(codeMap, 'code2', 0x1700);
+ assertEntry(codeMap, 'code1', 0x1800);
+ codeMap.deleteCode(0x1700);
+ assertNoEntry(codeMap, 0x1700);
+ assertEntry(codeMap, 'code1', 0x1800);
+})();
+
+
+(function testDynamicNamesDuplicates() {
+ var codeMap = new devtools.profiler.CodeMap();
+ // Code entries with same names but different addresses.
+ codeMap.addCode(0x1500, newCodeEntry(0x200, 'code'));
+ codeMap.addCode(0x1700, newCodeEntry(0x100, 'code'));
+ assertEntry(codeMap, 'code', 0x1500);
+ assertEntry(codeMap, 'code {1}', 0x1700);
+ // Test name stability.
+ assertEntry(codeMap, 'code', 0x1500);
+ assertEntry(codeMap, 'code {1}', 0x1700);
+})();
+
+
+(function testStaticEntriesExport() {
+ var codeMap = new devtools.profiler.CodeMap();
+ codeMap.addStaticCode(0x1500, newCodeEntry(0x3000, 'lib1'));
+ codeMap.addStaticCode(0x15500, newCodeEntry(0x5000, 'lib2'));
+ codeMap.addStaticCode(0x155500, newCodeEntry(0x10000, 'lib3'));
+ var allStatics = codeMap.getAllStaticEntries();
+ allStatics.sort();
+ assertEquals(['lib1: 3000', 'lib2: 5000', 'lib3: 10000'], allStatics);
+})();
+
+
+(function testDynamicEntriesExport() {
+ var codeMap = new devtools.profiler.CodeMap();
+ codeMap.addCode(0x1500, newCodeEntry(0x200, 'code1'));
+ codeMap.addCode(0x1700, newCodeEntry(0x100, 'code2'));
+ codeMap.addCode(0x1900, newCodeEntry(0x50, 'code3'));
+ var allDynamics = codeMap.getAllDynamicEntries();
+ allDynamics.sort();
+ assertEquals(['code1: 200', 'code2: 100', 'code3: 50'], allDynamics);
+ codeMap.deleteCode(0x1700);
+ var allDynamics2 = codeMap.getAllDynamicEntries();
+ allDynamics2.sort();
+ assertEquals(['code1: 200', 'code3: 50'], allDynamics2);
+ codeMap.deleteCode(0x1500);
+ var allDynamics3 = codeMap.getAllDynamicEntries();
+ assertEquals(['code3: 50'], allDynamics3);
+})();
diff --git a/deps/v8/test/mjsunit/tools/consarray.js b/deps/v8/test/mjsunit/tools/consarray.js
new file mode 100644
index 000000000..8b2c59bea
--- /dev/null
+++ b/deps/v8/test/mjsunit/tools/consarray.js
@@ -0,0 +1,60 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Load ConsArray implementation from <project root>/tools.
+// Files: tools/consarray.js
+
+
+var arr1 = new ConsArray();
+assertTrue(arr1.atEnd());
+
+arr1.concat([]);
+assertTrue(arr1.atEnd());
+
+arr1.concat([1]);
+assertFalse(arr1.atEnd());
+assertEquals(1, arr1.next());
+assertTrue(arr1.atEnd());
+
+arr1.concat([2, 3, 4]);
+arr1.concat([5]);
+arr1.concat([]);
+arr1.concat([6, 7]);
+
+assertFalse(arr1.atEnd());
+assertEquals(2, arr1.next());
+assertFalse(arr1.atEnd());
+assertEquals(3, arr1.next());
+assertFalse(arr1.atEnd());
+assertEquals(4, arr1.next());
+assertFalse(arr1.atEnd());
+assertEquals(5, arr1.next());
+assertFalse(arr1.atEnd());
+assertEquals(6, arr1.next());
+assertFalse(arr1.atEnd());
+assertEquals(7, arr1.next());
+assertTrue(arr1.atEnd());
diff --git a/deps/v8/test/mjsunit/tools/csvparser.js b/deps/v8/test/mjsunit/tools/csvparser.js
new file mode 100644
index 000000000..db3a2eba3
--- /dev/null
+++ b/deps/v8/test/mjsunit/tools/csvparser.js
@@ -0,0 +1,79 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Load CSV parser implementation from <project root>/tools.
+// Files: tools/csvparser.js
+
+var parser = new devtools.profiler.CsvParser();
+
+assertEquals(
+ [],
+ parser.parseLine(''));
+
+assertEquals(
+ ['', ''],
+ parser.parseLine(','));
+
+assertEquals(
+ ['1997','Ford','E350'],
+ parser.parseLine('1997,Ford,E350'));
+
+assertEquals(
+ ['1997','Ford','E350'],
+ parser.parseLine('"1997","Ford","E350"'));
+
+assertEquals(
+ ['1997','Ford','E350','Super, luxurious truck'],
+ parser.parseLine('1997,Ford,E350,"Super, luxurious truck"'));
+
+assertEquals(
+ ['1997','Ford','E350','Super "luxurious" truck'],
+ parser.parseLine('1997,Ford,E350,"Super ""luxurious"" truck"'));
+
+assertEquals(
+ ['1997','Ford','E350','Super "luxurious" "truck"'],
+ parser.parseLine('1997,Ford,E350,"Super ""luxurious"" ""truck"""'));
+
+assertEquals(
+ ['1997','Ford','E350','Super "luxurious""truck"'],
+ parser.parseLine('1997,Ford,E350,"Super ""luxurious""""truck"""'));
+
+assertEquals(
+ ['shared-library','/lib/ld-2.3.6.so','0x489a2000','0x489b7000'],
+ parser.parseLine('shared-library,"/lib/ld-2.3.6.so",0x489a2000,0x489b7000'));
+
+assertEquals(
+ ['code-creation','LazyCompile','0xf6fe2d20','1201','APPLY_PREPARE native runtime.js:165'],
+ parser.parseLine('code-creation,LazyCompile,0xf6fe2d20,1201,"APPLY_PREPARE native runtime.js:165"'));
+
+assertEquals(
+ ['code-creation','LazyCompile','0xf6fe4bc0','282',' native v8natives.js:69'],
+ parser.parseLine('code-creation,LazyCompile,0xf6fe4bc0,282," native v8natives.js:69"'));
+
+assertEquals(
+ ['code-creation','RegExp','0xf6c21c00','826','NccyrJroXvg\\/([^,]*)'],
+ parser.parseLine('code-creation,RegExp,0xf6c21c00,826,"NccyrJroXvg\\/([^,]*)"'));
diff --git a/deps/v8/test/mjsunit/tools/profile.js b/deps/v8/test/mjsunit/tools/profile.js
new file mode 100644
index 000000000..49eef3b0a
--- /dev/null
+++ b/deps/v8/test/mjsunit/tools/profile.js
@@ -0,0 +1,348 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Load source code files from <project root>/tools.
+// Files: tools/splaytree.js tools/codemap.js tools/consarray.js tools/profile.js
+
+
+function stackToString(stack) {
+ return stack.join(' -> ');
+};
+
+
+function assertPathExists(root, path, opt_message) {
+ var message = opt_message ? ' (' + opt_message + ')' : '';
+ assertNotNull(root.descendToChild(path, function(node, pos) {
+ assertNotNull(node,
+ stackToString(path.slice(0, pos)) + ' has no child ' +
+ path[pos] + message);
+ }), opt_message);
+};
+
+
+function assertNoPathExists(root, path, opt_message) {
+ var message = opt_message ? ' (' + opt_message + ')' : '';
+ assertNull(root.descendToChild(path), opt_message);
+};
+
+
+function countNodes(profile, traverseFunc) {
+ var count = 0;
+ traverseFunc.call(profile, function () { count++; });
+ return count;
+};
+
+
+function ProfileTestDriver() {
+ this.profile = new devtools.profiler.Profile();
+ this.stack_ = [];
+ this.addFunctions_();
+};
+
+
+// Addresses inside functions.
+ProfileTestDriver.prototype.funcAddrs_ = {
+ 'lib1-f1': 0x11110, 'lib1-f2': 0x11210,
+ 'lib2-f1': 0x21110, 'lib2-f2': 0x21210,
+ 'T: F1': 0x50110, 'T: F2': 0x50210, 'T: F3': 0x50410 };
+
+
+ProfileTestDriver.prototype.addFunctions_ = function() {
+ this.profile.addStaticCode('lib1', 0x11000, 0x12000);
+ this.profile.addStaticCode('lib1-f1', 0x11100, 0x11900);
+ this.profile.addStaticCode('lib1-f2', 0x11200, 0x11500);
+ this.profile.addStaticCode('lib2', 0x21000, 0x22000);
+ this.profile.addStaticCode('lib2-f1', 0x21100, 0x21900);
+ this.profile.addStaticCode('lib2-f2', 0x21200, 0x21500);
+ this.profile.addCode('T', 'F1', 0x50100, 0x100);
+ this.profile.addCode('T', 'F2', 0x50200, 0x100);
+ this.profile.addCode('T', 'F3', 0x50400, 0x100);
+};
+
+
+ProfileTestDriver.prototype.enter = function(funcName) {
+ // Stack looks like this: [pc, caller, ..., main].
+ // Therefore, we are adding entries at the beginning.
+ this.stack_.unshift(this.funcAddrs_[funcName]);
+ this.profile.recordTick(this.stack_);
+};
+
+
+ProfileTestDriver.prototype.stay = function() {
+ this.profile.recordTick(this.stack_);
+};
+
+
+ProfileTestDriver.prototype.leave = function() {
+ this.stack_.shift();
+};
+
+
+ProfileTestDriver.prototype.execute = function() {
+ this.enter('lib1-f1');
+ this.enter('lib1-f2');
+ this.enter('T: F1');
+ this.enter('T: F2');
+ this.leave();
+ this.stay();
+ this.enter('lib2-f1');
+ this.enter('lib2-f1');
+ this.leave();
+ this.stay();
+ this.leave();
+ this.enter('T: F3');
+ this.enter('T: F3');
+ this.enter('T: F3');
+ this.leave();
+ this.enter('T: F2');
+ this.stay();
+ this.leave();
+ this.leave();
+ this.leave();
+ this.leave();
+ this.enter('lib2-f1');
+ this.enter('lib1-f1');
+ this.leave();
+ this.leave();
+ this.stay();
+ this.leave();
+};
+
+
+function Inherits(childCtor, parentCtor) {
+ function tempCtor() {};
+ tempCtor.prototype = parentCtor.prototype;
+ childCtor.superClass_ = parentCtor.prototype;
+ childCtor.prototype = new tempCtor();
+ childCtor.prototype.constructor = childCtor;
+};
+
+
+(function testCallTreeBuilding() {
+ function Driver() {
+ ProfileTestDriver.call(this);
+ this.namesTopDown = [];
+ this.namesBottomUp = [];
+ };
+ Inherits(Driver, ProfileTestDriver);
+
+ Driver.prototype.enter = function(func) {
+ this.namesTopDown.push(func);
+ this.namesBottomUp.unshift(func);
+ assertNoPathExists(this.profile.getTopDownProfile().getRoot(), this.namesTopDown,
+ 'pre enter/topDown');
+ assertNoPathExists(this.profile.getBottomUpProfile().getRoot(), this.namesBottomUp,
+ 'pre enter/bottomUp');
+ Driver.superClass_.enter.call(this, func);
+ assertPathExists(this.profile.getTopDownProfile().getRoot(), this.namesTopDown,
+ 'post enter/topDown');
+ assertPathExists(this.profile.getBottomUpProfile().getRoot(), this.namesBottomUp,
+ 'post enter/bottomUp');
+ };
+
+ Driver.prototype.stay = function() {
+ var preTopDownNodes = countNodes(this.profile, this.profile.traverseTopDownTree);
+ var preBottomUpNodes = countNodes(this.profile, this.profile.traverseBottomUpTree);
+ Driver.superClass_.stay.call(this);
+ var postTopDownNodes = countNodes(this.profile, this.profile.traverseTopDownTree);
+ var postBottomUpNodes = countNodes(this.profile, this.profile.traverseBottomUpTree);
+ // Must be no changes in tree layout.
+ assertEquals(preTopDownNodes, postTopDownNodes, 'stay/topDown');
+ assertEquals(preBottomUpNodes, postBottomUpNodes, 'stay/bottomUp');
+ };
+
+ Driver.prototype.leave = function() {
+ Driver.superClass_.leave.call(this);
+ this.namesTopDown.pop();
+ this.namesBottomUp.shift();
+ };
+
+ var testDriver = new Driver();
+ testDriver.execute();
+})();
+
+
+function assertNodeWeights(root, path, selfTicks, totalTicks) {
+ var node = root.descendToChild(path);
+ var stack = stackToString(path);
+ assertNotNull(node, 'node not found: ' + stack);
+ assertEquals(selfTicks, node.selfWeight, 'self of ' + stack);
+ assertEquals(totalTicks, node.totalWeight, 'total of ' + stack);
+};
+
+
+(function testTopDownRootProfileTicks() {
+ var testDriver = new ProfileTestDriver();
+ testDriver.execute();
+
+ var pathWeights = [
+ [['lib1-f1'], 1, 16],
+ [['lib1-f1', 'lib1-f2'], 2, 15],
+ [['lib1-f1', 'lib1-f2', 'T: F1'], 2, 11],
+ [['lib1-f1', 'lib1-f2', 'T: F1', 'T: F2'], 1, 1],
+ [['lib1-f1', 'lib1-f2', 'T: F1', 'lib2-f1'], 2, 3],
+ [['lib1-f1', 'lib1-f2', 'T: F1', 'lib2-f1', 'lib2-f1'], 1, 1],
+ [['lib1-f1', 'lib1-f2', 'T: F1', 'T: F3'], 1, 5],
+ [['lib1-f1', 'lib1-f2', 'T: F1', 'T: F3', 'T: F3'], 1, 4],
+ [['lib1-f1', 'lib1-f2', 'T: F1', 'T: F3', 'T: F3', 'T: F3'], 1, 1],
+ [['lib1-f1', 'lib1-f2', 'T: F1', 'T: F3', 'T: F3', 'T: F2'], 2, 2],
+ [['lib1-f1', 'lib1-f2', 'lib2-f1'], 1, 2],
+ [['lib1-f1', 'lib1-f2', 'lib2-f1', 'lib1-f1'], 1, 1]
+ ];
+
+ var root = testDriver.profile.getTopDownProfile().getRoot();
+ for (var i = 0; i < pathWeights.length; ++i) {
+ var data = pathWeights[i];
+ assertNodeWeights(root, data[0], data[1], data[2]);
+ }
+})();
+
+
+(function testRootFlatProfileTicks() {
+ function Driver() {
+ ProfileTestDriver.call(this);
+ this.namesTopDown = [''];
+ this.counters = {};
+ this.root = null;
+ };
+ Inherits(Driver, ProfileTestDriver);
+
+ Driver.prototype.increment = function(func, self, total) {
+ if (!(func in this.counters)) {
+ this.counters[func] = { self: 0, total: 0 };
+ }
+ this.counters[func].self += self;
+ this.counters[func].total += total;
+ };
+
+ Driver.prototype.incrementTotals = function() {
+ // Only count each function in the stack once.
+ var met = {};
+ for (var i = 0; i < this.namesTopDown.length; ++i) {
+ var name = this.namesTopDown[i];
+ if (!(name in met)) {
+ this.increment(name, 0, 1);
+ }
+ met[name] = true;
+ }
+ };
+
+ Driver.prototype.enter = function(func) {
+ Driver.superClass_.enter.call(this, func);
+ this.namesTopDown.push(func);
+ this.increment(func, 1, 0);
+ this.incrementTotals();
+ };
+
+ Driver.prototype.stay = function() {
+ Driver.superClass_.stay.call(this);
+ this.increment(this.namesTopDown[this.namesTopDown.length - 1], 1, 0);
+ this.incrementTotals();
+ };
+
+ Driver.prototype.leave = function() {
+ Driver.superClass_.leave.call(this);
+ this.namesTopDown.pop();
+ };
+
+ Driver.prototype.extractRoot = function() {
+ assertTrue('' in this.counters);
+ this.root = this.counters[''];
+ delete this.counters[''];
+ };
+
+ var testDriver = new Driver();
+ testDriver.execute();
+ testDriver.extractRoot();
+
+ var counted = 0;
+ for (var c in testDriver.counters) {
+ counted++;
+ }
+
+ var flatProfileRoot = testDriver.profile.getFlatProfile().getRoot();
+ assertEquals(testDriver.root.self, flatProfileRoot.selfWeight);
+ assertEquals(testDriver.root.total, flatProfileRoot.totalWeight);
+
+ var flatProfile = flatProfileRoot.exportChildren();
+ assertEquals(counted, flatProfile.length, 'counted vs. flatProfile');
+ for (var i = 0; i < flatProfile.length; ++i) {
+ var rec = flatProfile[i];
+ assertTrue(rec.label in testDriver.counters, 'uncounted: ' + rec.label);
+ var reference = testDriver.counters[rec.label];
+ assertEquals(reference.self, rec.selfWeight, 'self of ' + rec.label);
+ assertEquals(reference.total, rec.totalWeight, 'total of ' + rec.label);
+ }
+
+})();
+
+
+(function testFunctionCalleesProfileTicks() {
+ var testDriver = new ProfileTestDriver();
+ testDriver.execute();
+
+ var pathWeights = [
+ [['lib2-f1'], 3, 5],
+ [['lib2-f1', 'lib2-f1'], 1, 1],
+ [['lib2-f1', 'lib1-f1'], 1, 1]
+ ];
+
+ var profile = testDriver.profile.getTopDownProfile('lib2-f1');
+ var root = profile.getRoot();
+ for (var i = 0; i < pathWeights.length; ++i) {
+ var data = pathWeights[i];
+ assertNodeWeights(root, data[0], data[1], data[2]);
+ }
+})();
+
+
+(function testFunctionFlatProfileTicks() {
+ var testDriver = new ProfileTestDriver();
+ testDriver.execute();
+
+ var flatWeights = {
+ 'lib2-f1': [1, 1],
+ 'lib1-f1': [1, 1]
+ };
+
+ var flatProfileRoot =
+ testDriver.profile.getFlatProfile('lib2-f1').findOrAddChild('lib2-f1');
+ assertEquals(3, flatProfileRoot.selfWeight);
+ assertEquals(5, flatProfileRoot.totalWeight);
+
+ var flatProfile = flatProfileRoot.exportChildren();
+ assertEquals(2, flatProfile.length, 'counted vs. flatProfile');
+ for (var i = 0; i < flatProfile.length; ++i) {
+ var rec = flatProfile[i];
+ assertTrue(rec.label in flatWeights, 'uncounted: ' + rec.label);
+ var reference = flatWeights[rec.label];
+ assertEquals(reference[0], rec.selfWeight, 'self of ' + rec.label);
+ assertEquals(reference[1], rec.totalWeight, 'total of ' + rec.label);
+ }
+
+})();
+
diff --git a/deps/v8/test/mjsunit/tools/profile_view.js b/deps/v8/test/mjsunit/tools/profile_view.js
new file mode 100644
index 000000000..3ed1128b6
--- /dev/null
+++ b/deps/v8/test/mjsunit/tools/profile_view.js
@@ -0,0 +1,95 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Load source code files from <project root>/tools.
+// Files: tools/consarray.js tools/profile.js tools/profile_view.js
+
+
+function createNode(name, time, opt_parent) {
+ var node = new devtools.profiler.ProfileView.Node(name, time, time, null);
+ if (opt_parent) {
+ opt_parent.addChild(node);
+ }
+ return node;
+}
+
+
+(function testSorting() {
+ //
+ // Build a tree:
+ // root +--c/5
+ // | |
+ // +--a/2 +--b/3--+--d/4
+ // | | |
+ // +--a/1--+--c/1 +--d/2
+ // | |
+ // +--c/1 +--b/2
+ //
+ // So we can sort it using 2 fields: name and time.
+ var root = createNode('root', 0);
+ createNode('a', 2, root);
+ var a1 = createNode('a', 1, root);
+ createNode('c', 1, root);
+ var b3 = createNode('b', 3, a1);
+ createNode('c', 1, a1);
+ createNode('b', 2, a1);
+ createNode('c', 5, b3);
+ createNode('d', 4, b3);
+ createNode('d', 2, b3);
+
+ var view = new devtools.profiler.ProfileView(root);
+ var flatTree = [];
+
+ function fillFlatTree(node) {
+ flatTree.push(node.internalFuncName);
+ flatTree.push(node.selfTime);
+ }
+
+ view.traverse(fillFlatTree);
+ assertEquals(
+ ['root', 0,
+ 'a', 2, 'a', 1, 'c', 1,
+ 'b', 3, 'c', 1, 'b', 2,
+ 'c', 5, 'd', 4, 'd', 2], flatTree);
+
+ function cmpStrs(s1, s2) {
+ return s1 == s2 ? 0 : (s1 < s2 ? -1 : 1);
+ }
+
+ view.sort(function(n1, n2) {
+ return cmpStrs(n1.internalFuncName, n2.internalFuncName) ||
+ (n1.selfTime - n2.selfTime);
+ });
+
+ flatTree = [];
+ view.traverse(fillFlatTree);
+ assertEquals(
+ ['root', 0,
+ 'a', 1, 'a', 2, 'c', 1,
+ 'b', 2, 'b', 3, 'c', 1,
+ 'c', 5, 'd', 2, 'd', 4], flatTree);
+})();
diff --git a/deps/v8/test/mjsunit/undeletable-functions.js b/deps/v8/test/mjsunit/undeletable-functions.js
new file mode 100644
index 000000000..86a74263e
--- /dev/null
+++ b/deps/v8/test/mjsunit/undeletable-functions.js
@@ -0,0 +1,181 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test that we match JSC in making some functions undeletable.
+// See http://code.google.com/p/chromium/issues/detail?id=1717
+// The functions on these prototypes are not just undeletable. It is
+// possible to override them with new definitions, then get the old
+// version back by deleting the new definition.
+
+var array;
+
+array = [
+ "toString", "toLocaleString", "join", "pop", "push", "concat", "reverse",
+ "shift", "unshift", "slice", "splice", "sort", "filter", "forEach", "some",
+ "every", "map", "indexOf", "lastIndexOf", "reduce", "reduceRight"];
+CheckJSCSemantics(Array.prototype, array, "Array prototype");
+
+array = [
+ "toString", "toDateString", "toTimeString", "toLocaleString",
+ "toLocaleDateString", "toLocaleTimeString", "valueOf", "getTime",
+ "getFullYear", "getUTCFullYear", "getMonth", "getUTCMonth", "getDate",
+ "getUTCDate", "getDay", "getUTCDay", "getHours", "getUTCHours", "getMinutes",
+ "getUTCMinutes", "getSeconds", "getUTCSeconds", "getMilliseconds",
+ "getUTCMilliseconds", "getTimezoneOffset", "setTime", "setMilliseconds",
+ "setUTCMilliseconds", "setSeconds", "setUTCSeconds", "setMinutes",
+ "setUTCMinutes", "setHours", "setUTCHours", "setDate", "setUTCDate",
+ "setMonth", "setUTCMonth", "setFullYear", "setUTCFullYear", "toGMTString",
+ "toUTCString", "getYear", "setYear", "toISOString", "toJSON"];
+CheckJSCSemantics(Date.prototype, array, "Date prototype");
+
+array = [
+ "random", "abs", "acos", "asin", "atan", "ceil", "cos", "exp", "floor", "log",
+ "round", "sin", "sqrt", "tan", "atan2", "pow", "max", "min"];
+CheckJSCSemantics(Math, array, "Math1");
+
+CheckEcmaSemantics(Date, ["UTC", "parse", "now"], "Date");
+
+array = [
+ "E", "LN10", "LN2", "LOG2E", "LOG10E", "PI", "SQRT1_2", "SQRT2"];
+CheckDontDelete(Math, array, "Math2");
+
+array = [
+ "escape", "unescape", "decodeURI", "decodeURIComponent", "encodeURI",
+ "encodeURIComponent", "isNaN", "isFinite", "parseInt", "parseFloat", "eval",
+ "execScript"];
+CheckEcmaSemantics(this, array, "Global");
+CheckReadOnlyAttr(this, "Infinity");
+
+array = ["exec", "test", "toString", "compile"];
+CheckEcmaSemantics(RegExp.prototype, array, "RegExp prototype");
+
+array = [
+ "toString", "toLocaleString", "valueOf", "hasOwnProperty",
+ "isPrototypeOf", "propertyIsEnumerable", "__defineGetter__",
+ "__lookupGetter__", "__defineSetter__", "__lookupSetter__"];
+CheckEcmaSemantics(Object.prototype, array, "Object prototype");
+
+array = [
+ "toString", "valueOf", "toJSON"];
+CheckEcmaSemantics(Boolean.prototype, array, "Boolean prototype");
+
+array = [
+ "toString", "toLocaleString", "valueOf", "toFixed", "toExponential",
+ "toPrecision", "toJSON"];
+CheckEcmaSemantics(Number.prototype, array, "Number prototype");
+
+CheckEcmaSemantics(Function.prototype, ["toString"], "Function prototype");
+CheckEcmaSemantics(Date.prototype, ["constructor"], "Date prototype constructor");
+
+array = [
+ "charAt", "charCodeAt", "concat", "indexOf",
+ "lastIndexOf", "localeCompare", "match", "replace", "search", "slice",
+ "split", "substring", "substr", "toLowerCase", "toLocaleLowerCase",
+ "toUpperCase", "toLocaleUpperCase", "link", "anchor", "fontcolor", "fontsize",
+ "big", "blink", "bold", "fixed", "italics", "small", "strike", "sub", "sup",
+ "toJSON", "toString", "valueOf"];
+CheckJSCSemantics(String.prototype, array, "String prototype");
+CheckEcmaSemantics(String, ["fromCharCode"], "String");
+
+
+function CheckEcmaSemantics(type, props, name) {
+ print(name);
+ for (var i = 0; i < props.length; i++) {
+ CheckDeletable(type, props[i]);
+ }
+}
+
+
+function CheckJSCSemantics(type, props, name) {
+ print(name);
+ for (var i = 0; i < props.length; i++) {
+ CheckNotDeletable(type, props[i]);
+ }
+}
+
+
+function CheckDontDelete(type, props, name) {
+ print(name);
+ for (var i = 0; i < props.length; i++) {
+ CheckDontDeleteAttr(type, props[i]);
+ }
+}
+
+
+function CheckDeletable(type, prop) {
+ var old = type[prop];
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
+ if (!type[prop]) return;
+ assertTrue(type.hasOwnProperty(prop), "inherited: " + prop);
+ var deleted = delete type[prop];
+ assertTrue(deleted, "delete operator returned false: " + prop);
+ assertFalse(hasOwnProperty.call(type, prop), "still there after delete: " + prop);
+ type[prop] = "foo";
+ assertEquals("foo", type[prop], "not overwritable: " + prop);
+ type[prop] = old;
+}
+
+
+function CheckNotDeletable(type, prop) {
+ var old = type[prop];
+ if (!type[prop]) return;
+ assertTrue(type.hasOwnProperty(prop), "inherited: " + prop);
+ var deleted = delete type[prop];
+ assertTrue(deleted, "delete operator returned false: " + prop);
+ assertTrue(type.hasOwnProperty(prop), "not there after delete: " + prop);
+ type[prop] = "foo";
+ assertEquals("foo", type[prop], "not overwritable: " + prop);
+ deleted = delete type[prop];
+ assertTrue(deleted, "delete operator returned false 2nd time: " + prop);
+ assertEquals(old.toString(), type[prop].toString(), "delete didn't restore the old value: " + prop);
+}
+
+
+function CheckDontDeleteAttr(type, prop) {
+ var old = type[prop];
+ if (!type[prop]) return;
+ assertTrue(type.hasOwnProperty(prop), "inherited: " + prop);
+ var deleted = delete type[prop];
+ assertFalse(deleted, "delete operator returned true: " + prop);
+ assertTrue(type.hasOwnProperty(prop), "not there after delete: " + prop);
+ type[prop] = "foo";
+ assertFalse("foo" == type[prop], "overwritable: " + prop);
+}
+
+
+function CheckReadOnlyAttr(type, prop) {
+ var old = type[prop];
+ if (!type[prop]) return;
+ assertTrue(type.hasOwnProperty(prop), "inherited: " + prop);
+ var deleted = delete type[prop];
+ assertFalse(deleted, "delete operator returned true: " + prop);
+ assertTrue(type.hasOwnProperty(prop), "not there after delete: " + prop);
+ type[prop] = "foo";
+ assertEquals("foo", type[prop], "overwritable: " + prop);
+}
+
+print("OK");
diff --git a/deps/v8/tools/codemap.js b/deps/v8/tools/codemap.js
new file mode 100644
index 000000000..3766db048
--- /dev/null
+++ b/deps/v8/tools/codemap.js
@@ -0,0 +1,230 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+// Initlialize namespaces
+var devtools = devtools || {};
+devtools.profiler = devtools.profiler || {};
+
+
+/**
+ * Constructs a mapper that maps addresses into code entries.
+ *
+ * @constructor
+ */
+devtools.profiler.CodeMap = function() {
+ /**
+ * Dynamic code entries. Used for JIT compiled code.
+ */
+ this.dynamics_ = new goog.structs.SplayTree();
+
+ /**
+ * Name generator for entries having duplicate names.
+ */
+ this.dynamicsNameGen_ = new devtools.profiler.CodeMap.NameGenerator();
+
+ /**
+ * Static code entries. Used for libraries code.
+ */
+ this.statics_ = new goog.structs.SplayTree();
+
+ /**
+ * Map of memory pages occupied with static code.
+ */
+ this.pages_ = [];
+};
+
+
+/**
+ * The number of alignment bits in a page address.
+ */
+devtools.profiler.CodeMap.PAGE_ALIGNMENT = 12;
+
+
+/**
+ * Page size in bytes.
+ */
+devtools.profiler.CodeMap.PAGE_SIZE =
+ 1 << devtools.profiler.CodeMap.PAGE_ALIGNMENT;
+
+
+/**
+ * Adds a dynamic (i.e. moveable and discardable) code entry.
+ *
+ * @param {number} start The starting address.
+ * @param {devtools.profiler.CodeMap.CodeEntry} codeEntry Code entry object.
+ */
+devtools.profiler.CodeMap.prototype.addCode = function(start, codeEntry) {
+ this.dynamics_.insert(start, codeEntry);
+};
+
+
+/**
+ * Moves a dynamic code entry. Throws an exception if there is no dynamic
+ * code entry with the specified starting address.
+ *
+ * @param {number} from The starting address of the entry being moved.
+ * @param {number} to The destination address.
+ */
+devtools.profiler.CodeMap.prototype.moveCode = function(from, to) {
+ var removedNode = this.dynamics_.remove(from);
+ this.dynamics_.insert(to, removedNode.value);
+};
+
+
+/**
+ * Discards a dynamic code entry. Throws an exception if there is no dynamic
+ * code entry with the specified starting address.
+ *
+ * @param {number} start The starting address of the entry being deleted.
+ */
+devtools.profiler.CodeMap.prototype.deleteCode = function(start) {
+ var removedNode = this.dynamics_.remove(start);
+};
+
+
+/**
+ * Adds a static code entry.
+ *
+ * @param {number} start The starting address.
+ * @param {devtools.profiler.CodeMap.CodeEntry} codeEntry Code entry object.
+ */
+devtools.profiler.CodeMap.prototype.addStaticCode = function(
+ start, codeEntry) {
+ this.markPages_(start, start + codeEntry.size);
+ this.statics_.insert(start, codeEntry);
+};
+
+
+/**
+ * @private
+ */
+devtools.profiler.CodeMap.prototype.markPages_ = function(start, end) {
+ for (var addr = start; addr <= end;
+ addr += devtools.profiler.CodeMap.PAGE_SIZE) {
+ this.pages_[addr >> devtools.profiler.CodeMap.PAGE_ALIGNMENT] = 1;
+ }
+};
+
+
+/**
+ * @private
+ */
+devtools.profiler.CodeMap.prototype.isAddressBelongsTo_ = function(addr, node) {
+ return addr >= node.key && addr < (node.key + node.value.size);
+};
+
+
+/**
+ * @private
+ */
+devtools.profiler.CodeMap.prototype.findInTree_ = function(tree, addr) {
+ var node = tree.findGreatestLessThan(addr);
+ return node && this.isAddressBelongsTo_(addr, node) ? node.value : null;
+};
+
+
+/**
+ * Finds a code entry that contains the specified address. Both static and
+ * dynamic code entries are considered.
+ *
+ * @param {number} addr Address.
+ */
+devtools.profiler.CodeMap.prototype.findEntry = function(addr) {
+ var pageAddr = addr >> devtools.profiler.CodeMap.PAGE_ALIGNMENT;
+ if (pageAddr in this.pages_) {
+ return this.findInTree_(this.statics_, addr);
+ }
+ var min = this.dynamics_.findMin();
+ var max = this.dynamics_.findMax();
+ if (max != null && addr < (max.key + max.value.size) && addr >= min.key) {
+ var dynaEntry = this.findInTree_(this.dynamics_, addr);
+ if (dynaEntry == null) return null;
+ // Dedupe entry name.
+ if (!dynaEntry.nameUpdated_) {
+ dynaEntry.name = this.dynamicsNameGen_.getName(dynaEntry.name);
+ dynaEntry.nameUpdated_ = true;
+ }
+ return dynaEntry;
+ }
+ return null;
+};
+
+
+/**
+ * Returns an array of all dynamic code entries, including deleted ones.
+ */
+devtools.profiler.CodeMap.prototype.getAllDynamicEntries = function() {
+ return this.dynamics_.exportValues();
+};
+
+
+/**
+ * Returns an array of all static code entries.
+ */
+devtools.profiler.CodeMap.prototype.getAllStaticEntries = function() {
+ return this.statics_.exportValues();
+};
+
+
+/**
+ * Creates a code entry object.
+ *
+ * @param {number} size Code entry size in bytes.
+ * @param {string} opt_name Code entry name.
+ * @constructor
+ */
+devtools.profiler.CodeMap.CodeEntry = function(size, opt_name) {
+ this.size = size;
+ this.name = opt_name || '';
+ this.nameUpdated_ = false;
+};
+
+
+devtools.profiler.CodeMap.CodeEntry.prototype.getName = function() {
+ return this.name;
+};
+
+
+devtools.profiler.CodeMap.CodeEntry.prototype.toString = function() {
+ return this.name + ': ' + this.size.toString(16);
+};
+
+
+devtools.profiler.CodeMap.NameGenerator = function() {
+ this.knownNames_ = [];
+};
+
+
+devtools.profiler.CodeMap.NameGenerator.prototype.getName = function(name) {
+ if (!(name in this.knownNames_)) {
+ this.knownNames_[name] = 0;
+ return name;
+ }
+ var count = ++this.knownNames_[name];
+ return name + ' {' + count + '}';
+};
diff --git a/deps/v8/tools/consarray.js b/deps/v8/tools/consarray.js
new file mode 100644
index 000000000..c67abb797
--- /dev/null
+++ b/deps/v8/tools/consarray.js
@@ -0,0 +1,93 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+/**
+ * Constructs a ConsArray object. It is used mainly for tree traversal.
+ * In this use case we have lots of arrays that we need to iterate
+ * sequentally. The internal Array implementation is horribly slow
+ * when concatenating on large (10K items) arrays due to memory copying.
+ * That's why we avoid copying memory and insead build a linked list
+ * of arrays to iterate through.
+ *
+ * @constructor
+ */
+function ConsArray() {
+ this.tail_ = new ConsArray.Cell(null, null);
+ this.currCell_ = this.tail_;
+ this.currCellPos_ = 0;
+};
+
+
+/**
+ * Concatenates another array for iterating. Empty arrays are ignored.
+ * This operation can be safely performed during ongoing ConsArray
+ * iteration.
+ *
+ * @param {Array} arr Array to concatenate.
+ */
+ConsArray.prototype.concat = function(arr) {
+ if (arr.length > 0) {
+ this.tail_.data = arr;
+ this.tail_ = this.tail_.next = new ConsArray.Cell(null, null);
+ }
+};
+
+
+/**
+ * Whether the end of iteration is reached.
+ */
+ConsArray.prototype.atEnd = function() {
+ return this.currCell_ === null ||
+ this.currCell_.data === null ||
+ this.currCellPos_ >= this.currCell_.data.length;
+};
+
+
+/**
+ * Returns the current item, moves to the next one.
+ */
+ConsArray.prototype.next = function() {
+ var result = this.currCell_.data[this.currCellPos_++];
+ if (this.currCellPos_ >= this.currCell_.data.length) {
+ this.currCell_ = this.currCell_.next;
+ this.currCellPos_ = 0;
+ }
+ return result;
+};
+
+
+/**
+ * A cell object used for constructing a list in ConsArray.
+ *
+ * @constructor
+ */
+ConsArray.Cell = function(data, next) {
+ this.data = data;
+ this.next = next;
+};
+
diff --git a/deps/v8/tools/csvparser.js b/deps/v8/tools/csvparser.js
new file mode 100644
index 000000000..9e58deaea
--- /dev/null
+++ b/deps/v8/tools/csvparser.js
@@ -0,0 +1,98 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+// Initlialize namespaces.
+var devtools = devtools || {};
+devtools.profiler = devtools.profiler || {};
+
+
+/**
+ * Creates a CSV lines parser.
+ */
+devtools.profiler.CsvParser = function() {
+};
+
+
+/**
+ * A regex for matching a trailing quote.
+ * @private
+ */
+devtools.profiler.CsvParser.TRAILING_QUOTE_RE_ = /\"$/;
+
+
+/**
+ * A regex for matching a double quote.
+ * @private
+ */
+devtools.profiler.CsvParser.DOUBLE_QUOTE_RE_ = /\"\"/g;
+
+
+/**
+ * Parses a line of CSV-encoded values. Returns an array of fields.
+ *
+ * @param {string} line Input line.
+ */
+devtools.profiler.CsvParser.prototype.parseLine = function(line) {
+ var insideQuotes = false;
+ var fields = [];
+ var prevPos = 0;
+ for (var i = 0, n = line.length; i < n; ++i) {
+ switch (line.charAt(i)) {
+ case ',':
+ if (!insideQuotes) {
+ fields.push(line.substring(prevPos, i));
+ prevPos = i + 1;
+ }
+ break;
+ case '"':
+ if (!insideQuotes) {
+ insideQuotes = true;
+ // Skip the leading quote.
+ prevPos++;
+ } else {
+ if (i + 1 < n && line.charAt(i + 1) != '"') {
+ insideQuotes = false;
+ } else {
+ i++;
+ }
+ }
+ break;
+ }
+ }
+ if (n > 0) {
+ fields.push(line.substring(prevPos));
+ }
+
+ for (i = 0; i < fields.length; ++i) {
+ // Eliminate trailing quotes.
+ fields[i] = fields[i].replace(devtools.profiler.CsvParser.TRAILING_QUOTE_RE_, '');
+ // Convert quoted quotes into single ones.
+ fields[i] = fields[i].replace(devtools.profiler.CsvParser.DOUBLE_QUOTE_RE_, '"');
+ }
+ return fields;
+};
diff --git a/deps/v8/tools/gyp/v8.gyp b/deps/v8/tools/gyp/v8.gyp
new file mode 100644
index 000000000..e980ff167
--- /dev/null
+++ b/deps/v8/tools/gyp/v8.gyp
@@ -0,0 +1,726 @@
+# Copyright 2009 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ 'msvs_use_common_release': 0,
+ 'base_source_files': [
+ '../../src/arm/assembler-arm-inl.h',
+ '../../src/arm/assembler-arm.cc',
+ '../../src/arm/assembler-arm.h',
+ '../../src/arm/builtins-arm.cc',
+ '../../src/arm/codegen-arm.cc',
+ '../../src/arm/codegen-arm.h',
+ '../../src/arm/constants-arm.h',
+ '../../src/arm/cpu-arm.cc',
+ '../../src/arm/debug-arm.cc',
+ '../../src/arm/disasm-arm.cc',
+ '../../src/arm/frames-arm.cc',
+ '../../src/arm/frames-arm.h',
+ '../../src/arm/ic-arm.cc',
+ '../../src/arm/jump-target-arm.cc',
+ '../../src/arm/macro-assembler-arm.cc',
+ '../../src/arm/macro-assembler-arm.h',
+ '../../src/arm/regexp-macro-assembler-arm.cc',
+ '../../src/arm/regexp-macro-assembler-arm.h',
+ '../../src/arm/register-allocator-arm.cc',
+ '../../src/arm/simulator-arm.cc',
+ '../../src/arm/stub-cache-arm.cc',
+ '../../src/arm/virtual-frame-arm.cc',
+ '../../src/arm/virtual-frame-arm.h',
+ '../../src/ia32/assembler-ia32-inl.h',
+ '../../src/ia32/assembler-ia32.cc',
+ '../../src/ia32/assembler-ia32.h',
+ '../../src/ia32/builtins-ia32.cc',
+ '../../src/ia32/codegen-ia32.cc',
+ '../../src/ia32/codegen-ia32.h',
+ '../../src/ia32/cpu-ia32.cc',
+ '../../src/ia32/debug-ia32.cc',
+ '../../src/ia32/disasm-ia32.cc',
+ '../../src/ia32/frames-ia32.cc',
+ '../../src/ia32/frames-ia32.h',
+ '../../src/ia32/ic-ia32.cc',
+ '../../src/ia32/jump-target-ia32.cc',
+ '../../src/ia32/macro-assembler-ia32.cc',
+ '../../src/ia32/macro-assembler-ia32.h',
+ '../../src/ia32/regexp-macro-assembler-ia32.cc',
+ '../../src/ia32/regexp-macro-assembler-ia32.h',
+ '../../src/ia32/register-allocator-ia32.cc',
+ '../../src/ia32/stub-cache-ia32.cc',
+ '../../src/ia32/virtual-frame-ia32.cc',
+ '../../src/ia32/virtual-frame-ia32.h',
+ '../../src/third_party/dtoa/dtoa.c',
+ '../../src/accessors.cc',
+ '../../src/accessors.h',
+ '../../src/allocation.cc',
+ '../../src/allocation.h',
+ '../../src/api.cc',
+ '../../src/api.h',
+ '../../src/apiutils.h',
+ '../../src/arguments.h',
+ '../../src/assembler.cc',
+ '../../src/assembler.h',
+ '../../src/ast.cc',
+ '../../src/ast.h',
+ '../../src/bootstrapper.cc',
+ '../../src/bootstrapper.h',
+ '../../src/builtins.cc',
+ '../../src/builtins.h',
+ '../../src/bytecodes-irregexp.h',
+ '../../src/char-predicates-inl.h',
+ '../../src/char-predicates.h',
+ '../../src/checks.cc',
+ '../../src/checks.h',
+ '../../src/code-stubs.cc',
+ '../../src/code-stubs.h',
+ '../../src/code.h',
+ '../../src/codegen-inl.h',
+ '../../src/codegen.cc',
+ '../../src/codegen.h',
+ '../../src/compilation-cache.cc',
+ '../../src/compilation-cache.h',
+ '../../src/compiler.cc',
+ '../../src/compiler.h',
+ '../../src/contexts.cc',
+ '../../src/contexts.h',
+ '../../src/conversions-inl.h',
+ '../../src/conversions.cc',
+ '../../src/conversions.h',
+ '../../src/counters.cc',
+ '../../src/counters.h',
+ '../../src/cpu.h',
+ '../../src/dateparser.cc',
+ '../../src/dateparser.h',
+ '../../src/dateparser-inl.h',
+ '../../src/debug.cc',
+ '../../src/debug.h',
+ '../../src/debug-agent.cc',
+ '../../src/debug-agent.h',
+ '../../src/disasm.h',
+ '../../src/disassembler.cc',
+ '../../src/disassembler.h',
+ '../../src/dtoa-config.c',
+ '../../src/execution.cc',
+ '../../src/execution.h',
+ '../../src/factory.cc',
+ '../../src/factory.h',
+ '../../src/flag-definitions.h',
+ '../../src/flags.cc',
+ '../../src/flags.h',
+ '../../src/frames-inl.h',
+ '../../src/frames.cc',
+ '../../src/frames.h',
+ '../../src/func-name-inferrer.cc',
+ '../../src/func-name-inferrer.h',
+ '../../src/global-handles.cc',
+ '../../src/global-handles.h',
+ '../../src/globals.h',
+ '../../src/handles-inl.h',
+ '../../src/handles.cc',
+ '../../src/handles.h',
+ '../../src/hashmap.cc',
+ '../../src/hashmap.h',
+ '../../src/heap-inl.h',
+ '../../src/heap.cc',
+ '../../src/heap.h',
+ '../../src/ic-inl.h',
+ '../../src/ic.cc',
+ '../../src/ic.h',
+ '../../src/interpreter-irregexp.cc',
+ '../../src/interpreter-irregexp.h',
+ '../../src/jump-target.cc',
+ '../../src/jump-target.h',
+ '../../src/jsregexp-inl.h',
+ '../../src/jsregexp.cc',
+ '../../src/jsregexp.h',
+ '../../src/list-inl.h',
+ '../../src/list.h',
+ '../../src/log.cc',
+ '../../src/log.h',
+ '../../src/macro-assembler.h',
+ '../../src/mark-compact.cc',
+ '../../src/mark-compact.h',
+ '../../src/memory.h',
+ '../../src/messages.cc',
+ '../../src/messages.h',
+ '../../src/natives.h',
+ '../../src/objects-debug.cc',
+ '../../src/objects-inl.h',
+ '../../src/objects.cc',
+ '../../src/objects.h',
+ '../../src/oprofile-agent.h',
+ '../../src/oprofile-agent.cc',
+ '../../src/parser.cc',
+ '../../src/parser.h',
+ '../../src/platform-freebsd.cc',
+ '../../src/platform-linux.cc',
+ '../../src/platform-macos.cc',
+ '../../src/platform-nullos.cc',
+ '../../src/platform-posix.cc',
+ '../../src/platform-win32.cc',
+ '../../src/platform.h',
+ '../../src/prettyprinter.cc',
+ '../../src/prettyprinter.h',
+ '../../src/property.cc',
+ '../../src/property.h',
+ '../../src/regexp-macro-assembler-irregexp-inl.h',
+ '../../src/regexp-macro-assembler-irregexp.cc',
+ '../../src/regexp-macro-assembler-irregexp.h',
+ '../../src/regexp-macro-assembler-tracer.cc',
+ '../../src/regexp-macro-assembler-tracer.h',
+ '../../src/regexp-macro-assembler.cc',
+ '../../src/regexp-macro-assembler.h',
+ '../../src/regexp-stack.cc',
+ '../../src/regexp-stack.h',
+ '../../src/register-allocator.h',
+ '../../src/register-allocator-inl.h',
+ '../../src/register-allocator.cc',
+ '../../src/rewriter.cc',
+ '../../src/rewriter.h',
+ '../../src/runtime.cc',
+ '../../src/runtime.h',
+ '../../src/scanner.cc',
+ '../../src/scanner.h',
+ '../../src/scopeinfo.cc',
+ '../../src/scopeinfo.h',
+ '../../src/scopes.cc',
+ '../../src/scopes.h',
+ '../../src/serialize.cc',
+ '../../src/serialize.h',
+ '../../src/shell.h',
+ '../../src/smart-pointer.h',
+ '../../src/snapshot-common.cc',
+ '../../src/snapshot.h',
+ '../../src/spaces-inl.h',
+ '../../src/spaces.cc',
+ '../../src/spaces.h',
+ '../../src/string-stream.cc',
+ '../../src/string-stream.h',
+ '../../src/stub-cache.cc',
+ '../../src/stub-cache.h',
+ '../../src/token.cc',
+ '../../src/token.h',
+ '../../src/top.cc',
+ '../../src/top.h',
+ '../../src/unicode-inl.h',
+ '../../src/unicode.cc',
+ '../../src/unicode.h',
+ '../../src/usage-analyzer.cc',
+ '../../src/usage-analyzer.h',
+ '../../src/utils.cc',
+ '../../src/utils.h',
+ '../../src/v8-counters.cc',
+ '../../src/v8-counters.h',
+ '../../src/v8.cc',
+ '../../src/v8.h',
+ '../../src/v8threads.cc',
+ '../../src/v8threads.h',
+ '../../src/variables.cc',
+ '../../src/variables.h',
+ '../../src/version.cc',
+ '../../src/version.h',
+ '../../src/virtual-frame.h',
+ '../../src/virtual-frame.cc',
+ '../../src/zone-inl.h',
+ '../../src/zone.cc',
+ '../../src/zone.h',
+ ],
+ 'not_base_source_files': [
+ # These files are #included by others and are not meant to be compiled
+ # directly.
+ '../../src/third_party/dtoa/dtoa.c',
+ ],
+ 'd8_source_files': [
+ '../../src/d8-debug.cc',
+ '../../src/d8-posix.cc',
+ '../../src/d8-readline.cc',
+ '../../src/d8-windows.cc',
+ '../../src/d8.cc',
+ ],
+ },
+ 'includes': [
+ '../../../build/common.gypi',
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'ENABLE_LOGGING_AND_PROFILING',
+ ],
+ 'configurations': {
+ 'Debug': {
+ 'defines': [
+ 'DEBUG',
+ '_DEBUG',
+ 'ENABLE_DISASSEMBLER',
+ ],
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'Optimizations': '0',
+ 'RuntimeLibrary': '1',
+ },
+ 'VCLinkerTool': {
+ 'LinkIncremental': '2',
+ },
+ },
+ },
+ 'Release': {
+ 'conditions': [
+ ['OS=="linux"', {
+ 'cflags!': [
+ '-O2',
+ ],
+ 'cflags': [
+ '-fomit-frame-pointer',
+ '-O3',
+ ],
+ 'cflags_cc': [
+ '-fno-rtti',
+ ],
+ }],
+ ['OS=="win"', {
+ 'msvs_configuration_attributes': {
+ 'OutputDirectory': '$(SolutionDir)$(ConfigurationName)',
+ 'IntermediateDirectory': '$(OutDir)\\obj\\$(ProjectName)',
+ 'CharacterSet': '1',
+ },
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'RuntimeLibrary': '0',
+ 'Optimizations': '2',
+ 'InlineFunctionExpansion': '2',
+ 'EnableIntrinsicFunctions': 'true',
+ 'FavorSizeOrSpeed': '0',
+ 'OmitFramePointers': 'true',
+ 'StringPooling': 'true',
+ },
+ 'VCLinkerTool': {
+ 'LinkIncremental': '1',
+ 'OptimizeReferences': '2',
+ 'OptimizeForWindows98': '1',
+ 'EnableCOMDATFolding': '2',
+ },
+ },
+ }],
+ ],
+ },
+ },
+ 'xcode_settings': {
+ 'GCC_ENABLE_CPP_EXCEPTIONS': 'NO',
+ 'GCC_ENABLE_CPP_RTTI': 'NO',
+ },
+ },
+ 'targets': [
+ # Targets that apply to any architecture.
+ {
+ 'target_name': 'js2c',
+ 'type': 'none',
+ 'variables': {
+ 'library_files': [
+ '../../src/runtime.js',
+ '../../src/v8natives.js',
+ '../../src/array.js',
+ '../../src/string.js',
+ '../../src/uri.js',
+ '../../src/math.js',
+ '../../src/messages.js',
+ '../../src/apinatives.js',
+ '../../src/debug-delay.js',
+ '../../src/mirror-delay.js',
+ '../../src/date-delay.js',
+ '../../src/json-delay.js',
+ '../../src/regexp-delay.js',
+ '../../src/macros.py',
+ ],
+ },
+ 'actions': [
+ {
+ 'action_name': 'js2c',
+ 'inputs': [
+ '../../tools/js2c.py',
+ '<@(library_files)',
+ ],
+ 'outputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/libraries.cc',
+ '<(SHARED_INTERMEDIATE_DIR)/libraries-empty.cc',
+ ],
+ 'action': ['python', '../../tools/js2c.py', '<@(_outputs)', 'CORE', '<@(library_files)'],
+ },
+ ],
+ },
+ {
+ 'target_name': 'd8_js2c',
+ 'type': 'none',
+ 'variables': {
+ 'library_files': [
+ '../../src/d8.js',
+ '../../src/macros.py',
+ ],
+ },
+ 'actions': [
+ {
+ 'action_name': 'js2c',
+ 'inputs': [
+ '../../tools/js2c.py',
+ '<@(library_files)',
+ ],
+ 'extra_inputs': [
+ ],
+ 'outputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/d8-js.cc',
+ '<(SHARED_INTERMEDIATE_DIR)/d8-js-empty.cc',
+ ],
+ 'action': ['python', '../../tools/js2c.py', '<@(_outputs)', 'D8', '<@(library_files)'],
+ },
+ ],
+ },
+
+ # Targets to build v8 for the native architecture (ia32).
+ {
+ 'target_name': 'v8_base',
+ 'type': '<(library)',
+ 'defines': [
+ 'V8_TARGET_ARCH_IA32'
+ ],
+ 'include_dirs+': [
+ '../../src',
+ '../../src/ia32',
+ ],
+ 'msvs_guid': 'EC8B7909-62AF-470D-A75D-E1D89C837142',
+ 'sources': [
+ '<@(base_source_files)',
+ ],
+ 'sources!': [
+ '<@(not_base_source_files)',
+ ],
+ 'sources/': [
+ ['exclude', '-arm\\.cc$'],
+ ['exclude', 'src/platform-.*\\.cc$' ],
+ ],
+ 'conditions': [
+ ['OS=="linux"',
+ {
+ 'link_settings': {
+ 'libraries': [
+ # Needed for clock_gettime() used by src/platform-linux.cc.
+ '-lrt',
+ ],
+ },
+ 'sources/': [
+ ['include', 'src/platform-linux\\.cc$'],
+ ['include', 'src/platform-posix\\.cc$']
+ ]
+ }
+ ],
+ ['OS=="mac"',
+ {
+ 'sources/': [
+ ['include', 'src/platform-macos\\.cc$'],
+ ['include', 'src/platform-posix\\.cc$']
+ ]
+ }
+ ],
+ ['OS=="win"', {
+ 'sources/': [['include', 'src/platform-win32\\.cc$']],
+ # 4355, 4800 came from common.vsprops
+ # 4018, 4244 were a per file config on dtoa-config.c
+ # TODO: It's probably possible and desirable to stop disabling the
+ # dtoa-specific warnings by modifying dtoa as was done in Chromium
+ # r9255. Refer to that revision for details.
+ 'msvs_disabled_warnings': [4355, 4800, 4018, 4244],
+ 'link_settings': {
+ 'libraries': [ '-lwinmm.lib' ],
+ },
+ }],
+ ],
+ },
+ {
+ 'target_name': 'v8_nosnapshot',
+ 'type': '<(library)',
+ 'defines': [
+ 'V8_TARGET_ARCH_IA32'
+ ],
+ 'dependencies': [
+ 'js2c',
+ 'v8_base',
+ ],
+ 'include_dirs': [
+ '../../src',
+ ],
+ 'sources': [
+ '<(SHARED_INTERMEDIATE_DIR)/libraries.cc',
+ '../../src/snapshot-empty.cc',
+ ],
+ 'export_dependent_settings': [
+ 'v8_base',
+ ],
+ },
+ {
+ 'target_name': 'mksnapshot',
+ 'type': 'executable',
+ 'dependencies': [
+ 'v8_nosnapshot',
+ ],
+ 'msvs_guid': '865575D0-37E2-405E-8CBA-5F6C485B5A26',
+ 'sources': [
+ '../../src/mksnapshot.cc',
+ ],
+ },
+ {
+ 'target_name': 'v8',
+ 'type': '<(library)',
+ 'defines': [
+ 'V8_TARGET_ARCH_IA32'
+ ],
+ 'dependencies': [
+ 'js2c',
+ 'mksnapshot',
+ 'v8_base',
+ ],
+ 'msvs_guid': '21E22961-22BF-4493-BD3A-868F93DA5179',
+ 'actions': [
+ {
+ 'action_name': 'mksnapshot',
+ 'inputs': [
+ '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)mksnapshot<(EXECUTABLE_SUFFIX)',
+ ],
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/snapshot.cc',
+ ],
+ 'action': ['<@(_inputs)', '<@(_outputs)'],
+ },
+ ],
+ 'include_dirs': [
+ '../../src',
+ ],
+ 'sources': [
+ '<(SHARED_INTERMEDIATE_DIR)/libraries-empty.cc',
+ '<(INTERMEDIATE_DIR)/snapshot.cc',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '../../include',
+ ],
+ },
+ 'export_dependent_settings': [
+ 'v8_base',
+ ],
+ },
+ {
+ 'target_name': 'v8_shell',
+ 'type': 'executable',
+ 'defines': [
+ 'V8_TARGET_ARCH_IA32'
+ ],
+ 'dependencies': [
+ 'v8',
+ ],
+ 'sources': [
+ '../../samples/shell.cc',
+ ],
+ 'conditions': [
+ [ 'OS=="win"', {
+ # This could be gotten by not setting chromium_code, if that's OK.
+ 'defines': ['_CRT_SECURE_NO_WARNINGS'],
+ }],
+ ],
+ },
+ ],
+
+ 'conditions': [ ['OS=="mac"', { 'targets': [
+ # TODO(bradnelson): temporarily disable 'd8' target on Windows while
+ # we work fix the performance regressions.
+ # TODO(sgk): temporarily disable 'd8' target on Linux while
+ # we work out getting the readline library on all the systems.
+ {
+ 'target_name': 'd8',
+ 'type': 'executable',
+ 'dependencies': [
+ 'd8_js2c',
+ 'v8',
+ ],
+ 'defines': [
+ 'V8_TARGET_ARCH_IA32'
+ ],
+ 'include_dirs': [
+ '../../src',
+ ],
+ 'sources': [
+ '<(SHARED_INTERMEDIATE_DIR)/d8-js.cc',
+ '<@(d8_source_files)',
+ ],
+ 'conditions': [
+ [ 'OS=="linux"', {
+ 'sources!': [ '../../src/d8-windows.cc' ],
+ 'link_settings': { 'libraries': [ '-lreadline' ] },
+ }],
+ [ 'OS=="mac"', {
+ 'sources!': [ '../../src/d8-windows.cc' ],
+ 'link_settings': { 'libraries': [
+ '$(SDKROOT)/usr/lib/libreadline.dylib'
+ ]},
+ }],
+ [ 'OS=="win"', {
+ 'sources!': [ '../../src/d8-readline.cc', '../../src/d8-posix.cc' ],
+ }],
+ ],
+ },
+ # TODO(sgk): temporarily disable the arm targets on Linux while
+ # we work out how to refactor the generator and/or add configuration
+ # settings to the .gyp file to handle building both variants in
+ # the same output directory.
+ #
+ # ARM targets, to test ARM code generation. These use an ARM simulator
+ # (src/simulator-arm.cc). The ARM targets are not snapshot-enabled.
+ {
+ 'target_name': 'v8_arm',
+ 'type': '<(library)',
+ 'dependencies': [
+ 'js2c',
+ ],
+ 'defines': [
+ 'V8_TARGET_ARCH_ARM',
+ ],
+ 'include_dirs+': [
+ '../../src',
+ '../../src/arm',
+ ],
+ 'sources': [
+ '<@(base_source_files)',
+ '<(SHARED_INTERMEDIATE_DIR)/libraries.cc',
+ '../../src/snapshot-empty.cc',
+ ],
+ 'sources!': [
+ '<@(not_base_source_files)',
+ ],
+ 'sources/': [
+ ['exclude', '-ia32\\.cc$'],
+ ['exclude', 'src/platform-.*\\.cc$' ],
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '../../include',
+ ],
+ },
+ 'conditions': [
+ ['OS=="linux"',
+ {
+ 'sources/': [
+ ['include', 'src/platform-linux\\.cc$'],
+ ['include', 'src/platform-posix\\.cc$']
+ ]
+ }
+ ],
+ ['OS=="mac"',
+ {
+ 'sources/': [
+ ['include', 'src/platform-macos\\.cc$'],
+ ['include', 'src/platform-posix\\.cc$']
+ ]
+ }
+ ],
+ ['OS=="win"', {
+ 'sources/': [['include', 'src/platform-win32\\.cc$']],
+ # 4355, 4800 came from common.vsprops
+ # 4018, 4244 were a per file config on dtoa-config.c
+ # TODO: It's probably possible and desirable to stop disabling the
+ # dtoa-specific warnings by modifying dtoa as was done in Chromium
+ # r9255. Refer to that revision for details.
+ 'msvs_disabled_warnings': [4355, 4800, 4018, 4244],
+ }],
+ ],
+ },
+ {
+ 'target_name': 'v8_shell_arm',
+ 'type': 'executable',
+ 'dependencies': [
+ 'v8_arm',
+ ],
+ 'defines': [
+ 'V8_TARGET_ARCH_ARM',
+ ],
+ 'sources': [
+ '../../samples/shell.cc',
+ ],
+ 'conditions': [
+ [ 'OS=="win"', {
+ # This could be gotten by not setting chromium_code, if that's OK.
+ 'defines': ['_CRT_SECURE_NO_WARNINGS'],
+ }],
+ ],
+ },
+ {
+ 'target_name': 'd8_arm',
+ 'type': 'executable',
+ 'dependencies': [
+ 'd8_js2c',
+ 'v8_arm',
+ ],
+ 'defines': [
+ 'V8_TARGET_ARCH_ARM',
+ ],
+ 'include_dirs': [
+ '../../src',
+ ],
+ 'sources': [
+ '<(SHARED_INTERMEDIATE_DIR)/d8-js.cc',
+ '<@(d8_source_files)',
+ ],
+ 'conditions': [
+ [ 'OS=="linux"', {
+ 'sources!': [ '../../src/d8-windows.cc' ],
+ 'link_settings': { 'libraries': [ '-lreadline' ] },
+ }],
+ [ 'OS=="mac"', {
+ 'sources!': [ '../../src/d8-windows.cc' ],
+ 'link_settings': { 'libraries': [
+ '$(SDKROOT)/usr/lib/libreadline.dylib'
+ ]},
+ }],
+ [ 'OS=="win"', {
+ 'sources!': [ '../../src/d8-readline.cc', '../../src/d8-posix.cc' ],
+ }],
+ ],
+ },
+ ]}], # OS != "linux" (temporary, TODO(sgk))
+
+
+ ['OS=="win"', {
+ 'target_defaults': {
+ 'defines': [
+ '_USE_32BIT_TIME_T',
+ '_CRT_SECURE_NO_DEPRECATE',
+ '_CRT_NONSTDC_NO_DEPRECATE',
+ ],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'AdditionalOptions': '/IGNORE:4221 /NXCOMPAT',
+ },
+ },
+ },
+ }],
+ ],
+}
diff --git a/deps/v8/tools/linux-tick-processor b/deps/v8/tools/linux-tick-processor
new file mode 100644
index 000000000..0ad295f14
--- /dev/null
+++ b/deps/v8/tools/linux-tick-processor
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+tools_dir=$(dirname "$0")
+
+if [ "$1" != "--no-build" ]
+then
+ scons -C $tools_dir/.. d8
+else
+ shift
+fi
+
+# nm spits out 'no symbols found' messages on stderr
+$tools_dir/../d8 $tools_dir/splaytree.js $tools_dir/codemap.js \
+ $tools_dir/csvparser.js $tools_dir/consarray.js \
+ $tools_dir/profile.js $tools_dir/profile_view.js \
+ $tools_dir/tickprocessor.js -- $@ 2>/dev/null
diff --git a/deps/v8/tools/profile.js b/deps/v8/tools/profile.js
new file mode 100644
index 000000000..614c63557
--- /dev/null
+++ b/deps/v8/tools/profile.js
@@ -0,0 +1,605 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+// Initlialize namespaces
+var devtools = devtools || {};
+devtools.profiler = devtools.profiler || {};
+
+
+/**
+ * Creates a profile object for processing profiling-related events
+ * and calculating function execution times.
+ *
+ * @constructor
+ */
+devtools.profiler.Profile = function() {
+ this.codeMap_ = new devtools.profiler.CodeMap();
+ this.topDownTree_ = new devtools.profiler.CallTree();
+ this.bottomUpTree_ = new devtools.profiler.CallTree();
+};
+
+
+/**
+ * Returns whether a function with the specified name must be skipped.
+ * Should be overriden by subclasses.
+ *
+ * @param {string} name Function name.
+ */
+devtools.profiler.Profile.prototype.skipThisFunction = function(name) {
+ return false;
+};
+
+
+/**
+ * Enum for profiler operations that involve looking up existing
+ * code entries.
+ *
+ * @enum {number}
+ */
+devtools.profiler.Profile.Operation = {
+ MOVE: 0,
+ DELETE: 1,
+ TICK: 2
+};
+
+
+/**
+ * Called whenever the specified operation has failed finding a function
+ * containing the specified address. Should be overriden by subclasses.
+ * See the devtools.profiler.Profile.Operation enum for the list of
+ * possible operations.
+ *
+ * @param {number} operation Operation.
+ * @param {number} addr Address of the unknown code.
+ * @param {number} opt_stackPos If an unknown address is encountered
+ * during stack strace processing, specifies a position of the frame
+ * containing the address.
+ */
+devtools.profiler.Profile.prototype.handleUnknownCode = function(
+ operation, addr, opt_stackPos) {
+};
+
+
+/**
+ * Registers static (library) code entry.
+ *
+ * @param {string} name Code entry name.
+ * @param {number} startAddr Starting address.
+ * @param {number} endAddr Ending address.
+ */
+devtools.profiler.Profile.prototype.addStaticCode = function(
+ name, startAddr, endAddr) {
+ var entry = new devtools.profiler.CodeMap.CodeEntry(
+ endAddr - startAddr, name);
+ this.codeMap_.addStaticCode(startAddr, entry);
+ return entry;
+};
+
+
+/**
+ * Registers dynamic (JIT-compiled) code entry.
+ *
+ * @param {string} type Code entry type.
+ * @param {string} name Code entry name.
+ * @param {number} start Starting address.
+ * @param {number} size Code entry size.
+ */
+devtools.profiler.Profile.prototype.addCode = function(
+ type, name, start, size) {
+ var entry = new devtools.profiler.Profile.DynamicCodeEntry(size, type, name);
+ this.codeMap_.addCode(start, entry);
+ return entry;
+};
+
+
+/**
+ * Reports about moving of a dynamic code entry.
+ *
+ * @param {number} from Current code entry address.
+ * @param {number} to New code entry address.
+ */
+devtools.profiler.Profile.prototype.moveCode = function(from, to) {
+ try {
+ this.codeMap_.moveCode(from, to);
+ } catch (e) {
+ this.handleUnknownCode(devtools.profiler.Profile.Operation.MOVE, from);
+ }
+};
+
+
+/**
+ * Reports about deletion of a dynamic code entry.
+ *
+ * @param {number} start Starting address.
+ */
+devtools.profiler.Profile.prototype.deleteCode = function(start) {
+ try {
+ this.codeMap_.deleteCode(start);
+ } catch (e) {
+ this.handleUnknownCode(devtools.profiler.Profile.Operation.DELETE, start);
+ }
+};
+
+
+/**
+ * Records a tick event. Stack must contain a sequence of
+ * addresses starting with the program counter value.
+ *
+ * @param {Array<number>} stack Stack sample.
+ */
+devtools.profiler.Profile.prototype.recordTick = function(stack) {
+ var processedStack = this.resolveAndFilterFuncs_(stack);
+ this.bottomUpTree_.addPath(processedStack);
+ processedStack.reverse();
+ this.topDownTree_.addPath(processedStack);
+};
+
+
+/**
+ * Translates addresses into function names and filters unneeded
+ * functions.
+ *
+ * @param {Array<number>} stack Stack sample.
+ */
+devtools.profiler.Profile.prototype.resolveAndFilterFuncs_ = function(stack) {
+ var result = [];
+ for (var i = 0; i < stack.length; ++i) {
+ var entry = this.codeMap_.findEntry(stack[i]);
+ if (entry) {
+ var name = entry.getName();
+ if (!this.skipThisFunction(name)) {
+ result.push(name);
+ }
+ } else {
+ this.handleUnknownCode(
+ devtools.profiler.Profile.Operation.TICK, stack[i], i);
+ }
+ }
+ return result;
+};
+
+
+/**
+ * Performs a BF traversal of the top down call graph.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} f Visitor function.
+ */
+devtools.profiler.Profile.prototype.traverseTopDownTree = function(f) {
+ this.topDownTree_.traverse(f);
+};
+
+
+/**
+ * Performs a BF traversal of the bottom up call graph.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} f Visitor function.
+ */
+devtools.profiler.Profile.prototype.traverseBottomUpTree = function(f) {
+ this.bottomUpTree_.traverse(f);
+};
+
+
+/**
+ * Calculates a top down profile for a node with the specified label.
+ * If no name specified, returns the whole top down calls tree.
+ *
+ * @param {string} opt_label Node label.
+ */
+devtools.profiler.Profile.prototype.getTopDownProfile = function(opt_label) {
+ return this.getTreeProfile_(this.topDownTree_, opt_label);
+};
+
+
+/**
+ * Calculates a bottom up profile for a node with the specified label.
+ * If no name specified, returns the whole bottom up calls tree.
+ *
+ * @param {string} opt_label Node label.
+ */
+devtools.profiler.Profile.prototype.getBottomUpProfile = function(opt_label) {
+ return this.getTreeProfile_(this.bottomUpTree_, opt_label);
+};
+
+
+/**
+ * Helper function for calculating a tree profile.
+ *
+ * @param {devtools.profiler.Profile.CallTree} tree Call tree.
+ * @param {string} opt_label Node label.
+ */
+devtools.profiler.Profile.prototype.getTreeProfile_ = function(tree, opt_label) {
+ if (!opt_label) {
+ tree.computeTotalWeights();
+ return tree;
+ } else {
+ var subTree = tree.cloneSubtree(opt_label);
+ subTree.computeTotalWeights();
+ return subTree;
+ }
+};
+
+
+/**
+ * Calculates a flat profile of callees starting from a node with
+ * the specified label. If no name specified, starts from the root.
+ *
+ * @param {string} opt_label Starting node label.
+ */
+devtools.profiler.Profile.prototype.getFlatProfile = function(opt_label) {
+ var counters = new devtools.profiler.CallTree();
+ var rootLabel = opt_label || devtools.profiler.CallTree.ROOT_NODE_LABEL;
+ var precs = {};
+ precs[rootLabel] = 0;
+ var root = counters.findOrAddChild(rootLabel);
+
+ this.topDownTree_.computeTotalWeights();
+ this.topDownTree_.traverseInDepth(
+ function onEnter(node) {
+ if (!(node.label in precs)) {
+ precs[node.label] = 0;
+ }
+ var nodeLabelIsRootLabel = node.label == rootLabel;
+ if (nodeLabelIsRootLabel || precs[rootLabel] > 0) {
+ if (precs[rootLabel] == 0) {
+ root.selfWeight += node.selfWeight;
+ root.totalWeight += node.totalWeight;
+ } else {
+ var rec = root.findOrAddChild(node.label);
+ rec.selfWeight += node.selfWeight;
+ if (nodeLabelIsRootLabel || precs[node.label] == 0) {
+ rec.totalWeight += node.totalWeight;
+ }
+ }
+ precs[node.label]++;
+ }
+ },
+ function onExit(node) {
+ if (node.label == rootLabel || precs[rootLabel] > 0) {
+ precs[node.label]--;
+ }
+ },
+ null);
+
+ if (!opt_label) {
+ // If we have created a flat profile for the whole program, we don't
+ // need an explicit root in it. Thus, replace the counters tree
+ // root with the node corresponding to the whole program.
+ counters.root_ = root;
+ } else {
+ // Propagate weights so percents can be calculated correctly.
+ counters.getRoot().selfWeight = root.selfWeight;
+ counters.getRoot().totalWeight = root.totalWeight;
+ }
+ return counters;
+};
+
+
+/**
+ * Creates a dynamic code entry.
+ *
+ * @param {number} size Code size.
+ * @param {string} type Code type.
+ * @param {string} name Function name.
+ * @constructor
+ */
+devtools.profiler.Profile.DynamicCodeEntry = function(size, type, name) {
+ devtools.profiler.CodeMap.CodeEntry.call(this, size, name);
+ this.type = type;
+};
+
+
+/**
+ * Returns node name.
+ */
+devtools.profiler.Profile.DynamicCodeEntry.prototype.getName = function() {
+ var name = this.name;
+ if (name.length == 0) {
+ name = '<anonymous>';
+ } else if (name.charAt(0) == ' ') {
+ // An anonymous function with location: " aaa.js:10".
+ name = '<anonymous>' + name;
+ }
+ return this.type + ': ' + name;
+};
+
+
+/**
+ * Constructs a call graph.
+ *
+ * @constructor
+ */
+devtools.profiler.CallTree = function() {
+ this.root_ = new devtools.profiler.CallTree.Node(
+ devtools.profiler.CallTree.ROOT_NODE_LABEL);
+};
+
+
+/**
+ * The label of the root node.
+ */
+devtools.profiler.CallTree.ROOT_NODE_LABEL = '';
+
+
+/**
+ * @private
+ */
+devtools.profiler.CallTree.prototype.totalsComputed_ = false;
+
+
+/**
+ * Returns the tree root.
+ */
+devtools.profiler.CallTree.prototype.getRoot = function() {
+ return this.root_;
+};
+
+
+/**
+ * Adds the specified call path, constructing nodes as necessary.
+ *
+ * @param {Array<string>} path Call path.
+ */
+devtools.profiler.CallTree.prototype.addPath = function(path) {
+ if (path.length == 0) {
+ return;
+ }
+ var curr = this.root_;
+ for (var i = 0; i < path.length; ++i) {
+ curr = curr.findOrAddChild(path[i]);
+ }
+ curr.selfWeight++;
+ this.totalsComputed_ = false;
+};
+
+
+/**
+ * Finds an immediate child of the specified parent with the specified
+ * label, creates a child node if necessary. If a parent node isn't
+ * specified, uses tree root.
+ *
+ * @param {string} label Child node label.
+ */
+devtools.profiler.CallTree.prototype.findOrAddChild = function(label) {
+ return this.root_.findOrAddChild(label);
+};
+
+
+/**
+ * Creates a subtree by cloning and merging all subtrees rooted at nodes
+ * with a given label. E.g. cloning the following call tree on label 'A'
+ * will give the following result:
+ *
+ * <A>--<B> <B>
+ * / /
+ * <root> == clone on 'A' ==> <root>--<A>
+ * \ \
+ * <C>--<A>--<D> <D>
+ *
+ * And <A>'s selfWeight will be the sum of selfWeights of <A>'s from the
+ * source call tree.
+ *
+ * @param {string} label The label of the new root node.
+ */
+devtools.profiler.CallTree.prototype.cloneSubtree = function(label) {
+ var subTree = new devtools.profiler.CallTree();
+ this.traverse(function(node, parent) {
+ if (!parent && node.label != label) {
+ return null;
+ }
+ var child = (parent ? parent : subTree).findOrAddChild(node.label);
+ child.selfWeight += node.selfWeight;
+ return child;
+ });
+ return subTree;
+};
+
+
+/**
+ * Computes total weights in the call graph.
+ */
+devtools.profiler.CallTree.prototype.computeTotalWeights = function() {
+ if (this.totalsComputed_) {
+ return;
+ }
+ this.root_.computeTotalWeight();
+ this.totalsComputed_ = true;
+};
+
+
+/**
+ * Traverses the call graph in preorder. This function can be used for
+ * building optionally modified tree clones. This is the boilerplate code
+ * for this scenario:
+ *
+ * callTree.traverse(function(node, parentClone) {
+ * var nodeClone = cloneNode(node);
+ * if (parentClone)
+ * parentClone.addChild(nodeClone);
+ * return nodeClone;
+ * });
+ *
+ * @param {function(devtools.profiler.CallTree.Node, *)} f Visitor function.
+ * The second parameter is the result of calling 'f' on the parent node.
+ */
+devtools.profiler.CallTree.prototype.traverse = function(f) {
+ var pairsToProcess = new ConsArray();
+ pairsToProcess.concat([{node: this.root_, param: null}]);
+ while (!pairsToProcess.atEnd()) {
+ var pair = pairsToProcess.next();
+ var node = pair.node;
+ var newParam = f(node, pair.param);
+ var morePairsToProcess = [];
+ node.forEachChild(function (child) {
+ morePairsToProcess.push({node: child, param: newParam}); });
+ pairsToProcess.concat(morePairsToProcess);
+ }
+};
+
+
+/**
+ * Performs an indepth call graph traversal.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} enter A function called
+ * prior to visiting node's children.
+ * @param {function(devtools.profiler.CallTree.Node)} exit A function called
+ * after visiting node's children.
+ */
+devtools.profiler.CallTree.prototype.traverseInDepth = function(enter, exit) {
+ function traverse(node) {
+ enter(node);
+ node.forEachChild(traverse);
+ exit(node);
+ }
+ traverse(this.root_);
+};
+
+
+/**
+ * Constructs a call graph node.
+ *
+ * @param {string} label Node label.
+ * @param {devtools.profiler.CallTree.Node} opt_parent Node parent.
+ */
+devtools.profiler.CallTree.Node = function(label, opt_parent) {
+ this.label = label;
+ this.parent = opt_parent;
+ this.children = {};
+};
+
+
+/**
+ * Node self weight (how many times this node was the last node in
+ * a call path).
+ * @type {number}
+ */
+devtools.profiler.CallTree.Node.prototype.selfWeight = 0;
+
+
+/**
+ * Node total weight (includes weights of all children).
+ * @type {number}
+ */
+devtools.profiler.CallTree.Node.prototype.totalWeight = 0;
+
+
+/**
+ * Adds a child node.
+ *
+ * @param {string} label Child node label.
+ */
+devtools.profiler.CallTree.Node.prototype.addChild = function(label) {
+ var child = new devtools.profiler.CallTree.Node(label, this);
+ this.children[label] = child;
+ return child;
+};
+
+
+/**
+ * Computes node's total weight.
+ */
+devtools.profiler.CallTree.Node.prototype.computeTotalWeight =
+ function() {
+ var totalWeight = this.selfWeight;
+ this.forEachChild(function(child) {
+ totalWeight += child.computeTotalWeight(); });
+ return this.totalWeight = totalWeight;
+};
+
+
+/**
+ * Returns all node's children as an array.
+ */
+devtools.profiler.CallTree.Node.prototype.exportChildren = function() {
+ var result = [];
+ this.forEachChild(function (node) { result.push(node); });
+ return result;
+};
+
+
+/**
+ * Finds an immediate child with the specified label.
+ *
+ * @param {string} label Child node label.
+ */
+devtools.profiler.CallTree.Node.prototype.findChild = function(label) {
+ return this.children[label] || null;
+};
+
+
+/**
+ * Finds an immediate child with the specified label, creates a child
+ * node if necessary.
+ *
+ * @param {string} label Child node label.
+ */
+devtools.profiler.CallTree.Node.prototype.findOrAddChild = function(label) {
+ return this.findChild(label) || this.addChild(label);
+};
+
+
+/**
+ * Calls the specified function for every child.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} f Visitor function.
+ */
+devtools.profiler.CallTree.Node.prototype.forEachChild = function(f) {
+ for (var c in this.children) {
+ f(this.children[c]);
+ }
+};
+
+
+/**
+ * Walks up from the current node up to the call tree root.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} f Visitor function.
+ */
+devtools.profiler.CallTree.Node.prototype.walkUpToRoot = function(f) {
+ for (var curr = this; curr != null; curr = curr.parent) {
+ f(curr);
+ }
+};
+
+
+/**
+ * Tries to find a node with the specified path.
+ *
+ * @param {Array<string>} labels The path.
+ * @param {function(devtools.profiler.CallTree.Node)} opt_f Visitor function.
+ */
+devtools.profiler.CallTree.Node.prototype.descendToChild = function(
+ labels, opt_f) {
+ for (var pos = 0, curr = this; pos < labels.length && curr != null; pos++) {
+ var child = curr.findChild(labels[pos]);
+ if (opt_f) {
+ opt_f(child, pos);
+ }
+ curr = child;
+ }
+ return curr;
+};
diff --git a/deps/v8/tools/profile_view.js b/deps/v8/tools/profile_view.js
new file mode 100644
index 000000000..cd0511f6b
--- /dev/null
+++ b/deps/v8/tools/profile_view.js
@@ -0,0 +1,323 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+// Initlialize namespaces
+var devtools = devtools || {};
+devtools.profiler = devtools.profiler || {};
+
+
+/**
+ * Creates a Profile View builder object.
+ *
+ * @param {number} samplingRate Number of ms between profiler ticks.
+ * @constructor
+ */
+devtools.profiler.ViewBuilder = function(samplingRate) {
+ this.samplingRate = samplingRate;
+};
+
+
+/**
+ * Builds a profile view for the specified call tree.
+ *
+ * @param {devtools.profiler.CallTree} callTree A call tree.
+ */
+devtools.profiler.ViewBuilder.prototype.buildView = function(
+ callTree) {
+ var head;
+ var samplingRate = this.samplingRate;
+ callTree.traverse(function(node, viewParent) {
+ var viewNode = new devtools.profiler.ProfileView.Node(
+ node.label, node.totalWeight * samplingRate,
+ node.selfWeight * samplingRate, head);
+ if (viewParent) {
+ viewParent.addChild(viewNode);
+ } else {
+ head = viewNode;
+ }
+ return viewNode;
+ });
+ var view = new devtools.profiler.ProfileView(head);
+ return view;
+};
+
+
+/**
+ * Creates a Profile View object. It allows to perform sorting
+ * and filtering actions on the profile. Profile View mimicks
+ * the Profile object from WebKit's JSC profiler.
+ *
+ * @param {devtools.profiler.ProfileView.Node} head Head (root) node.
+ * @constructor
+ */
+devtools.profiler.ProfileView = function(head) {
+ this.head = head;
+ this.title = '';
+ this.uid = '';
+ this.heavyProfile = null;
+ this.treeProfile = null;
+ this.flatProfile = null;
+};
+
+
+/**
+ * Updates references between profiles. This is needed for WebKit
+ * ProfileView.
+ */
+devtools.profiler.ProfileView.prototype.updateProfilesRefs = function() {
+ var profileNames = ["treeProfile", "heavyProfile", "flatProfile"];
+ for (var i = 0; i < profileNames.length; ++i) {
+ var destProfile = this[profileNames[i]];
+ for (var j = 0; j < profileNames.length; ++j) {
+ destProfile[profileNames[j]] = this[profileNames[j]];
+ }
+ }
+};
+
+
+/**
+ * Sorts the profile view using the specified sort function.
+ *
+ * @param {function(devtools.profiler.ProfileView.Node,
+ * devtools.profiler.ProfileView.Node):number} sortFunc A sorting
+ * functions. Must comply with Array.sort sorting function requirements.
+ */
+devtools.profiler.ProfileView.prototype.sort = function(sortFunc) {
+ this.traverse(function (node) {
+ node.sortChildren(sortFunc);
+ });
+};
+
+
+/**
+ * Sorts the profile view by self time, ascending.
+ */
+devtools.profiler.ProfileView.prototype.sortSelfTimeAscending = function() {
+ this.sort(function (node1, node2) {
+ return node1.selfTime - node2.selfTime; });
+};
+
+
+/**
+ * Sorts the profile view by self time, descending.
+ */
+devtools.profiler.ProfileView.prototype.sortSelfTimeDescending = function() {
+ this.sort(function (node1, node2) {
+ return node2.selfTime - node1.selfTime; });
+};
+
+
+/**
+ * Sorts the profile view by total time, ascending.
+ */
+devtools.profiler.ProfileView.prototype.sortTotalTimeAscending = function() {
+ this.sort(function (node1, node2) {
+ return node1.totalTime - node2.totalTime; });
+};
+
+
+/**
+ * Sorts the profile view by total time, descending.
+ */
+devtools.profiler.ProfileView.prototype.sortTotalTimeDescending = function() {
+ this.sort(function (node1, node2) {
+ return node2.totalTime - node1.totalTime; });
+};
+
+
+/**
+ * String comparator compatible with Array.sort requirements.
+ *
+ * @param {string} s1 First string.
+ * @param {string} s2 Second string.
+ */
+devtools.profiler.ProfileView.compareStrings = function(s1, s2) {
+ return s1 < s2 ? -1 : (s1 > s2 ? 1 : 0);
+};
+
+
+/**
+ * Sorts the profile view by function name, ascending.
+ */
+devtools.profiler.ProfileView.prototype.sortFunctionNameAscending = function() {
+ this.sort(function (node1, node2) {
+ return devtools.profiler.ProfileView.compareStrings(
+ node1.functionName, node2.functionName); });
+};
+
+
+/**
+ * Sorts the profile view by function name, descending.
+ */
+devtools.profiler.ProfileView.prototype.sortFunctionNameDescending = function() {
+ this.sort(function (node1, node2) {
+ return devtools.profiler.ProfileView.compareStrings(
+ node2.functionName, node1.functionName); });
+};
+
+
+/**
+ * Traverses profile view nodes in preorder.
+ *
+ * @param {function(devtools.profiler.ProfileView.Node)} f Visitor function.
+ */
+devtools.profiler.ProfileView.prototype.traverse = function(f) {
+ var nodesToTraverse = new ConsArray();
+ nodesToTraverse.concat([this.head]);
+ while (!nodesToTraverse.atEnd()) {
+ var node = nodesToTraverse.next();
+ f(node);
+ nodesToTraverse.concat(node.children);
+ }
+};
+
+
+/**
+ * Constructs a Profile View node object. Each node object corresponds to
+ * a function call.
+ *
+ * @param {string} internalFuncName A fully qualified function name.
+ * @param {number} totalTime Amount of time that application spent in the
+ * corresponding function and its descendants (not that depending on
+ * profile they can be either callees or callers.)
+ * @param {number} selfTime Amount of time that application spent in the
+ * corresponding function only.
+ * @param {devtools.profiler.ProfileView.Node} head Profile view head.
+ * @constructor
+ */
+devtools.profiler.ProfileView.Node = function(
+ internalFuncName, totalTime, selfTime, head) {
+ this.callIdentifier = 0;
+ this.internalFuncName = internalFuncName;
+ this.initFuncInfo();
+ this.totalTime = totalTime;
+ this.selfTime = selfTime;
+ this.head = head;
+ this.parent = null;
+ this.children = [];
+ this.visible = true;
+};
+
+
+/**
+ * RegEx for stripping V8's prefixes of compiled functions.
+ */
+devtools.profiler.ProfileView.Node.FUNC_NAME_STRIP_RE =
+ /^(?:LazyCompile|Function): (.*)$/;
+
+
+/**
+ * RegEx for extracting script source URL and line number.
+ */
+devtools.profiler.ProfileView.Node.FUNC_NAME_PARSE_RE = /^([^ ]+) (.*):(\d+)$/;
+
+
+/**
+ * RegEx for removing protocol name from URL.
+ */
+devtools.profiler.ProfileView.Node.URL_PARSE_RE = /^(?:http:\/)?.*\/([^/]+)$/;
+
+
+/**
+ * Inits 'functionName', 'url', and 'lineNumber' fields using 'internalFuncName'
+ * field.
+ */
+devtools.profiler.ProfileView.Node.prototype.initFuncInfo = function() {
+ var nodeAlias = devtools.profiler.ProfileView.Node;
+ this.functionName = this.internalFuncName;
+
+ var strippedName = nodeAlias.FUNC_NAME_STRIP_RE.exec(this.functionName);
+ if (strippedName) {
+ this.functionName = strippedName[1];
+ }
+
+ var parsedName = nodeAlias.FUNC_NAME_PARSE_RE.exec(this.functionName);
+ if (parsedName) {
+ this.url = parsedName[2];
+ var parsedUrl = nodeAlias.URL_PARSE_RE.exec(this.url);
+ if (parsedUrl) {
+ this.url = parsedUrl[1];
+ }
+ this.functionName = parsedName[1];
+ this.lineNumber = parsedName[3];
+ } else {
+ this.url = '';
+ this.lineNumber = 0;
+ }
+};
+
+
+/**
+ * Returns a share of the function's total time in application's total time.
+ */
+devtools.profiler.ProfileView.Node.prototype.__defineGetter__(
+ 'totalPercent',
+ function() { return this.totalTime /
+ (this.head ? this.head.totalTime : this.totalTime) * 100.0; });
+
+
+/**
+ * Returns a share of the function's self time in application's total time.
+ */
+devtools.profiler.ProfileView.Node.prototype.__defineGetter__(
+ 'selfPercent',
+ function() { return this.selfTime /
+ (this.head ? this.head.totalTime : this.totalTime) * 100.0; });
+
+
+/**
+ * Returns a share of the function's total time in its parent's total time.
+ */
+devtools.profiler.ProfileView.Node.prototype.__defineGetter__(
+ 'parentTotalPercent',
+ function() { return this.totalTime /
+ (this.parent ? this.parent.totalTime : this.totalTime) * 100.0; });
+
+
+/**
+ * Adds a child to the node.
+ *
+ * @param {devtools.profiler.ProfileView.Node} node Child node.
+ */
+devtools.profiler.ProfileView.Node.prototype.addChild = function(node) {
+ node.parent = this;
+ this.children.push(node);
+};
+
+
+/**
+ * Sorts all the node's children recursively.
+ *
+ * @param {function(devtools.profiler.ProfileView.Node,
+ * devtools.profiler.ProfileView.Node):number} sortFunc A sorting
+ * functions. Must comply with Array.sort sorting function requirements.
+ */
+devtools.profiler.ProfileView.Node.prototype.sortChildren = function(
+ sortFunc) {
+ this.children.sort(sortFunc);
+};
diff --git a/deps/v8/tools/splaytree.js b/deps/v8/tools/splaytree.js
index 3045456dc..7b3af8b99 100644
--- a/deps/v8/tools/splaytree.js
+++ b/deps/v8/tools/splaytree.js
@@ -28,7 +28,8 @@
// A namespace stub. It will become more clear how to declare it properly
// during integration of this script into Dev Tools.
-goog = { structs: {} };
+var goog = goog || {};
+goog.structs = goog.structs || {};
/**
@@ -94,7 +95,6 @@ goog.structs.SplayTree.prototype.insert = function(key, value) {
};
-
/**
* Removes a node with the specified key from the tree if the tree
* contains a node with this key. The removed node is returned. If the
diff --git a/deps/v8/tools/tickprocessor.js b/deps/v8/tools/tickprocessor.js
new file mode 100644
index 000000000..196daa984
--- /dev/null
+++ b/deps/v8/tools/tickprocessor.js
@@ -0,0 +1,646 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+function Profile(separateIc) {
+ devtools.profiler.Profile.call(this);
+ if (!separateIc) {
+ this.skipThisFunction = function(name) { return Profile.IC_RE.test(name); };
+ }
+};
+Profile.prototype = devtools.profiler.Profile.prototype;
+
+
+Profile.IC_RE =
+ /^(?:CallIC|LoadIC|StoreIC)|(?:Builtin: (?:Keyed)?(?:Call|Load|Store)IC_)/;
+
+
+/**
+ * A thin wrapper around shell's 'read' function showing a file name on error.
+ */
+function readFile(fileName) {
+ try {
+ return read(fileName);
+ } catch (e) {
+ print(fileName + ': ' + (e.message || e));
+ throw e;
+ }
+}
+
+
+function TickProcessor(
+ cppEntriesProvider, separateIc, ignoreUnknown, stateFilter) {
+ this.cppEntriesProvider_ = cppEntriesProvider;
+ this.ignoreUnknown_ = ignoreUnknown;
+ this.stateFilter_ = stateFilter;
+ var ticks = this.ticks_ =
+ { total: 0, unaccounted: 0, excluded: 0, gc: 0 };
+
+ Profile.prototype.handleUnknownCode = function(
+ operation, addr, opt_stackPos) {
+ var op = devtools.profiler.Profile.Operation;
+ switch (operation) {
+ case op.MOVE:
+ print('Code move event for unknown code: 0x' + addr.toString(16));
+ break;
+ case op.DELETE:
+ print('Code delete event for unknown code: 0x' + addr.toString(16));
+ break;
+ case op.TICK:
+ // Only unknown PCs (the first frame) are reported as unaccounted,
+ // otherwise tick balance will be corrupted (this behavior is compatible
+ // with the original tickprocessor.py script.)
+ if (opt_stackPos == 0) {
+ ticks.unaccounted++;
+ }
+ break;
+ }
+ };
+
+ this.profile_ = new Profile(separateIc);
+ this.codeTypes_ = {};
+ // Count each tick as a time unit.
+ this.viewBuilder_ = new devtools.profiler.ViewBuilder(1);
+ this.lastLogFileName_ = null;
+};
+
+
+TickProcessor.VmStates = {
+ JS: 0,
+ GC: 1,
+ COMPILER: 2,
+ OTHER: 3,
+ EXTERNAL: 4
+};
+
+
+TickProcessor.CodeTypes = {
+ CPP: 0,
+ SHARED_LIB: 1
+};
+// Otherwise, this is JS-related code. We are not adding it to
+// codeTypes_ map because there can be zillions of them.
+
+
+TickProcessor.RecordsDispatch = {
+ 'shared-library': { parsers: [null, parseInt, parseInt],
+ processor: 'processSharedLibrary' },
+ 'code-creation': { parsers: [null, parseInt, parseInt, null],
+ processor: 'processCodeCreation' },
+ 'code-move': { parsers: [parseInt, parseInt],
+ processor: 'processCodeMove' },
+ 'code-delete': { parsers: [parseInt], processor: 'processCodeDelete' },
+ 'tick': { parsers: [parseInt, parseInt, parseInt, 'var-args'],
+ processor: 'processTick' },
+ 'profiler': null,
+ // Obsolete row types.
+ 'code-allocate': null,
+ 'begin-code-region': null,
+ 'end-code-region': null
+};
+
+
+TickProcessor.CALL_PROFILE_CUTOFF_PCT = 2.0;
+
+
+TickProcessor.prototype.setCodeType = function(name, type) {
+ this.codeTypes_[name] = TickProcessor.CodeTypes[type];
+};
+
+
+TickProcessor.prototype.isSharedLibrary = function(name) {
+ return this.codeTypes_[name] == TickProcessor.CodeTypes.SHARED_LIB;
+};
+
+
+TickProcessor.prototype.isCppCode = function(name) {
+ return this.codeTypes_[name] == TickProcessor.CodeTypes.CPP;
+};
+
+
+TickProcessor.prototype.isJsCode = function(name) {
+ return !(name in this.codeTypes_);
+};
+
+
+TickProcessor.prototype.processLogFile = function(fileName) {
+ this.lastLogFileName_ = fileName;
+ var contents = readFile(fileName);
+ this.processLog(contents.split('\n'));
+};
+
+
+TickProcessor.prototype.processLog = function(lines) {
+ var csvParser = new devtools.profiler.CsvParser();
+ try {
+ for (var i = 0, n = lines.length; i < n; ++i) {
+ var line = lines[i];
+ if (!line) {
+ continue;
+ }
+ var fields = csvParser.parseLine(line);
+ this.dispatchLogRow(fields);
+ }
+ } catch (e) {
+ print('line ' + (i + 1) + ': ' + (e.message || e));
+ throw e;
+ }
+};
+
+
+TickProcessor.prototype.dispatchLogRow = function(fields) {
+ // Obtain the dispatch.
+ var command = fields[0];
+ if (!(command in TickProcessor.RecordsDispatch)) {
+ throw new Error('unknown command: ' + command);
+ }
+ var dispatch = TickProcessor.RecordsDispatch[command];
+
+ if (dispatch === null) {
+ return;
+ }
+
+ // Parse fields.
+ var parsedFields = [];
+ for (var i = 0; i < dispatch.parsers.length; ++i) {
+ var parser = dispatch.parsers[i];
+ if (parser === null) {
+ parsedFields.push(fields[1 + i]);
+ } else if (typeof parser == 'function') {
+ parsedFields.push(parser(fields[1 + i]));
+ } else {
+ // var-args
+ parsedFields.push(fields.slice(1 + i));
+ break;
+ }
+ }
+
+ // Run the processor.
+ this[dispatch.processor].apply(this, parsedFields);
+};
+
+
+TickProcessor.prototype.processSharedLibrary = function(
+ name, startAddr, endAddr) {
+ var entry = this.profile_.addStaticCode(name, startAddr, endAddr);
+ this.setCodeType(entry.getName(), 'SHARED_LIB');
+
+ var self = this;
+ var libFuncs = this.cppEntriesProvider_.parseVmSymbols(
+ name, startAddr, endAddr, function(fName, fStart, fEnd) {
+ self.profile_.addStaticCode(fName, fStart, fEnd);
+ self.setCodeType(fName, 'CPP');
+ });
+};
+
+
+TickProcessor.prototype.processCodeCreation = function(
+ type, start, size, name) {
+ var entry = this.profile_.addCode(type, name, start, size);
+};
+
+
+TickProcessor.prototype.processCodeMove = function(from, to) {
+ this.profile_.moveCode(from, to);
+};
+
+
+TickProcessor.prototype.processCodeDelete = function(start) {
+ this.profile_.deleteCode(start);
+};
+
+
+TickProcessor.prototype.includeTick = function(vmState) {
+ return this.stateFilter_ == null || this.stateFilter_ == vmState;
+};
+
+
+TickProcessor.prototype.processTick = function(pc, sp, vmState, stack) {
+ this.ticks_.total++;
+ if (vmState == TickProcessor.VmStates.GC) this.ticks_.gc++;
+ if (!this.includeTick(vmState)) {
+ this.ticks_.excluded++;
+ return;
+ }
+
+ var fullStack = [pc];
+ for (var i = 0, n = stack.length; i < n; ++i) {
+ var frame = stack[i];
+ // Leave only numbers starting with 0x. Filter possible 'overflow' string.
+ if (frame.charAt(0) == '0') {
+ fullStack.push(parseInt(frame, 16));
+ }
+ }
+ this.profile_.recordTick(fullStack);
+};
+
+
+TickProcessor.prototype.printStatistics = function() {
+ print('Statistical profiling result from ' + this.lastLogFileName_ +
+ ', (' + this.ticks_.total +
+ ' ticks, ' + this.ticks_.unaccounted + ' unaccounted, ' +
+ this.ticks_.excluded + ' excluded).');
+
+ if (this.ticks_.total == 0) return;
+
+ // Print the unknown ticks percentage if they are not ignored.
+ if (!this.ignoreUnknown_ && this.ticks_.unaccounted > 0) {
+ this.printHeader('Unknown');
+ this.printCounter(this.ticks_.unaccounted, this.ticks_.total);
+ }
+
+ // Disable initialization of 'funcName', 'url', 'lineNumber' as
+ // we don't use it and it just wastes time.
+ devtools.profiler.ProfileView.Node.prototype.initFuncInfo = function() {};
+
+ var flatProfile = this.profile_.getFlatProfile();
+ var flatView = this.viewBuilder_.buildView(flatProfile);
+ // Sort by self time, desc, then by name, desc.
+ flatView.sort(function(rec1, rec2) {
+ return rec2.selfTime - rec1.selfTime ||
+ (rec2.internalFuncName < rec1.internalFuncName ? -1 : 1); });
+ var totalTicks = this.ticks_.total;
+ if (this.ignoreUnknown_) {
+ totalTicks -= this.ticks_.unaccounted;
+ }
+ // Our total time contains all the ticks encountered,
+ // while profile only knows about the filtered ticks.
+ flatView.head.totalTime = totalTicks;
+
+ // Count library ticks
+ var flatViewNodes = flatView.head.children;
+ var self = this;
+ var libraryTicks = 0;
+ this.processProfile(flatViewNodes,
+ function(name) { return self.isSharedLibrary(name); },
+ function(rec) { libraryTicks += rec.selfTime; });
+ var nonLibraryTicks = totalTicks - libraryTicks;
+
+ this.printHeader('Shared libraries');
+ this.printEntries(flatViewNodes, null,
+ function(name) { return self.isSharedLibrary(name); });
+
+ this.printHeader('JavaScript');
+ this.printEntries(flatViewNodes, nonLibraryTicks,
+ function(name) { return self.isJsCode(name); });
+
+ this.printHeader('C++');
+ this.printEntries(flatViewNodes, nonLibraryTicks,
+ function(name) { return self.isCppCode(name); });
+
+ this.printHeader('GC');
+ this.printCounter(this.ticks_.gc, totalTicks);
+
+ this.printHeavyProfHeader();
+ var heavyProfile = this.profile_.getBottomUpProfile();
+ var heavyView = this.viewBuilder_.buildView(heavyProfile);
+ // To show the same percentages as in the flat profile.
+ heavyView.head.totalTime = totalTicks;
+ // Sort by total time, desc, then by name, desc.
+ heavyView.sort(function(rec1, rec2) {
+ return rec2.totalTime - rec1.totalTime ||
+ (rec2.internalFuncName < rec1.internalFuncName ? -1 : 1); });
+ this.printHeavyProfile(heavyView.head.children);
+};
+
+
+function padLeft(s, len) {
+ s = s.toString();
+ if (s.length < len) {
+ s = (new Array(len - s.length + 1).join(' ')) + s;
+ }
+ return s;
+};
+
+
+TickProcessor.prototype.printHeader = function(headerTitle) {
+ print('\n [' + headerTitle + ']:');
+ print(' ticks total nonlib name');
+};
+
+
+TickProcessor.prototype.printHeavyProfHeader = function() {
+ print('\n [Bottom up (heavy) profile]:');
+ print(' Note: percentage shows a share of a particular caller in the ' +
+ 'total\n' +
+ ' amount of its parent calls.');
+ print(' Callers occupying less than ' +
+ TickProcessor.CALL_PROFILE_CUTOFF_PCT.toFixed(1) +
+ '% are not shown.\n');
+ print(' ticks parent name');
+};
+
+
+TickProcessor.prototype.printCounter = function(ticksCount, totalTicksCount) {
+ var pct = ticksCount * 100.0 / totalTicksCount;
+ print(' ' + padLeft(ticksCount, 5) + ' ' + padLeft(pct.toFixed(1), 5) + '%');
+};
+
+
+TickProcessor.prototype.processProfile = function(
+ profile, filterP, func) {
+ for (var i = 0, n = profile.length; i < n; ++i) {
+ var rec = profile[i];
+ if (!filterP(rec.internalFuncName)) {
+ continue;
+ }
+ func(rec);
+ }
+};
+
+
+TickProcessor.prototype.printEntries = function(
+ profile, nonLibTicks, filterP) {
+ this.processProfile(profile, filterP, function (rec) {
+ if (rec.selfTime == 0) return;
+ var nonLibPct = nonLibTicks != null ?
+ rec.selfTime * 100.0 / nonLibTicks : 0.0;
+ print(' ' + padLeft(rec.selfTime, 5) + ' ' +
+ padLeft(rec.selfPercent.toFixed(1), 5) + '% ' +
+ padLeft(nonLibPct.toFixed(1), 5) + '% ' +
+ rec.internalFuncName);
+ });
+};
+
+
+TickProcessor.prototype.printHeavyProfile = function(profile, opt_indent) {
+ var self = this;
+ var indent = opt_indent || 0;
+ var indentStr = padLeft('', indent);
+ this.processProfile(profile, function() { return true; }, function (rec) {
+ // Cut off too infrequent callers.
+ if (rec.parentTotalPercent < TickProcessor.CALL_PROFILE_CUTOFF_PCT) return;
+ print(' ' + padLeft(rec.totalTime, 5) + ' ' +
+ padLeft(rec.parentTotalPercent.toFixed(1), 5) + '% ' +
+ indentStr + rec.internalFuncName);
+ // Limit backtrace depth.
+ if (indent < 10) {
+ self.printHeavyProfile(rec.children, indent + 2);
+ }
+ // Delimit top-level functions.
+ if (indent == 0) {
+ print('');
+ }
+ });
+};
+
+
+function CppEntriesProvider() {
+};
+
+
+CppEntriesProvider.prototype.parseVmSymbols = function(
+ libName, libStart, libEnd, processorFunc) {
+ this.loadSymbols(libName);
+
+ var prevEntry;
+
+ function addPrevEntry(end) {
+ // Several functions can be mapped onto the same address. To avoid
+ // creating zero-sized entries, skip such duplicates.
+ if (prevEntry && prevEntry.start != end) {
+ processorFunc(prevEntry.name, prevEntry.start, end);
+ }
+ }
+
+ while (true) {
+ var funcInfo = this.parseNextLine();
+ if (funcInfo === null) {
+ continue;
+ } else if (funcInfo === false) {
+ break;
+ }
+ if (funcInfo.start < libStart && funcInfo.start < libEnd - libStart) {
+ funcInfo.start += libStart;
+ }
+ addPrevEntry(funcInfo.start);
+ prevEntry = funcInfo;
+ }
+ addPrevEntry(libEnd);
+};
+
+
+CppEntriesProvider.prototype.loadSymbols = function(libName) {
+};
+
+
+CppEntriesProvider.prototype.parseNextLine = function() {
+ return false;
+};
+
+
+function inherits(childCtor, parentCtor) {
+ function tempCtor() {};
+ tempCtor.prototype = parentCtor.prototype;
+ childCtor.prototype = new tempCtor();
+};
+
+
+function UnixCppEntriesProvider() {
+ this.symbols = [];
+ this.parsePos = 0;
+};
+inherits(UnixCppEntriesProvider, CppEntriesProvider);
+
+
+UnixCppEntriesProvider.FUNC_RE = /^([0-9a-fA-F]{8}) . (.*)$/;
+
+
+UnixCppEntriesProvider.prototype.loadSymbols = function(libName) {
+ this.symbols = [
+ os.system('nm', ['-C', '-n', libName], -1, -1),
+ os.system('nm', ['-C', '-n', '-D', libName], -1, -1)
+ ];
+ this.parsePos = 0;
+};
+
+
+UnixCppEntriesProvider.prototype.parseNextLine = function() {
+ if (this.symbols.length == 0) {
+ return false;
+ }
+ var lineEndPos = this.symbols[0].indexOf('\n', this.parsePos);
+ if (lineEndPos == -1) {
+ this.symbols.shift();
+ this.parsePos = 0;
+ return this.parseNextLine();
+ }
+
+ var line = this.symbols[0].substring(this.parsePos, lineEndPos);
+ this.parsePos = lineEndPos + 1;
+ var fields = line.match(UnixCppEntriesProvider.FUNC_RE);
+ return fields ? { name: fields[2], start: parseInt(fields[1], 16) } : null;
+};
+
+
+function WindowsCppEntriesProvider() {
+ this.symbols = '';
+ this.parsePos = 0;
+};
+inherits(WindowsCppEntriesProvider, CppEntriesProvider);
+
+
+WindowsCppEntriesProvider.FILENAME_RE = /^(.*)\.exe$/;
+
+
+WindowsCppEntriesProvider.FUNC_RE =
+ /^ 0001:[0-9a-fA-F]{8}\s+([_\?@$0-9a-zA-Z]+)\s+([0-9a-fA-F]{8}).*$/;
+
+
+WindowsCppEntriesProvider.prototype.loadSymbols = function(libName) {
+ var fileNameFields = libName.match(WindowsCppEntriesProvider.FILENAME_RE);
+ // Only try to load symbols for the .exe file.
+ if (!fileNameFields) return;
+ var mapFileName = fileNameFields[1] + '.map';
+ this.symbols = readFile(mapFileName);
+};
+
+
+WindowsCppEntriesProvider.prototype.parseNextLine = function() {
+ var lineEndPos = this.symbols.indexOf('\r\n', this.parsePos);
+ if (lineEndPos == -1) {
+ return false;
+ }
+
+ var line = this.symbols.substring(this.parsePos, lineEndPos);
+ this.parsePos = lineEndPos + 2;
+ var fields = line.match(WindowsCppEntriesProvider.FUNC_RE);
+ return fields ?
+ { name: this.unmangleName(fields[1]), start: parseInt(fields[2], 16) } :
+ null;
+};
+
+
+/**
+ * Performs very simple unmangling of C++ names.
+ *
+ * Does not handle arguments and template arguments. The mangled names have
+ * the form:
+ *
+ * ?LookupInDescriptor@JSObject@internal@v8@@...arguments info...
+ */
+WindowsCppEntriesProvider.prototype.unmangleName = function(name) {
+ // Empty or non-mangled name.
+ if (name.length < 1 || name.charAt(0) != '?') return name;
+ var nameEndPos = name.indexOf('@@');
+ var components = name.substring(1, nameEndPos).split('@');
+ components.reverse();
+ return components.join('::');
+};
+
+
+function padRight(s, len) {
+ s = s.toString();
+ if (s.length < len) {
+ s = s + (new Array(len - s.length + 1).join(' '));
+ }
+ return s;
+};
+
+
+function processArguments(args) {
+ var result = {
+ logFileName: 'v8.log',
+ platform: 'unix',
+ stateFilter: null,
+ ignoreUnknown: false,
+ separateIc: false
+ };
+ var argsDispatch = {
+ '-j': ['stateFilter', TickProcessor.VmStates.JS,
+ 'Show only ticks from JS VM state'],
+ '-g': ['stateFilter', TickProcessor.VmStates.GC,
+ 'Show only ticks from GC VM state'],
+ '-c': ['stateFilter', TickProcessor.VmStates.COMPILER,
+ 'Show only ticks from COMPILER VM state'],
+ '-o': ['stateFilter', TickProcessor.VmStates.OTHER,
+ 'Show only ticks from OTHER VM state'],
+ '-e': ['stateFilter', TickProcessor.VmStates.EXTERNAL,
+ 'Show only ticks from EXTERNAL VM state'],
+ '--ignore-unknown': ['ignoreUnknown', true,
+ 'Exclude ticks of unknown code entries from processing'],
+ '--separate-ic': ['separateIc', true,
+ 'Separate IC entries'],
+ '--unix': ['platform', 'unix',
+ 'Specify that we are running on *nix platform'],
+ '--windows': ['platform', 'windows',
+ 'Specify that we are running on Windows platform']
+ };
+ argsDispatch['--js'] = argsDispatch['-j'];
+ argsDispatch['--gc'] = argsDispatch['-g'];
+ argsDispatch['--compiler'] = argsDispatch['-c'];
+ argsDispatch['--other'] = argsDispatch['-o'];
+ argsDispatch['--external'] = argsDispatch['-e'];
+
+ function printUsageAndExit() {
+ print('Cmdline args: [options] [log-file-name]\n' +
+ 'Default log file name is "v8.log".\n');
+ print('Options:');
+ for (var arg in argsDispatch) {
+ var synonims = [arg];
+ var dispatch = argsDispatch[arg];
+ for (var synArg in argsDispatch) {
+ if (arg !== synArg && dispatch === argsDispatch[synArg]) {
+ synonims.push(synArg);
+ delete argsDispatch[synArg];
+ }
+ }
+ print(' ' + padRight(synonims.join(', '), 20) + dispatch[2]);
+ }
+ quit(2);
+ }
+
+ while (args.length) {
+ var arg = args[0];
+ if (arg.charAt(0) != '-') {
+ break;
+ }
+ args.shift();
+ if (arg in argsDispatch) {
+ var dispatch = argsDispatch[arg];
+ result[dispatch[0]] = dispatch[1];
+ } else {
+ printUsageAndExit();
+ }
+ }
+
+ if (args.length >= 1) {
+ result.logFileName = args.shift();
+ }
+ return result;
+};
+
+
+var params = processArguments(arguments);
+var tickProcessor = new TickProcessor(
+ params.platform == 'unix' ? new UnixCppEntriesProvider() :
+ new WindowsCppEntriesProvider(),
+ params.separateIc,
+ params.ignoreUnknown,
+ params.stateFilter);
+tickProcessor.processLogFile(params.logFileName);
+tickProcessor.printStatistics();
diff --git a/deps/v8/tools/tickprocessor.py b/deps/v8/tools/tickprocessor.py
index 95e6e50f9..cc540d3db 100644
--- a/deps/v8/tools/tickprocessor.py
+++ b/deps/v8/tools/tickprocessor.py
@@ -411,7 +411,7 @@ class TickProcessor(object):
number_of_accounted_ticks -= self.unaccounted_number_of_ticks
number_of_non_library_ticks = number_of_accounted_ticks - self.number_of_library_ticks
- entries.sort(key=lambda e:e.tick_count, reverse=True)
+ entries.sort(key=lambda e: (e.tick_count, e.ToString()), reverse=True)
for entry in entries:
if entry.tick_count > 0 and condition(entry):
total_percentage = entry.tick_count * 100.0 / number_of_accounted_ticks
diff --git a/deps/v8/tools/v8.xcodeproj/project.pbxproj b/deps/v8/tools/v8.xcodeproj/project.pbxproj
index eba4ec771..83212fb42 100644..100755
--- a/deps/v8/tools/v8.xcodeproj/project.pbxproj
+++ b/deps/v8/tools/v8.xcodeproj/project.pbxproj
@@ -132,6 +132,8 @@
89A88E2C0E71A6D20043BA31 /* v8threads.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF19D0E719B8F00D62E90 /* v8threads.cc */; };
89A88E2D0E71A6D50043BA31 /* variables.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF19F0E719B8F00D62E90 /* variables.cc */; };
89A88E2E0E71A6D60043BA31 /* zone.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1A20E719B8F00D62E90 /* zone.cc */; };
+ 89B933AF0FAA0F9600201304 /* version.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF32F0FAA0ED200136CF6 /* version.cc */; };
+ 89B933B00FAA0F9D00201304 /* version.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF32F0FAA0ED200136CF6 /* version.cc */; };
89F23C3F0E78D5B2006B2466 /* accessors.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF0F60E719B8F00D62E90 /* accessors.cc */; };
89F23C400E78D5B2006B2466 /* allocation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF0F80E719B8F00D62E90 /* allocation.cc */; };
89F23C410E78D5B2006B2466 /* api.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF0FA0E719B8F00D62E90 /* api.cc */; };
@@ -269,18 +271,19 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
- 58950D4E0F55514900F3E8BA /* jump-target-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "jump-target-arm.cc"; sourceTree = "<group>"; };
- 58950D4F0F55514900F3E8BA /* jump-target-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "jump-target-ia32.cc"; sourceTree = "<group>"; };
+ 58242A1E0FA1F14D00BD6F59 /* json-delay.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "json-delay.js"; sourceTree = "<group>"; };
+ 58950D4E0F55514900F3E8BA /* jump-target-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "jump-target-arm.cc"; path = "arm/jump-target-arm.cc"; sourceTree = "<group>"; };
+ 58950D4F0F55514900F3E8BA /* jump-target-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "jump-target-ia32.cc"; path = "ia32/jump-target-ia32.cc"; sourceTree = "<group>"; };
58950D500F55514900F3E8BA /* jump-target.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "jump-target.cc"; sourceTree = "<group>"; };
58950D510F55514900F3E8BA /* jump-target.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "jump-target.h"; sourceTree = "<group>"; };
- 58950D520F55514900F3E8BA /* register-allocator-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "register-allocator-arm.cc"; sourceTree = "<group>"; };
- 58950D530F55514900F3E8BA /* register-allocator-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "register-allocator-ia32.cc"; sourceTree = "<group>"; };
+ 58950D520F55514900F3E8BA /* register-allocator-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "register-allocator-arm.cc"; path = "arm/register-allocator-arm.cc"; sourceTree = "<group>"; };
+ 58950D530F55514900F3E8BA /* register-allocator-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "register-allocator-ia32.cc"; path = "ia32/register-allocator-ia32.cc"; sourceTree = "<group>"; };
58950D540F55514900F3E8BA /* register-allocator.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "register-allocator.cc"; sourceTree = "<group>"; };
58950D550F55514900F3E8BA /* register-allocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "register-allocator.h"; sourceTree = "<group>"; };
- 58950D560F55514900F3E8BA /* virtual-frame-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "virtual-frame-arm.cc"; sourceTree = "<group>"; };
- 58950D570F55514900F3E8BA /* virtual-frame-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "virtual-frame-arm.h"; sourceTree = "<group>"; };
- 58950D580F55514900F3E8BA /* virtual-frame-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "virtual-frame-ia32.cc"; sourceTree = "<group>"; };
- 58950D590F55514900F3E8BA /* virtual-frame-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "virtual-frame-ia32.h"; sourceTree = "<group>"; };
+ 58950D560F55514900F3E8BA /* virtual-frame-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "virtual-frame-arm.cc"; path = "arm/virtual-frame-arm.cc"; sourceTree = "<group>"; };
+ 58950D570F55514900F3E8BA /* virtual-frame-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "virtual-frame-arm.h"; path = "arm/virtual-frame-arm.h"; sourceTree = "<group>"; };
+ 58950D580F55514900F3E8BA /* virtual-frame-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "virtual-frame-ia32.cc"; path = "ia32/virtual-frame-ia32.cc"; sourceTree = "<group>"; };
+ 58950D590F55514900F3E8BA /* virtual-frame-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "virtual-frame-ia32.h"; path = "ia32/virtual-frame-ia32.h"; sourceTree = "<group>"; };
58950D5A0F55514900F3E8BA /* virtual-frame.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "virtual-frame.cc"; sourceTree = "<group>"; };
58950D5B0F55514900F3E8BA /* virtual-frame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "virtual-frame.h"; sourceTree = "<group>"; };
8900116B0E71CA2300F91F35 /* libraries.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = libraries.cc; sourceTree = "<group>"; };
@@ -299,8 +302,8 @@
89495E470E79FC23001F68C3 /* compilation-cache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "compilation-cache.h"; sourceTree = "<group>"; };
8956B6CD0F5D86570033B5A2 /* debug-agent.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "debug-agent.cc"; sourceTree = "<group>"; };
8956B6CE0F5D86570033B5A2 /* debug-agent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "debug-agent.h"; sourceTree = "<group>"; };
- 8964482B0E9C00F700E7C516 /* codegen-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "codegen-ia32.h"; sourceTree = "<group>"; };
- 896448BC0E9D530500E7C516 /* codegen-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "codegen-arm.h"; sourceTree = "<group>"; };
+ 8964482B0E9C00F700E7C516 /* codegen-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "codegen-ia32.h"; path = "ia32/codegen-ia32.h"; sourceTree = "<group>"; };
+ 896448BC0E9D530500E7C516 /* codegen-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "codegen-arm.h"; path = "arm/codegen-arm.h"; sourceTree = "<group>"; };
8970F2F00E719FB2006AE7B5 /* libv8.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libv8.a; sourceTree = BUILT_PRODUCTS_DIR; };
897F767A0E71B4CC007ACF34 /* v8_shell */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = v8_shell; sourceTree = BUILT_PRODUCTS_DIR; };
897FF0D40E719A8500D62E90 /* v8-debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "v8-debug.h"; sourceTree = "<group>"; };
@@ -314,20 +317,20 @@
897FF0FA0E719B8F00D62E90 /* api.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = api.cc; sourceTree = "<group>"; };
897FF0FB0E719B8F00D62E90 /* api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = api.h; sourceTree = "<group>"; };
897FF0FC0E719B8F00D62E90 /* arguments.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = arguments.h; sourceTree = "<group>"; };
- 897FF0FD0E719B8F00D62E90 /* assembler-arm-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "assembler-arm-inl.h"; sourceTree = "<group>"; };
- 897FF0FE0E719B8F00D62E90 /* assembler-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "assembler-arm.cc"; sourceTree = "<group>"; };
- 897FF0FF0E719B8F00D62E90 /* assembler-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "assembler-arm.h"; sourceTree = "<group>"; };
- 897FF1000E719B8F00D62E90 /* assembler-ia32-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "assembler-ia32-inl.h"; sourceTree = "<group>"; };
- 897FF1010E719B8F00D62E90 /* assembler-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "assembler-ia32.cc"; sourceTree = "<group>"; };
- 897FF1020E719B8F00D62E90 /* assembler-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "assembler-ia32.h"; sourceTree = "<group>"; };
+ 897FF0FD0E719B8F00D62E90 /* assembler-arm-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "assembler-arm-inl.h"; path = "arm/assembler-arm-inl.h"; sourceTree = "<group>"; };
+ 897FF0FE0E719B8F00D62E90 /* assembler-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "assembler-arm.cc"; path = "arm/assembler-arm.cc"; sourceTree = "<group>"; };
+ 897FF0FF0E719B8F00D62E90 /* assembler-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "assembler-arm.h"; path = "arm/assembler-arm.h"; sourceTree = "<group>"; };
+ 897FF1000E719B8F00D62E90 /* assembler-ia32-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "assembler-ia32-inl.h"; path = "ia32/assembler-ia32-inl.h"; sourceTree = "<group>"; };
+ 897FF1010E719B8F00D62E90 /* assembler-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "assembler-ia32.cc"; path = "ia32/assembler-ia32.cc"; sourceTree = "<group>"; };
+ 897FF1020E719B8F00D62E90 /* assembler-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "assembler-ia32.h"; path = "ia32/assembler-ia32.h"; sourceTree = "<group>"; };
897FF1030E719B8F00D62E90 /* assembler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = assembler.cc; sourceTree = "<group>"; };
897FF1040E719B8F00D62E90 /* assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assembler.h; sourceTree = "<group>"; };
897FF1050E719B8F00D62E90 /* ast.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ast.cc; sourceTree = "<group>"; };
897FF1060E719B8F00D62E90 /* ast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ast.h; sourceTree = "<group>"; };
897FF1070E719B8F00D62E90 /* bootstrapper.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bootstrapper.cc; sourceTree = "<group>"; };
897FF1080E719B8F00D62E90 /* bootstrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bootstrapper.h; sourceTree = "<group>"; };
- 897FF1090E719B8F00D62E90 /* builtins-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "builtins-arm.cc"; sourceTree = "<group>"; };
- 897FF10A0E719B8F00D62E90 /* builtins-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "builtins-ia32.cc"; sourceTree = "<group>"; };
+ 897FF1090E719B8F00D62E90 /* builtins-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "builtins-arm.cc"; path = "arm/builtins-arm.cc"; sourceTree = "<group>"; };
+ 897FF10A0E719B8F00D62E90 /* builtins-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "builtins-ia32.cc"; path = "ia32/builtins-ia32.cc"; sourceTree = "<group>"; };
897FF10B0E719B8F00D62E90 /* builtins.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = builtins.cc; sourceTree = "<group>"; };
897FF10C0E719B8F00D62E90 /* builtins.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = builtins.h; sourceTree = "<group>"; };
897FF10D0E719B8F00D62E90 /* char-predicates-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "char-predicates-inl.h"; sourceTree = "<group>"; };
@@ -337,14 +340,14 @@
897FF1110E719B8F00D62E90 /* code-stubs.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "code-stubs.cc"; sourceTree = "<group>"; };
897FF1120E719B8F00D62E90 /* code-stubs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "code-stubs.h"; sourceTree = "<group>"; };
897FF1130E719B8F00D62E90 /* code.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = code.h; sourceTree = "<group>"; };
- 897FF1140E719B8F00D62E90 /* codegen-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "codegen-arm.cc"; sourceTree = "<group>"; };
- 897FF1150E719B8F00D62E90 /* codegen-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "codegen-ia32.cc"; sourceTree = "<group>"; };
+ 897FF1140E719B8F00D62E90 /* codegen-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "codegen-arm.cc"; path = "arm/codegen-arm.cc"; sourceTree = "<group>"; };
+ 897FF1150E719B8F00D62E90 /* codegen-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "codegen-ia32.cc"; path = "ia32/codegen-ia32.cc"; sourceTree = "<group>"; };
897FF1160E719B8F00D62E90 /* codegen-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "codegen-inl.h"; sourceTree = "<group>"; };
897FF1170E719B8F00D62E90 /* codegen.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = codegen.cc; sourceTree = "<group>"; };
897FF1180E719B8F00D62E90 /* codegen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = codegen.h; sourceTree = "<group>"; };
897FF1190E719B8F00D62E90 /* compiler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = compiler.cc; sourceTree = "<group>"; };
897FF11A0E719B8F00D62E90 /* compiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = compiler.h; sourceTree = "<group>"; };
- 897FF11B0E719B8F00D62E90 /* constants-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "constants-arm.h"; sourceTree = "<group>"; };
+ 897FF11B0E719B8F00D62E90 /* constants-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "constants-arm.h"; path = "arm/constants-arm.h"; sourceTree = "<group>"; };
897FF11C0E719B8F00D62E90 /* contexts.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = contexts.cc; sourceTree = "<group>"; };
897FF11D0E719B8F00D62E90 /* contexts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = contexts.h; sourceTree = "<group>"; };
897FF11E0E719B8F00D62E90 /* conversions-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "conversions-inl.h"; sourceTree = "<group>"; };
@@ -352,15 +355,15 @@
897FF1200E719B8F00D62E90 /* conversions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = conversions.h; sourceTree = "<group>"; };
897FF1210E719B8F00D62E90 /* counters.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = counters.cc; sourceTree = "<group>"; };
897FF1220E719B8F00D62E90 /* counters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = counters.h; sourceTree = "<group>"; };
- 897FF1230E719B8F00D62E90 /* cpu-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "cpu-arm.cc"; sourceTree = "<group>"; };
- 897FF1240E719B8F00D62E90 /* cpu-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "cpu-ia32.cc"; sourceTree = "<group>"; };
+ 897FF1230E719B8F00D62E90 /* cpu-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "cpu-arm.cc"; path = "arm/cpu-arm.cc"; sourceTree = "<group>"; };
+ 897FF1240E719B8F00D62E90 /* cpu-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "cpu-ia32.cc"; path = "ia32/cpu-ia32.cc"; sourceTree = "<group>"; };
897FF1250E719B8F00D62E90 /* cpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpu.h; sourceTree = "<group>"; };
897FF1260E719B8F00D62E90 /* dateparser.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dateparser.cc; sourceTree = "<group>"; };
897FF1270E719B8F00D62E90 /* dateparser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dateparser.h; sourceTree = "<group>"; };
897FF1280E719B8F00D62E90 /* debug.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug.cc; sourceTree = "<group>"; };
897FF1290E719B8F00D62E90 /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = "<group>"; };
- 897FF12A0E719B8F00D62E90 /* disasm-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "disasm-arm.cc"; sourceTree = "<group>"; };
- 897FF12B0E719B8F00D62E90 /* disasm-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "disasm-ia32.cc"; sourceTree = "<group>"; };
+ 897FF12A0E719B8F00D62E90 /* disasm-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "disasm-arm.cc"; path = "arm/disasm-arm.cc"; sourceTree = "<group>"; };
+ 897FF12B0E719B8F00D62E90 /* disasm-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "disasm-ia32.cc"; path = "ia32/disasm-ia32.cc"; sourceTree = "<group>"; };
897FF12C0E719B8F00D62E90 /* disasm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = disasm.h; sourceTree = "<group>"; };
897FF12D0E719B8F00D62E90 /* disassembler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = disassembler.cc; sourceTree = "<group>"; };
897FF12E0E719B8F00D62E90 /* disassembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = disassembler.h; sourceTree = "<group>"; };
@@ -371,10 +374,10 @@
897FF1330E719B8F00D62E90 /* factory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = factory.h; sourceTree = "<group>"; };
897FF1350E719B8F00D62E90 /* flags.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = flags.cc; sourceTree = "<group>"; };
897FF1360E719B8F00D62E90 /* flags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = flags.h; sourceTree = "<group>"; };
- 897FF1370E719B8F00D62E90 /* frames-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "frames-arm.cc"; sourceTree = "<group>"; };
- 897FF1380E719B8F00D62E90 /* frames-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "frames-arm.h"; sourceTree = "<group>"; };
- 897FF1390E719B8F00D62E90 /* frames-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "frames-ia32.cc"; sourceTree = "<group>"; };
- 897FF13A0E719B8F00D62E90 /* frames-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "frames-ia32.h"; sourceTree = "<group>"; };
+ 897FF1370E719B8F00D62E90 /* frames-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "frames-arm.cc"; path = "arm/frames-arm.cc"; sourceTree = "<group>"; };
+ 897FF1380E719B8F00D62E90 /* frames-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "frames-arm.h"; path = "arm/frames-arm.h"; sourceTree = "<group>"; };
+ 897FF1390E719B8F00D62E90 /* frames-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "frames-ia32.cc"; path = "ia32/frames-ia32.cc"; sourceTree = "<group>"; };
+ 897FF13A0E719B8F00D62E90 /* frames-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "frames-ia32.h"; path = "ia32/frames-ia32.h"; sourceTree = "<group>"; };
897FF13B0E719B8F00D62E90 /* frames-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "frames-inl.h"; sourceTree = "<group>"; };
897FF13C0E719B8F00D62E90 /* frames.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = frames.cc; sourceTree = "<group>"; };
897FF13D0E719B8F00D62E90 /* frames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = frames.h; sourceTree = "<group>"; };
@@ -389,8 +392,8 @@
897FF1460E719B8F00D62E90 /* heap-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "heap-inl.h"; sourceTree = "<group>"; };
897FF1470E719B8F00D62E90 /* heap.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = heap.cc; sourceTree = "<group>"; };
897FF1480E719B8F00D62E90 /* heap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = heap.h; sourceTree = "<group>"; };
- 897FF1490E719B8F00D62E90 /* ic-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "ic-arm.cc"; sourceTree = "<group>"; };
- 897FF14A0E719B8F00D62E90 /* ic-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "ic-ia32.cc"; sourceTree = "<group>"; };
+ 897FF1490E719B8F00D62E90 /* ic-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "ic-arm.cc"; path = "arm/ic-arm.cc"; sourceTree = "<group>"; };
+ 897FF14A0E719B8F00D62E90 /* ic-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "ic-ia32.cc"; path = "ia32/ic-ia32.cc"; sourceTree = "<group>"; };
897FF14B0E719B8F00D62E90 /* ic-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ic-inl.h"; sourceTree = "<group>"; };
897FF14C0E719B8F00D62E90 /* ic.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ic.cc; sourceTree = "<group>"; };
897FF14D0E719B8F00D62E90 /* ic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ic.h; sourceTree = "<group>"; };
@@ -400,10 +403,10 @@
897FF1510E719B8F00D62E90 /* list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = list.h; sourceTree = "<group>"; };
897FF1520E719B8F00D62E90 /* log.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = log.cc; sourceTree = "<group>"; };
897FF1530E719B8F00D62E90 /* log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = log.h; sourceTree = "<group>"; };
- 897FF1540E719B8F00D62E90 /* macro-assembler-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "macro-assembler-arm.cc"; sourceTree = "<group>"; };
- 897FF1550E719B8F00D62E90 /* macro-assembler-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "macro-assembler-arm.h"; sourceTree = "<group>"; };
- 897FF1560E719B8F00D62E90 /* macro-assembler-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "macro-assembler-ia32.cc"; sourceTree = "<group>"; };
- 897FF1570E719B8F00D62E90 /* macro-assembler-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "macro-assembler-ia32.h"; sourceTree = "<group>"; };
+ 897FF1540E719B8F00D62E90 /* macro-assembler-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "macro-assembler-arm.cc"; path = "arm/macro-assembler-arm.cc"; sourceTree = "<group>"; };
+ 897FF1550E719B8F00D62E90 /* macro-assembler-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "macro-assembler-arm.h"; path = "arm/macro-assembler-arm.h"; sourceTree = "<group>"; };
+ 897FF1560E719B8F00D62E90 /* macro-assembler-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "macro-assembler-ia32.cc"; path = "ia32/macro-assembler-ia32.cc"; sourceTree = "<group>"; };
+ 897FF1570E719B8F00D62E90 /* macro-assembler-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "macro-assembler-ia32.h"; path = "ia32/macro-assembler-ia32.h"; sourceTree = "<group>"; };
897FF1580E719B8F00D62E90 /* macro-assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "macro-assembler.h"; sourceTree = "<group>"; };
897FF1590E719B8F00D62E90 /* mark-compact.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "mark-compact.cc"; sourceTree = "<group>"; };
897FF15A0E719B8F00D62E90 /* mark-compact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mark-compact.h"; sourceTree = "<group>"; };
@@ -441,10 +444,10 @@
897FF17A0E719B8F00D62E90 /* serialize.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = serialize.cc; sourceTree = "<group>"; };
897FF17B0E719B8F00D62E90 /* serialize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = serialize.h; sourceTree = "<group>"; };
897FF17C0E719B8F00D62E90 /* shell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = shell.h; sourceTree = "<group>"; };
- 897FF17D0E719B8F00D62E90 /* simulator-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "simulator-arm.cc"; sourceTree = "<group>"; };
- 897FF17E0E719B8F00D62E90 /* simulator-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "simulator-arm.h"; sourceTree = "<group>"; };
- 897FF17F0E719B8F00D62E90 /* simulator-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "simulator-ia32.cc"; sourceTree = "<group>"; };
- 897FF1800E719B8F00D62E90 /* simulator-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "simulator-ia32.h"; sourceTree = "<group>"; };
+ 897FF17D0E719B8F00D62E90 /* simulator-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "simulator-arm.cc"; path = "arm/simulator-arm.cc"; sourceTree = "<group>"; };
+ 897FF17E0E719B8F00D62E90 /* simulator-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "simulator-arm.h"; path = "arm/simulator-arm.h"; sourceTree = "<group>"; };
+ 897FF17F0E719B8F00D62E90 /* simulator-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "simulator-ia32.cc"; path = "ia32/simulator-ia32.cc"; sourceTree = "<group>"; };
+ 897FF1800E719B8F00D62E90 /* simulator-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "simulator-ia32.h"; path = "ia32/simulator-ia32.h"; sourceTree = "<group>"; };
897FF1810E719B8F00D62E90 /* smart-pointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "smart-pointer.h"; sourceTree = "<group>"; };
897FF1820E719B8F00D62E90 /* snapshot-common.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "snapshot-common.cc"; sourceTree = "<group>"; };
897FF1830E719B8F00D62E90 /* snapshot-empty.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "snapshot-empty.cc"; sourceTree = "<group>"; };
@@ -454,8 +457,8 @@
897FF1870E719B8F00D62E90 /* spaces.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = spaces.h; sourceTree = "<group>"; };
897FF1880E719B8F00D62E90 /* string-stream.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "string-stream.cc"; sourceTree = "<group>"; };
897FF1890E719B8F00D62E90 /* string-stream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "string-stream.h"; sourceTree = "<group>"; };
- 897FF18A0E719B8F00D62E90 /* stub-cache-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "stub-cache-arm.cc"; sourceTree = "<group>"; };
- 897FF18B0E719B8F00D62E90 /* stub-cache-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "stub-cache-ia32.cc"; sourceTree = "<group>"; };
+ 897FF18A0E719B8F00D62E90 /* stub-cache-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "stub-cache-arm.cc"; path = "arm/stub-cache-arm.cc"; sourceTree = "<group>"; };
+ 897FF18B0E719B8F00D62E90 /* stub-cache-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "stub-cache-ia32.cc"; path = "ia32/stub-cache-ia32.cc"; sourceTree = "<group>"; };
897FF18C0E719B8F00D62E90 /* stub-cache.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "stub-cache.cc"; sourceTree = "<group>"; };
897FF18D0E719B8F00D62E90 /* stub-cache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "stub-cache.h"; sourceTree = "<group>"; };
897FF18E0E719B8F00D62E90 /* token.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = token.cc; sourceTree = "<group>"; };
@@ -495,17 +498,19 @@
897FF1B50E719C0900D62E90 /* shell.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shell.cc; sourceTree = "<group>"; };
897FF1B60E719C2300D62E90 /* js2c.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = js2c.py; sourceTree = "<group>"; };
897FF1B70E719C2E00D62E90 /* macros.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; name = macros.py; path = ../src/macros.py; sourceTree = "<group>"; };
- 898BD20C0EF6CC850068B00A /* debug-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "debug-arm.cc"; sourceTree = "<group>"; };
- 898BD20D0EF6CC850068B00A /* debug-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "debug-ia32.cc"; sourceTree = "<group>"; };
+ 897FF32F0FAA0ED200136CF6 /* version.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = version.cc; sourceTree = "<group>"; };
+ 897FF3300FAA0ED200136CF6 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = "<group>"; };
+ 898BD20C0EF6CC850068B00A /* debug-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "debug-arm.cc"; path = "arm/debug-arm.cc"; sourceTree = "<group>"; };
+ 898BD20D0EF6CC850068B00A /* debug-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "debug-ia32.cc"; path = "ia32/debug-ia32.cc"; sourceTree = "<group>"; };
89A15C630EE4661A00B48DEB /* bytecodes-irregexp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "bytecodes-irregexp.h"; sourceTree = "<group>"; };
89A15C660EE4665300B48DEB /* interpreter-irregexp.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "interpreter-irregexp.cc"; sourceTree = "<group>"; };
89A15C670EE4665300B48DEB /* interpreter-irregexp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "interpreter-irregexp.h"; sourceTree = "<group>"; };
89A15C680EE4665300B48DEB /* jsregexp-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "jsregexp-inl.h"; sourceTree = "<group>"; };
89A15C6D0EE466A900B48DEB /* platform-freebsd.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "platform-freebsd.cc"; sourceTree = "<group>"; };
- 89A15C700EE466D000B48DEB /* regexp-macro-assembler-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "regexp-macro-assembler-arm.cc"; sourceTree = "<group>"; };
- 89A15C710EE466D000B48DEB /* regexp-macro-assembler-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "regexp-macro-assembler-arm.h"; sourceTree = "<group>"; };
- 89A15C720EE466D000B48DEB /* regexp-macro-assembler-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "regexp-macro-assembler-ia32.cc"; sourceTree = "<group>"; };
- 89A15C730EE466D000B48DEB /* regexp-macro-assembler-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "regexp-macro-assembler-ia32.h"; sourceTree = "<group>"; };
+ 89A15C700EE466D000B48DEB /* regexp-macro-assembler-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "regexp-macro-assembler-arm.cc"; path = "arm/regexp-macro-assembler-arm.cc"; sourceTree = "<group>"; };
+ 89A15C710EE466D000B48DEB /* regexp-macro-assembler-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "regexp-macro-assembler-arm.h"; path = "arm/regexp-macro-assembler-arm.h"; sourceTree = "<group>"; };
+ 89A15C720EE466D000B48DEB /* regexp-macro-assembler-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "regexp-macro-assembler-ia32.cc"; path = "ia32/regexp-macro-assembler-ia32.cc"; sourceTree = "<group>"; };
+ 89A15C730EE466D000B48DEB /* regexp-macro-assembler-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "regexp-macro-assembler-ia32.h"; path = "ia32/regexp-macro-assembler-ia32.h"; sourceTree = "<group>"; };
89A15C740EE466D000B48DEB /* regexp-macro-assembler-irregexp-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "regexp-macro-assembler-irregexp-inl.h"; sourceTree = "<group>"; };
89A15C750EE466D000B48DEB /* regexp-macro-assembler-irregexp.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "regexp-macro-assembler-irregexp.cc"; sourceTree = "<group>"; };
89A15C760EE466D000B48DEB /* regexp-macro-assembler-irregexp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "regexp-macro-assembler-irregexp.h"; sourceTree = "<group>"; };
@@ -826,6 +831,8 @@
897FF19E0E719B8F00D62E90 /* v8threads.h */,
897FF19F0E719B8F00D62E90 /* variables.cc */,
897FF1A00E719B8F00D62E90 /* variables.h */,
+ 897FF32F0FAA0ED200136CF6 /* version.cc */,
+ 897FF3300FAA0ED200136CF6 /* version.h */,
58950D560F55514900F3E8BA /* virtual-frame-arm.cc */,
58950D570F55514900F3E8BA /* virtual-frame-arm.h */,
58950D580F55514900F3E8BA /* virtual-frame-ia32.cc */,
@@ -846,6 +853,7 @@
897FF1A70E719BC100D62E90 /* array.js */,
897FF1A80E719BC100D62E90 /* date-delay.js */,
897FF1A90E719BC100D62E90 /* debug-delay.js */,
+ 58242A1E0FA1F14D00BD6F59 /* json-delay.js */,
897FF1AA0E719BC100D62E90 /* math.js */,
897FF1AB0E719BC100D62E90 /* messages.js */,
897FF1AC0E719BC100D62E90 /* mirror-delay.js */,
@@ -1059,7 +1067,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "set -ex\nJS_FILES=\"runtime.js\"\\\n\" v8natives.js\"\\\n\" array.js\"\\\n\" string.js\"\\\n\" uri.js\"\\\n\" math.js\"\\\n\" messages.js\"\\\n\" apinatives.js\"\\\n\" debug-delay.js\"\\\n\" mirror-delay.js\"\\\n\" date-delay.js\"\\\n\" regexp-delay.js\"\\\n\" macros.py\"\n\nV8ROOT=\"${SRCROOT}/..\"\n\nSRC_DIR=\"${V8ROOT}/src\"\n\nNATIVE_JS_FILES=\"\"\n\nfor i in ${JS_FILES} ; do\n NATIVE_JS_FILES+=\"${SRC_DIR}/${i} \"\ndone\n\nV8_GENERATED_SOURCES_DIR=\"${CONFIGURATION_TEMP_DIR}/generated\"\nmkdir -p \"${V8_GENERATED_SOURCES_DIR}\"\n\nLIBRARIES_CC=\"${V8_GENERATED_SOURCES_DIR}/libraries.cc\"\nLIBRARIES_EMPTY_CC=\"${V8_GENERATED_SOURCES_DIR}/libraries-empty.cc\"\n\npython \"${V8ROOT}/tools/js2c.py\" \\\n \"${LIBRARIES_CC}.new\" \\\n \"${LIBRARIES_EMPTY_CC}.new\" \\\n \"CORE\" \\\n ${NATIVE_JS_FILES}\n\n# Only use the new files if they're different from the existing files (if any),\n# preserving the existing files' timestamps when there are no changes. This\n# minimizes unnecessary build activity for a no-change build.\n\nif ! diff -q \"${LIBRARIES_CC}.new\" \"${LIBRARIES_CC}\" >& /dev/null ; then\n mv \"${LIBRARIES_CC}.new\" \"${LIBRARIES_CC}\"\nelse\n rm \"${LIBRARIES_CC}.new\"\nfi\n\nif ! diff -q \"${LIBRARIES_EMPTY_CC}.new\" \"${LIBRARIES_EMPTY_CC}\" >& /dev/null ; then\n mv \"${LIBRARIES_EMPTY_CC}.new\" \"${LIBRARIES_EMPTY_CC}\"\nelse\n rm \"${LIBRARIES_EMPTY_CC}.new\"\nfi\n";
+ shellScript = "set -ex\nJS_FILES=\"runtime.js\"\\\n\" v8natives.js\"\\\n\" array.js\"\\\n\" string.js\"\\\n\" uri.js\"\\\n\" math.js\"\\\n\" messages.js\"\\\n\" apinatives.js\"\\\n\" debug-delay.js\"\\\n\" mirror-delay.js\"\\\n\" date-delay.js\"\\\n\" json-delay.js\"\\\n\" regexp-delay.js\"\\\n\" macros.py\"\n\nV8ROOT=\"${SRCROOT}/..\"\n\nSRC_DIR=\"${V8ROOT}/src\"\n\nNATIVE_JS_FILES=\"\"\n\nfor i in ${JS_FILES} ; do\n NATIVE_JS_FILES+=\"${SRC_DIR}/${i} \"\ndone\n\nV8_GENERATED_SOURCES_DIR=\"${CONFIGURATION_TEMP_DIR}/generated\"\nmkdir -p \"${V8_GENERATED_SOURCES_DIR}\"\n\nLIBRARIES_CC=\"${V8_GENERATED_SOURCES_DIR}/libraries.cc\"\nLIBRARIES_EMPTY_CC=\"${V8_GENERATED_SOURCES_DIR}/libraries-empty.cc\"\n\npython \"${V8ROOT}/tools/js2c.py\" \\\n \"${LIBRARIES_CC}.new\" \\\n \"${LIBRARIES_EMPTY_CC}.new\" \\\n \"CORE\" \\\n ${NATIVE_JS_FILES}\n\n# Only use the new files if they're different from the existing files (if any),\n# preserving the existing files' timestamps when there are no changes. This\n# minimizes unnecessary build activity for a no-change build.\n\nif ! diff -q \"${LIBRARIES_CC}.new\" \"${LIBRARIES_CC}\" >& /dev/null ; then\n mv \"${LIBRARIES_CC}.new\" \"${LIBRARIES_CC}\"\nelse\n rm \"${LIBRARIES_CC}.new\"\nfi\n\nif ! diff -q \"${LIBRARIES_EMPTY_CC}.new\" \"${LIBRARIES_EMPTY_CC}\" >& /dev/null ; then\n mv \"${LIBRARIES_EMPTY_CC}.new\" \"${LIBRARIES_EMPTY_CC}\"\nelse\n rm \"${LIBRARIES_EMPTY_CC}.new\"\nfi\n";
};
89F23C3D0E78D5B2006B2466 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
@@ -1072,7 +1080,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "set -ex\nJS_FILES=\"runtime.js\"\\\n\" v8natives.js\"\\\n\" array.js\"\\\n\" string.js\"\\\n\" uri.js\"\\\n\" math.js\"\\\n\" messages.js\"\\\n\" apinatives.js\"\\\n\" debug-delay.js\"\\\n\" mirror-delay.js\"\\\n\" date-delay.js\"\\\n\" regexp-delay.js\"\\\n\" macros.py\"\n\nV8ROOT=\"${SRCROOT}/..\"\n\nSRC_DIR=\"${V8ROOT}/src\"\n\nNATIVE_JS_FILES=\"\"\n\nfor i in ${JS_FILES} ; do\n NATIVE_JS_FILES+=\"${SRC_DIR}/${i} \"\ndone\n\nV8_GENERATED_SOURCES_DIR=\"${CONFIGURATION_TEMP_DIR}/generated\"\nmkdir -p \"${V8_GENERATED_SOURCES_DIR}\"\n\nLIBRARIES_CC=\"${V8_GENERATED_SOURCES_DIR}/libraries.cc\"\nLIBRARIES_EMPTY_CC=\"${V8_GENERATED_SOURCES_DIR}/libraries-empty.cc\"\n\npython \"${V8ROOT}/tools/js2c.py\" \\\n \"${LIBRARIES_CC}.new\" \\\n \"${LIBRARIES_EMPTY_CC}.new\" \\\n \"CORE\" \\\n ${NATIVE_JS_FILES}\n\n# Only use the new files if they're different from the existing files (if any),\n# preserving the existing files' timestamps when there are no changes. This\n# minimizes unnecessary build activity for a no-change build.\n\nif ! diff -q \"${LIBRARIES_CC}.new\" \"${LIBRARIES_CC}\" >& /dev/null ; then\n mv \"${LIBRARIES_CC}.new\" \"${LIBRARIES_CC}\"\nelse\n rm \"${LIBRARIES_CC}.new\"\nfi\n\nif ! diff -q \"${LIBRARIES_EMPTY_CC}.new\" \"${LIBRARIES_EMPTY_CC}\" >& /dev/null ; then\n mv \"${LIBRARIES_EMPTY_CC}.new\" \"${LIBRARIES_EMPTY_CC}\"\nelse\n rm \"${LIBRARIES_EMPTY_CC}.new\"\nfi\n";
+ shellScript = "set -ex\nJS_FILES=\"runtime.js\"\\\n\" v8natives.js\"\\\n\" array.js\"\\\n\" string.js\"\\\n\" uri.js\"\\\n\" math.js\"\\\n\" messages.js\"\\\n\" apinatives.js\"\\\n\" debug-delay.js\"\\\n\" mirror-delay.js\"\\\n\" date-delay.js\"\\\n\" json-delay.js\"\\\n\" regexp-delay.js\"\\\n\" macros.py\"\n\nV8ROOT=\"${SRCROOT}/..\"\n\nSRC_DIR=\"${V8ROOT}/src\"\n\nNATIVE_JS_FILES=\"\"\n\nfor i in ${JS_FILES} ; do\n NATIVE_JS_FILES+=\"${SRC_DIR}/${i} \"\ndone\n\nV8_GENERATED_SOURCES_DIR=\"${CONFIGURATION_TEMP_DIR}/generated\"\nmkdir -p \"${V8_GENERATED_SOURCES_DIR}\"\n\nLIBRARIES_CC=\"${V8_GENERATED_SOURCES_DIR}/libraries.cc\"\nLIBRARIES_EMPTY_CC=\"${V8_GENERATED_SOURCES_DIR}/libraries-empty.cc\"\n\npython \"${V8ROOT}/tools/js2c.py\" \\\n \"${LIBRARIES_CC}.new\" \\\n \"${LIBRARIES_EMPTY_CC}.new\" \\\n \"CORE\" \\\n ${NATIVE_JS_FILES}\n\n# Only use the new files if they're different from the existing files (if any),\n# preserving the existing files' timestamps when there are no changes. This\n# minimizes unnecessary build activity for a no-change build.\n\nif ! diff -q \"${LIBRARIES_CC}.new\" \"${LIBRARIES_CC}\" >& /dev/null ; then\n mv \"${LIBRARIES_CC}.new\" \"${LIBRARIES_CC}\"\nelse\n rm \"${LIBRARIES_CC}.new\"\nfi\n\nif ! diff -q \"${LIBRARIES_EMPTY_CC}.new\" \"${LIBRARIES_EMPTY_CC}\" >& /dev/null ; then\n mv \"${LIBRARIES_EMPTY_CC}.new\" \"${LIBRARIES_EMPTY_CC}\"\nelse\n rm \"${LIBRARIES_EMPTY_CC}.new\"\nfi\n";
};
/* End PBXShellScriptBuildPhase section */
@@ -1175,6 +1183,7 @@
89A88E2B0E71A6D10043BA31 /* v8.cc in Sources */,
89A88E2C0E71A6D20043BA31 /* v8threads.cc in Sources */,
89A88E2D0E71A6D50043BA31 /* variables.cc in Sources */,
+ 89B933AF0FAA0F9600201304 /* version.cc in Sources */,
58950D660F5551C200F3E8BA /* virtual-frame.cc in Sources */,
58950D670F5551C400F3E8BA /* virtual-frame-ia32.cc in Sources */,
89A88E2E0E71A6D60043BA31 /* zone.cc in Sources */,
@@ -1277,6 +1286,7 @@
89F23C7F0E78D5B2006B2466 /* v8.cc in Sources */,
89F23C800E78D5B2006B2466 /* v8threads.cc in Sources */,
89F23C810E78D5B2006B2466 /* variables.cc in Sources */,
+ 89B933B00FAA0F9D00201304 /* version.cc in Sources */,
58950D680F5551CB00F3E8BA /* virtual-frame.cc in Sources */,
58950D690F5551CE00F3E8BA /* virtual-frame-arm.cc in Sources */,
89F23C820E78D5B2006B2466 /* zone.cc in Sources */,
@@ -1426,6 +1436,11 @@
893988090F2A35FA007D5254 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ V8_TARGET_ARCH_IA32,
+ DEBUG,
+ );
HEADER_SEARCH_PATHS = ../src;
PRODUCT_NAME = v8_shell;
};
@@ -1434,6 +1449,11 @@
8939880A0F2A35FA007D5254 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ V8_TARGET_ARCH_IA32,
+ NDEBUG,
+ );
HEADER_SEARCH_PATHS = ../src;
PRODUCT_NAME = v8_shell;
};
@@ -1446,6 +1466,7 @@
GCC_PREPROCESSOR_DEFINITIONS = (
"$(GCC_PREPROCESSOR_DEFINITIONS)",
ENABLE_DISASSEMBLER,
+ V8_TARGET_ARCH_IA32,
ENABLE_LOGGING_AND_PROFILING,
);
HEADER_SEARCH_PATHS = ../src;
@@ -1458,6 +1479,11 @@
isa = XCBuildConfiguration;
buildSettings = {
DEPLOYMENT_POSTPROCESSING = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(GCC_PREPROCESSOR_DEFINITIONS)",
+ V8_TARGET_ARCH_IA32,
+ NDEBUG,
+ );
HEADER_SEARCH_PATHS = ../src;
PRODUCT_NAME = v8;
STRIP_STYLE = debugging;
@@ -1486,7 +1512,7 @@
DEPLOYMENT_POSTPROCESSING = NO;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(GCC_PREPROCESSOR_DEFINITIONS)",
- ARM,
+ V8_TARGET_ARCH_ARM,
ENABLE_DISASSEMBLER,
ENABLE_LOGGING_AND_PROFILING,
);
@@ -1502,7 +1528,7 @@
DEPLOYMENT_POSTPROCESSING = NO;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(GCC_PREPROCESSOR_DEFINITIONS)",
- ARM,
+ V8_TARGET_ARCH_ARM,
);
HEADER_SEARCH_PATHS = ../src;
PRODUCT_NAME = "v8-arm";
diff --git a/deps/v8/tools/visual_studio/arm.vsprops b/deps/v8/tools/visual_studio/arm.vsprops
index 0e37d4179..3aa937448 100644
--- a/deps/v8/tools/visual_studio/arm.vsprops
+++ b/deps/v8/tools/visual_studio/arm.vsprops
@@ -6,7 +6,7 @@
>
<Tool
Name="VCCLCompilerTool"
- PreprocessorDefinitions="ARM"
+ PreprocessorDefinitions="V8_TARGET_ARCH_ARM"
DisableSpecificWarnings="4996"
/>
</VisualStudioPropertySheet>
diff --git a/deps/v8/tools/visual_studio/d8.vcproj b/deps/v8/tools/visual_studio/d8.vcproj
index a05a3f39e..21636ba35 100644
--- a/deps/v8/tools/visual_studio/d8.vcproj
+++ b/deps/v8/tools/visual_studio/d8.vcproj
@@ -18,7 +18,7 @@
<Configuration
Name="Debug|Win32"
ConfigurationType="1"
- InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+ InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\debug.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
@@ -79,7 +79,7 @@
<Configuration
Name="Release|Win32"
ConfigurationType="1"
- InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+ InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\release.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
diff --git a/deps/v8/tools/visual_studio/ia32.vsprops b/deps/v8/tools/visual_studio/ia32.vsprops
new file mode 100644
index 000000000..fda6c32a8
--- /dev/null
+++ b/deps/v8/tools/visual_studio/ia32.vsprops
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="ia32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="V8_TARGET_ARCH_IA32"
+ />
+</VisualStudioPropertySheet>
diff --git a/deps/v8/tools/visual_studio/js2c.cmd b/deps/v8/tools/visual_studio/js2c.cmd
index b6a46a2a6..df5293ba5 100644
--- a/deps/v8/tools/visual_studio/js2c.cmd
+++ b/deps/v8/tools/visual_studio/js2c.cmd
@@ -3,4 +3,4 @@ set SOURCE_DIR=%1
set TARGET_DIR=%2
set PYTHON="..\..\..\third_party\python_24\python.exe"
if not exist %PYTHON% set PYTHON=python.exe
-%PYTHON% ..\js2c.py %TARGET_DIR%\natives.cc %TARGET_DIR%\natives-empty.cc CORE %SOURCE_DIR%\macros.py %SOURCE_DIR%\runtime.js %SOURCE_DIR%\v8natives.js %SOURCE_DIR%\array.js %SOURCE_DIR%\string.js %SOURCE_DIR%\uri.js %SOURCE_DIR%\math.js %SOURCE_DIR%\messages.js %SOURCE_DIR%\apinatives.js %SOURCE_DIR%\debug-delay.js %SOURCE_DIR%\mirror-delay.js %SOURCE_DIR%\date-delay.js %SOURCE_DIR%\regexp-delay.js
+%PYTHON% ..\js2c.py %TARGET_DIR%\natives.cc %TARGET_DIR%\natives-empty.cc CORE %SOURCE_DIR%\macros.py %SOURCE_DIR%\runtime.js %SOURCE_DIR%\v8natives.js %SOURCE_DIR%\array.js %SOURCE_DIR%\string.js %SOURCE_DIR%\uri.js %SOURCE_DIR%\math.js %SOURCE_DIR%\messages.js %SOURCE_DIR%\apinatives.js %SOURCE_DIR%\debug-delay.js %SOURCE_DIR%\mirror-delay.js %SOURCE_DIR%\date-delay.js %SOURCE_DIR%\regexp-delay.js %SOURCE_DIR%\json-delay.js
diff --git a/deps/v8/tools/visual_studio/v8.vcproj b/deps/v8/tools/visual_studio/v8.vcproj
index 212fd07c0..47ba8c1f4 100644
--- a/deps/v8/tools/visual_studio/v8.vcproj
+++ b/deps/v8/tools/visual_studio/v8.vcproj
@@ -18,7 +18,7 @@
<Configuration
Name="Debug|Win32"
ConfigurationType="4"
- InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+ InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\debug.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
@@ -70,7 +70,7 @@
<Configuration
Name="Release|Win32"
ConfigurationType="4"
- InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+ InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\release.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
@@ -163,6 +163,10 @@
>
</File>
<File
+ RelativePath="..\..\src\json-delay.js"
+ >
+ </File>
+ <File
RelativePath="..\..\src\runtime.js"
>
</File>
@@ -184,7 +188,7 @@
Name="VCCustomBuildTool"
Description="Processing js files..."
CommandLine=".\js2c.cmd ..\..\src &quot;$(IntDir)\DerivedSources&quot;"
- AdditionalDependencies="..\..\src\macros.py;..\..\src\runtime.js;..\..\src\v8natives.js;..\..\src\array.js;..\..\src\string.js;..\..\src\uri.js;..\..\src\math.js;..\..\src\messages.js;..\..\src\apinatives.js;..\..\src\debug-delay.js;..\..\src\mirror-delay.js;..\..\src\date-delay.js;..\..\src\regexp-delay.js"
+ AdditionalDependencies="..\..\src\macros.py;..\..\src\runtime.js;..\..\src\v8natives.js;..\..\src\array.js;..\..\src\string.js;..\..\src\uri.js;..\..\src\math.js;..\..\src\messages.js;..\..\src\apinatives.js;..\..\src\debug-delay.js;..\..\src\mirror-delay.js;..\..\src\date-delay.js;..\..\src\regexp-delay.js;..\..\src\json-delay.js"
Outputs="$(IntDir)\DerivedSources\natives.cc;$(IntDir)\DerivedSources\natives-empty.cc"
/>
</FileConfiguration>
@@ -195,7 +199,7 @@
Name="VCCustomBuildTool"
Description="Processing js files..."
CommandLine=".\js2c.cmd ..\..\src &quot;$(IntDir)\DerivedSources&quot;"
- AdditionalDependencies="..\..\src\macros.py;..\..\src\runtime.js;..\..\src\v8natives.js;..\..\src\array.js;..\..\src\string.js;..\..\src\uri.js;..\..\src\math.js;..\..\src\messages.js;..\..\src\apinatives.js;..\..\src\debug-delay.js;..\..\src\mirror-delay.js;..\..\src\date-delay.js;..\..\src\regexp-delay.js"
+ AdditionalDependencies="..\..\src\macros.py;..\..\src\runtime.js;..\..\src\v8natives.js;..\..\src\array.js;..\..\src\string.js;..\..\src\uri.js;..\..\src\math.js;..\..\src\messages.js;..\..\src\apinatives.js;..\..\src\debug-delay.js;..\..\src\mirror-delay.js;..\..\src\date-delay.js;..\..\src\regexp-delay.js;..\..\src\json-delay.js"
Outputs="$(IntDir)\DerivedSources\natives.cc;$(IntDir)\DerivedSources\natives-empty.cc"
/>
</FileConfiguration>
diff --git a/deps/v8/tools/visual_studio/v8_base.vcproj b/deps/v8/tools/visual_studio/v8_base.vcproj
index 776e628d0..b1802eff7 100644
--- a/deps/v8/tools/visual_studio/v8_base.vcproj
+++ b/deps/v8/tools/visual_studio/v8_base.vcproj
@@ -18,7 +18,7 @@
<Configuration
Name="Debug|Win32"
ConfigurationType="4"
- InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+ InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\debug.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
@@ -69,7 +69,7 @@
<Configuration
Name="Release|Win32"
ConfigurationType="4"
- InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+ InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\release.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
@@ -177,15 +177,15 @@
>
</File>
<File
- RelativePath="..\..\src\assembler-ia32-inl.h"
+ RelativePath="..\..\src\ia32\assembler-ia32-inl.h"
>
</File>
<File
- RelativePath="..\..\src\assembler-ia32.cc"
+ RelativePath="..\..\src\ia32\assembler-ia32.cc"
>
</File>
<File
- RelativePath="..\..\src\assembler-ia32.h"
+ RelativePath="..\..\src\ia32\assembler-ia32.h"
>
</File>
<File
@@ -221,7 +221,7 @@
>
</File>
<File
- RelativePath="..\..\src\builtins-ia32.cc"
+ RelativePath="..\..\src\ia32\builtins-ia32.cc"
>
</File>
<File
@@ -265,11 +265,11 @@
>
</File>
<File
- RelativePath="..\..\src\codegen-ia32.cc"
+ RelativePath="..\..\src\ia32\codegen-ia32.cc"
>
</File>
<File
- RelativePath="..\..\src\codegen-ia32.h"
+ RelativePath="..\..\src\ia32\codegen-ia32.h"
>
</File>
<File
@@ -329,7 +329,7 @@
>
</File>
<File
- RelativePath="..\..\src\cpu-ia32.cc"
+ RelativePath="..\..\src\ia32\cpu-ia32.cc"
>
</File>
<File
@@ -353,7 +353,7 @@
>
</File>
<File
- RelativePath="..\..\src\debug-ia32.cc"
+ RelativePath="..\..\src\ia32\debug-ia32.cc"
>
</File>
<File
@@ -397,11 +397,11 @@
>
</File>
<File
- RelativePath="..\..\src\frames-ia32.cc"
+ RelativePath="..\..\src\ia32\frames-ia32.cc"
>
</File>
<File
- RelativePath="..\..\src\frames-ia32.h"
+ RelativePath="..\..\src\ia32\frames-ia32.h"
>
</File>
<File
@@ -469,7 +469,7 @@
>
</File>
<File
- RelativePath="..\..\src\ic-ia32.cc"
+ RelativePath="..\..\src\ia32\ic-ia32.cc"
>
</File>
<File
@@ -505,7 +505,7 @@
>
</File>
<File
- RelativePath="..\..\src\jump-target-ia32.cc"
+ RelativePath="..\..\src\ia32\jump-target-ia32.cc"
>
</File>
<File
@@ -537,11 +537,11 @@
>
</File>
<File
- RelativePath="..\..\src\macro-assembler-ia32.cc"
+ RelativePath="..\..\src\ia32\macro-assembler-ia32.cc"
>
</File>
<File
- RelativePath="..\..\src\macro-assembler-ia32.h"
+ RelativePath="..\..\src\ia32\macro-assembler-ia32.h"
>
</File>
<File
@@ -645,11 +645,11 @@
>
</File>
<File
- RelativePath="..\..\src\regexp-macro-assembler-ia32.cc"
+ RelativePath="..\..\src\ia32\regexp-macro-assembler-ia32.cc"
>
</File>
<File
- RelativePath="..\..\src\regexp-macro-assembler-ia32.h"
+ RelativePath="..\..\src\ia32\regexp-macro-assembler-ia32.h"
>
</File>
<File
@@ -689,7 +689,7 @@
>
</File>
<File
- RelativePath="..\..\src\register-allocator-ia32.cc"
+ RelativePath="..\..\src\ia32\register-allocator-ia32.cc"
>
</File>
<File
@@ -773,7 +773,7 @@
>
</File>
<File
- RelativePath="..\..\src\stub-cache-ia32.cc"
+ RelativePath="..\..\src\ia32\stub-cache-ia32.cc"
>
</File>
<File
@@ -857,11 +857,19 @@
>
</File>
<File
+ RelativePath="..\..\src\version.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\version.h"
+ >
+ </File>
+ <File
RelativePath="..\..\src\virtual-frame.h"
>
</File>
<File
- RelativePath="..\..\src\virtual-frame-ia32.h"
+ RelativePath="..\..\src\ia32\virtual-frame-ia32.h"
>
</File>
<File
@@ -869,7 +877,7 @@
>
</File>
<File
- RelativePath="..\..\src\virtual-frame-ia32.cc"
+ RelativePath="..\..\src\ia32\virtual-frame-ia32.cc"
>
</File>
<File
@@ -888,7 +896,7 @@
Name="third party"
>
<File
- RelativePath="..\..\src\disasm-ia32.cc"
+ RelativePath="..\..\src\ia32\disasm-ia32.cc"
>
</File>
<File
diff --git a/deps/v8/tools/visual_studio/v8_base_arm.vcproj b/deps/v8/tools/visual_studio/v8_base_arm.vcproj
index a91d63ace..35a08d5ae 100644
--- a/deps/v8/tools/visual_studio/v8_base_arm.vcproj
+++ b/deps/v8/tools/visual_studio/v8_base_arm.vcproj
@@ -177,15 +177,15 @@
>
</File>
<File
- RelativePath="..\..\src\assembler-arm-inl.h"
+ RelativePath="..\..\src\arm\assembler-arm-inl.h"
>
</File>
<File
- RelativePath="..\..\src\assembler-arm.cc"
+ RelativePath="..\..\src\arm\assembler-arm.cc"
>
</File>
<File
- RelativePath="..\..\src\assembler-arm.h"
+ RelativePath="..\..\src\arm\assembler-arm.h"
>
</File>
<File
@@ -221,7 +221,7 @@
>
</File>
<File
- RelativePath="..\..\src\builtins-arm.cc"
+ RelativePath="..\..\src\arm\builtins-arm.cc"
>
</File>
<File
@@ -265,11 +265,11 @@
>
</File>
<File
- RelativePath="..\..\src\codegen-arm.cc"
+ RelativePath="..\..\src\arm\codegen-arm.cc"
>
</File>
<File
- RelativePath="..\..\src\codegen-arm.h"
+ RelativePath="..\..\src\arm\codegen-arm.h"
>
</File>
<File
@@ -301,7 +301,7 @@
>
</File>
<File
- RelativePath="..\..\src\constants-arm.h"
+ RelativePath="..\..\src\arm\constants-arm.h"
>
</File>
<File
@@ -333,7 +333,7 @@
>
</File>
<File
- RelativePath="..\..\src\cpu-arm.cc"
+ RelativePath="..\..\src\arm\cpu-arm.cc"
>
</File>
<File
@@ -349,7 +349,15 @@
>
</File>
<File
- RelativePath="..\..\src\debug-arm.cc"
+ RelativePath="..\..\src\debug-agent.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\debug-agent.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\arm\debug-arm.cc"
>
</File>
<File
@@ -393,11 +401,11 @@
>
</File>
<File
- RelativePath="..\..\src\frames-arm.cc"
+ RelativePath="..\..\src\arm\frames-arm.cc"
>
</File>
<File
- RelativePath="..\..\src\frames-arm.h"
+ RelativePath="..\..\src\arm\frames-arm.h"
>
</File>
<File
@@ -465,7 +473,7 @@
>
</File>
<File
- RelativePath="..\..\src\ic-arm.cc"
+ RelativePath="..\..\src\arm\ic-arm.cc"
>
</File>
<File
@@ -501,7 +509,7 @@
>
</File>
<File
- RelativePath="..\..\src\jump-target-arm.cc"
+ RelativePath="..\..\src\arm\jump-target-arm.cc"
>
</File>
<File
@@ -533,11 +541,11 @@
>
</File>
<File
- RelativePath="..\..\src\macro-assembler-arm.cc"
+ RelativePath="..\..\src\arm\macro-assembler-arm.cc"
>
</File>
<File
- RelativePath="..\..\src\macro-assembler-arm.h"
+ RelativePath="..\..\src\arm\macro-assembler-arm.h"
>
</File>
<File
@@ -593,6 +601,14 @@
>
</File>
<File
+ RelativePath="..\..\src\oprofile-agent.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\oprofile-agent.h"
+ >
+ </File>
+ <File
RelativePath="..\..\src\parser.cc"
>
</File>
@@ -633,11 +649,11 @@
>
</File>
<File
- RelativePath="..\..\src\regexp-macro-assembler-arm.cc"
+ RelativePath="..\..\src\arm\regexp-macro-assembler-arm.cc"
>
</File>
<File
- RelativePath="..\..\src\regexp-macro-assembler-arm.h"
+ RelativePath="..\..\src\arm\regexp-macro-assembler-arm.h"
>
</File>
<File
@@ -677,7 +693,7 @@
>
</File>
<File
- RelativePath="..\..\src\register-allocator-arm.cc"
+ RelativePath="..\..\src\arm\register-allocator-arm.cc"
>
</File>
<File
@@ -741,11 +757,11 @@
>
</File>
<File
- RelativePath="..\..\src\simulator-arm.cc"
+ RelativePath="..\..\src\arm\simulator-arm.cc"
>
</File>
<File
- RelativePath="..\..\src\simulator-arm.h"
+ RelativePath="..\..\src\arm\simulator-arm.h"
>
</File>
<File
@@ -769,7 +785,7 @@
>
</File>
<File
- RelativePath="..\..\src\stub-cache-arm.cc"
+ RelativePath="..\..\src\arm\stub-cache-arm.cc"
>
</File>
<File
@@ -853,11 +869,19 @@
>
</File>
<File
+ RelativePath="..\..\src\version.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\version.h"
+ >
+ </File>
+ <File
RelativePath="..\..\src\virtual-frame.h"
>
</File>
<File
- RelativePath="..\..\src\virtual-frame-arm.h"
+ RelativePath="..\..\src\arm\virtual-frame-arm.h"
>
</File>
<File
@@ -865,7 +889,7 @@
>
</File>
<File
- RelativePath="..\..\src\virtual-frame-arm.cc"
+ RelativePath="..\..\src\arm\virtual-frame-arm.cc"
>
</File>
<File
@@ -884,7 +908,7 @@
Name="third party"
>
<File
- RelativePath="..\..\src\disasm-arm.cc"
+ RelativePath="..\..\src\arm\disasm-arm.cc"
>
</File>
<File
diff --git a/deps/v8/tools/visual_studio/v8_cctest.vcproj b/deps/v8/tools/visual_studio/v8_cctest.vcproj
index 5d49d2487..6aa090ad0 100644
--- a/deps/v8/tools/visual_studio/v8_cctest.vcproj
+++ b/deps/v8/tools/visual_studio/v8_cctest.vcproj
@@ -18,7 +18,7 @@
<Configuration
Name="Debug|Win32"
ConfigurationType="1"
- InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+ InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\debug.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
@@ -79,7 +79,7 @@
<Configuration
Name="Release|Win32"
ConfigurationType="1"
- InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+ InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\release.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
@@ -202,6 +202,10 @@
>
</File>
<File
+ RelativePath="..\..\test\cctest\test-log.cc"
+ >
+ </File>
+ <File
RelativePath="..\..\test\cctest\test-log-ia32.cc"
>
</File>
@@ -233,6 +237,10 @@
RelativePath="..\..\test\cctest\test-utils.cc"
>
</File>
+ <File
+ RelativePath="..\..\test\cctest\test-version.cc"
+ >
+ </File>
</Files>
<Globals>
</Globals>
diff --git a/deps/v8/tools/visual_studio/v8_cctest_arm.vcproj b/deps/v8/tools/visual_studio/v8_cctest_arm.vcproj
index 44812f018..566d75eef 100644
--- a/deps/v8/tools/visual_studio/v8_cctest_arm.vcproj
+++ b/deps/v8/tools/visual_studio/v8_cctest_arm.vcproj
@@ -196,6 +196,10 @@
>
</File>
<File
+ RelativePath="..\..\test\cctest\test-log.cc"
+ >
+ </File>
+ <File
RelativePath="..\..\test\cctest\test-mark-compact.cc"
>
</File>
@@ -219,6 +223,10 @@
RelativePath="..\..\test\cctest\test-utils.cc"
>
</File>
+ <File
+ RelativePath="..\..\test\cctest\test-version.cc"
+ >
+ </File>
</Files>
<Globals>
</Globals>
diff --git a/deps/v8/tools/visual_studio/v8_mksnapshot.vcproj b/deps/v8/tools/visual_studio/v8_mksnapshot.vcproj
index 4d5d84f75..00950b069 100644
--- a/deps/v8/tools/visual_studio/v8_mksnapshot.vcproj
+++ b/deps/v8/tools/visual_studio/v8_mksnapshot.vcproj
@@ -18,7 +18,7 @@
<Configuration
Name="Debug|Win32"
ConfigurationType="1"
- InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+ InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\debug.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
@@ -79,7 +79,7 @@
<Configuration
Name="Release|Win32"
ConfigurationType="1"
- InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+ InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\release.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
diff --git a/deps/v8/tools/visual_studio/v8_process_sample.vcproj b/deps/v8/tools/visual_studio/v8_process_sample.vcproj
index ea8c97d4e..d94966b33 100644
--- a/deps/v8/tools/visual_studio/v8_process_sample.vcproj
+++ b/deps/v8/tools/visual_studio/v8_process_sample.vcproj
@@ -18,7 +18,7 @@
<Configuration
Name="Debug|Win32"
ConfigurationType="1"
- InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+ InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\debug.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
@@ -79,7 +79,7 @@
<Configuration
Name="Release|Win32"
ConfigurationType="1"
- InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+ InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\release.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
diff --git a/deps/v8/tools/visual_studio/v8_shell_sample.vcproj b/deps/v8/tools/visual_studio/v8_shell_sample.vcproj
index b5d9c612a..2cbd22df6 100644
--- a/deps/v8/tools/visual_studio/v8_shell_sample.vcproj
+++ b/deps/v8/tools/visual_studio/v8_shell_sample.vcproj
@@ -18,7 +18,7 @@
<Configuration
Name="Debug|Win32"
ConfigurationType="1"
- InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+ InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\debug.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
@@ -79,7 +79,7 @@
<Configuration
Name="Release|Win32"
ConfigurationType="1"
- InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+ InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\release.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
diff --git a/deps/v8/tools/visual_studio/v8_snapshot.vcproj b/deps/v8/tools/visual_studio/v8_snapshot.vcproj
index 25d922f15..29db4f8d0 100644
--- a/deps/v8/tools/visual_studio/v8_snapshot.vcproj
+++ b/deps/v8/tools/visual_studio/v8_snapshot.vcproj
@@ -18,7 +18,7 @@
<Configuration
Name="Debug|Win32"
ConfigurationType="4"
- InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+ InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\debug.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
@@ -70,7 +70,7 @@
<Configuration
Name="Release|Win32"
ConfigurationType="4"
- InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+ InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\release.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
diff --git a/deps/v8/tools/visual_studio/v8_snapshot_cc.vcproj b/deps/v8/tools/visual_studio/v8_snapshot_cc.vcproj
index 1cfac247c..7c4799afd 100644
--- a/deps/v8/tools/visual_studio/v8_snapshot_cc.vcproj
+++ b/deps/v8/tools/visual_studio/v8_snapshot_cc.vcproj
@@ -18,7 +18,7 @@
<Configuration
Name="Debug|Win32"
ConfigurationType="10"
- InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+ InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\debug.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
@@ -36,7 +36,7 @@
<Configuration
Name="Release|Win32"
ConfigurationType="10"
- InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+ InheritedPropertySheets=".\common.vsprops;.\ia32.vsprops;.\release.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
diff --git a/deps/v8/tools/windows-tick-processor.bat b/deps/v8/tools/windows-tick-processor.bat
new file mode 100644
index 000000000..52454e34b
--- /dev/null
+++ b/deps/v8/tools/windows-tick-processor.bat
@@ -0,0 +1,5 @@
+@echo off
+
+SET tools_dir=%~dp0
+
+%tools_dir%..\d8 %tools_dir%splaytree.js %tools_dir%codemap.js %tools_dir%csvparser.js %tools_dir%consarray.js %tools_dir%profile.js %tools_dir%profile_view.js %tools_dir%tickprocessor.js -- --windows %*