Browse Source

Merge branch 'v0.7.1-release'

v0.7.4-release
isaacs 13 years ago
parent
commit
5988872ff1
  1. 23
      ChangeLog
  2. 38
      deps/v8/ChangeLog
  3. 41
      deps/v8/Makefile
  4. 17
      deps/v8/SConstruct
  5. 225
      deps/v8/build/android.gypi
  6. 32
      deps/v8/build/common.gypi
  7. 1
      deps/v8/build/standalone.gypi
  8. 1
      deps/v8/src/api.cc
  9. 8
      deps/v8/src/arm/code-stubs-arm.cc
  10. 10
      deps/v8/src/arm/constants-arm.h
  11. 2
      deps/v8/src/arm/disasm-arm.cc
  12. 6
      deps/v8/src/arm/full-codegen-arm.cc
  13. 26
      deps/v8/src/arm/ic-arm.cc
  14. 58
      deps/v8/src/arm/lithium-codegen-arm.cc
  15. 72
      deps/v8/src/arm/macro-assembler-arm.cc
  16. 12
      deps/v8/src/arm/macro-assembler-arm.h
  17. 26
      deps/v8/src/arm/stub-cache-arm.cc
  18. 2
      deps/v8/src/array.js
  19. 2
      deps/v8/src/assembler.h
  20. 23
      deps/v8/src/ast.cc
  21. 2
      deps/v8/src/bignum-dtoa.h
  22. 6
      deps/v8/src/bootstrapper.cc
  23. 2
      deps/v8/src/builtins.cc
  24. 6
      deps/v8/src/d8-debug.cc
  25. 37
      deps/v8/src/d8-readline.cc
  26. 58
      deps/v8/src/d8.cc
  27. 2
      deps/v8/src/d8.gyp
  28. 19
      deps/v8/src/d8.h
  29. 2
      deps/v8/src/dtoa.h
  30. 2
      deps/v8/src/execution.cc
  31. 252
      deps/v8/src/extensions/experimental/break-iterator.cc
  32. 89
      deps/v8/src/extensions/experimental/break-iterator.h
  33. 222
      deps/v8/src/extensions/experimental/collator.cc
  34. 68
      deps/v8/src/extensions/experimental/collator.h
  35. 384
      deps/v8/src/extensions/experimental/datetime-format.cc
  36. 83
      deps/v8/src/extensions/experimental/datetime-format.h
  37. 105
      deps/v8/src/extensions/experimental/experimental.gyp
  38. 74
      deps/v8/src/extensions/experimental/i18n-extension.cc
  39. 54
      deps/v8/src/extensions/experimental/i18n-extension.h
  40. 126
      deps/v8/src/extensions/experimental/i18n-js2c.py
  41. 111
      deps/v8/src/extensions/experimental/i18n-locale.cc
  42. 60
      deps/v8/src/extensions/experimental/i18n-locale.h
  43. 87
      deps/v8/src/extensions/experimental/i18n-utils.cc
  44. 69
      deps/v8/src/extensions/experimental/i18n-utils.h
  45. 380
      deps/v8/src/extensions/experimental/i18n.js
  46. 252
      deps/v8/src/extensions/experimental/language-matcher.cc
  47. 95
      deps/v8/src/extensions/experimental/language-matcher.h
  48. 374
      deps/v8/src/extensions/experimental/number-format.cc
  49. 71
      deps/v8/src/extensions/experimental/number-format.h
  50. 2
      deps/v8/src/factory.h
  51. 10
      deps/v8/src/full-codegen.h
  52. 2
      deps/v8/src/global-handles.cc
  53. 49
      deps/v8/src/heap.cc
  54. 13
      deps/v8/src/heap.h
  55. 24
      deps/v8/src/hydrogen-instructions.cc
  56. 138
      deps/v8/src/hydrogen-instructions.h
  57. 132
      deps/v8/src/hydrogen.cc
  58. 9
      deps/v8/src/hydrogen.h
  59. 43
      deps/v8/src/ia32/code-stubs-ia32.cc
  60. 6
      deps/v8/src/ia32/full-codegen-ia32.cc
  61. 26
      deps/v8/src/ia32/ic-ia32.cc
  62. 63
      deps/v8/src/ia32/lithium-codegen-ia32.cc
  63. 67
      deps/v8/src/ia32/macro-assembler-ia32.cc
  64. 5
      deps/v8/src/ia32/macro-assembler-ia32.h
  65. 2
      deps/v8/src/ia32/regexp-macro-assembler-ia32.cc
  66. 4
      deps/v8/src/ia32/stub-cache-ia32.cc
  67. 14
      deps/v8/src/ic.cc
  68. 2
      deps/v8/src/incremental-marking-inl.h
  69. 22
      deps/v8/src/incremental-marking.cc
  70. 7
      deps/v8/src/isolate.cc
  71. 18
      deps/v8/src/isolate.h
  72. 4
      deps/v8/src/json-parser.h
  73. 2
      deps/v8/src/jsregexp.cc
  74. 2
      deps/v8/src/jsregexp.h
  75. 2
      deps/v8/src/list.h
  76. 2
      deps/v8/src/liveedit-debugger.js
  77. 2
      deps/v8/src/liveobjectlist.cc
  78. 2
      deps/v8/src/macros.py
  79. 14
      deps/v8/src/mark-compact-inl.h
  80. 71
      deps/v8/src/mark-compact.cc
  81. 14
      deps/v8/src/mark-compact.h
  82. 12
      deps/v8/src/mips/assembler-mips-inl.h
  83. 19
      deps/v8/src/mips/assembler-mips.h
  84. 6
      deps/v8/src/mips/builtins-mips.cc
  85. 29
      deps/v8/src/mips/code-stubs-mips.cc
  86. 4
      deps/v8/src/mips/constants-mips.cc
  87. 2
      deps/v8/src/mips/constants-mips.h
  88. 6
      deps/v8/src/mips/full-codegen-mips.cc
  89. 29
      deps/v8/src/mips/ic-mips.cc
  90. 116
      deps/v8/src/mips/lithium-codegen-mips.cc
  91. 10
      deps/v8/src/mips/lithium-codegen-mips.h
  92. 23
      deps/v8/src/mips/lithium-gap-resolver-mips.cc
  93. 2
      deps/v8/src/mips/lithium-mips.cc
  94. 144
      deps/v8/src/mips/macro-assembler-mips.cc
  95. 48
      deps/v8/src/mips/macro-assembler-mips.h
  96. 4
      deps/v8/src/mips/simulator-mips.cc
  97. 59
      deps/v8/src/mips/stub-cache-mips.cc
  98. 2
      deps/v8/src/objects-debug.cc
  99. 4
      deps/v8/src/objects-inl.h
  100. 2
      deps/v8/src/objects-printer.cc

23
ChangeLog

@ -1,4 +1,23 @@
2012.01.16, Version 0.7.0 (unstable) 2012.01.23, Version 0.7.1 (unstable)
* Update V8 to 3.8.8
* Install node-waf by default (Fedor Indutny)
* crypto: Add ability to turn off PKCS padding (Ingmar Runge)
* v8: implement VirtualMemory class on SunOS (Ben Noordhuis)
* Add cluster.setupMaster (Andreas Madsen)
* move `path.exists*` to `fs.exists*` (Maciej Małecki)
* typed arrays: set class name (Ben Noordhuis)
* libuv bug fixes (Igor Zinkovsky, Ben Noordhuis, Dan VerWeire)
2012.01.16, Version 0.7.0 (unstable), 9cc55dca6f67a6096c858b841c677b0593404321
* Upgrade V8 to 3.8.6 * Upgrade V8 to 3.8.6
@ -13,7 +32,7 @@
* Bug fixes * Bug fixes
2012.01.19, Version 0.6.8 (stable) 2012.01.19, Version 0.6.8 (stable), d18cebaf8a7ac701dabd71a3aa4eb0571db6a645
* Update V8 to 3.6.6.19 * Update V8 to 3.6.6.19

38
deps/v8/ChangeLog

@ -1,3 +1,41 @@
2012-01-23: Version 3.8.8
Limited number of loop iterations in Heap::ReserveSpace
(Chromium issue 99027).
Fixed solaris build (VirtualMemory) (issue 1761).
Fixed strict vs. non-strict handling of function proxies in
higher-order array and string methods.
Enabled asynchronous remote debugging with d8 (issue 1691).
Stability and performance improvements on all platforms.
2012-01-19: Version 3.8.7
Ensure that LRandom restores rsi after call to the C function on x64.
(Chromium issue http://crbug.com/110509)
Fixing include issues on *bsd when building with scons.
(issue 1897)
Provide a switch to specify -fno-strict-aliasing
(issue 1887)
Move WIN32 define from standalone.gypi to common.gypi
(issue 1760)
Fix corner-case in heap size estimation.
(issue 1893)
Fix and enable NEW_NON_STRICT_FAST ArgumentsAccess stub on x64.
(issue 1903)
Performance improvements and bug fixes.
2012-01-16: Version 3.8.6 2012-01-16: Version 3.8.6
Add primitive WebGL array support to d8. Add primitive WebGL array support to d8.

41
deps/v8/Makefile

@ -1,4 +1,4 @@
# Copyright 2011 the V8 project authors. All rights reserved. # Copyright 2012 the V8 project authors. All rights reserved.
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are # modification, are permitted provided that the following conditions are
# met: # met:
@ -33,6 +33,8 @@ OUTDIR ?= out
TESTJOBS ?= -j16 TESTJOBS ?= -j16
GYPFLAGS ?= GYPFLAGS ?=
TESTFLAGS ?= TESTFLAGS ?=
ANDROID_NDK_ROOT ?=
ANDROID_TOOL_PREFIX = $(ANDROID_NDK_ROOT)/toolchain/bin/arm-linux-androideabi
# Special build flags. Use them like this: "make library=shared" # Special build flags. Use them like this: "make library=shared"
@ -85,6 +87,10 @@ endif
ifeq ($(presubmit), no) ifeq ($(presubmit), no)
TESTFLAGS += --no-presubmit TESTFLAGS += --no-presubmit
endif endif
# strictaliasing=off (workaround for GCC-4.5)
ifeq ($(strictaliasing), off)
GYPFLAGS += -Dv8_no_strict_aliasing=1
endif
# ----------------- available targets: -------------------- # ----------------- available targets: --------------------
# - "dependencies": pulls in external dependencies (currently: GYP) # - "dependencies": pulls in external dependencies (currently: GYP)
@ -93,6 +99,7 @@ endif
# - every combination <arch>.<mode>, e.g. "ia32.release" # - every combination <arch>.<mode>, e.g. "ia32.release"
# - "native": current host's architecture, release mode # - "native": current host's architecture, release mode
# - any of the above with .check appended, e.g. "ia32.release.check" # - any of the above with .check appended, e.g. "ia32.release.check"
# - "android": cross-compile for Android/ARM (release mode)
# - default (no target specified): build all DEFAULT_ARCHES and MODES # - default (no target specified): build all DEFAULT_ARCHES and MODES
# - "check": build all targets and run all tests # - "check": build all targets and run all tests
# - "<arch>.clean" for any <arch> in ARCHES # - "<arch>.clean" for any <arch> in ARCHES
@ -120,7 +127,8 @@ ENVFILE = $(OUTDIR)/environment
.PHONY: all check clean dependencies $(ENVFILE).new native \ .PHONY: all check clean dependencies $(ENVFILE).new native \
$(ARCHES) $(MODES) $(BUILDS) $(CHECKS) $(addsuffix .clean,$(ARCHES)) \ $(ARCHES) $(MODES) $(BUILDS) $(CHECKS) $(addsuffix .clean,$(ARCHES)) \
$(addsuffix .check,$(MODES)) $(addsuffix .check,$(ARCHES)) $(addsuffix .check,$(MODES)) $(addsuffix .check,$(ARCHES)) \
must-set-ANDROID_NDK_ROOT
# Target definitions. "all" is the default. # Target definitions. "all" is the default.
all: $(MODES) all: $(MODES)
@ -144,6 +152,18 @@ native: $(OUTDIR)/Makefile-native
CXX="$(CXX)" LINK="$(LINK)" BUILDTYPE=Release \ CXX="$(CXX)" LINK="$(LINK)" BUILDTYPE=Release \
builddir="$(shell pwd)/$(OUTDIR)/$@" builddir="$(shell pwd)/$(OUTDIR)/$@"
# TODO(jkummerow): add "android.debug" when we need it.
android android.release: $(OUTDIR)/Makefile-android
@$(MAKE) -C "$(OUTDIR)" -f Makefile-android \
CXX="$(ANDROID_TOOL_PREFIX)-g++" \
AR="$(ANDROID_TOOL_PREFIX)-ar" \
RANLIB="$(ANDROID_TOOL_PREFIX)-ranlib" \
CC="$(ANDROID_TOOL_PREFIX)-gcc" \
LD="$(ANDROID_TOOL_PREFIX)-ld" \
LINK="$(ANDROID_TOOL_PREFIX)-g++" \
BUILDTYPE=Release \
builddir="$(shell pwd)/$(OUTDIR)/android.release"
# Test targets. # Test targets.
check: all check: all
@tools/test-wrapper-gypbuild.py $(TESTJOBS) --outdir=$(OUTDIR) \ @tools/test-wrapper-gypbuild.py $(TESTJOBS) --outdir=$(OUTDIR) \
@ -178,6 +198,11 @@ native.clean:
rm -rf $(OUTDIR)/native rm -rf $(OUTDIR)/native
find $(OUTDIR) -regex '.*\(host\|target\)-native\.mk' -delete find $(OUTDIR) -regex '.*\(host\|target\)-native\.mk' -delete
android.clean:
rm -f $(OUTDIR)/Makefile-android
rm -rf $(OUTDIR)/android.release
find $(OUTDIR) -regex '.*\(host\|target\)-android\.mk' -delete
clean: $(addsuffix .clean,$(ARCHES)) native.clean clean: $(addsuffix .clean,$(ARCHES)) native.clean
# GYP file generation targets. # GYP file generation targets.
@ -205,6 +230,18 @@ $(OUTDIR)/Makefile-native: $(GYPFILES) $(ENVFILE)
build/gyp/gyp --generator-output="$(OUTDIR)" build/all.gyp \ build/gyp/gyp --generator-output="$(OUTDIR)" build/all.gyp \
-Ibuild/standalone.gypi --depth=. -S-native $(GYPFLAGS) -Ibuild/standalone.gypi --depth=. -S-native $(GYPFLAGS)
$(OUTDIR)/Makefile-android: $(GYPFILES) $(ENVFILE) build/android.gypi \
must-set-ANDROID_NDK_ROOT
CC="${ANDROID_TOOL_PREFIX}-gcc" \
build/gyp/gyp --generator-output="$(OUTDIR)" build/all.gyp \
-Ibuild/standalone.gypi --depth=. -Ibuild/android.gypi \
-S-android $(GYPFLAGS)
must-set-ANDROID_NDK_ROOT:
ifndef ANDROID_NDK_ROOT
$(error ANDROID_NDK_ROOT is not set)
endif
# Replaces the old with the new environment file if they're different, which # Replaces the old with the new environment file if they're different, which
# will trigger GYP to regenerate Makefiles. # will trigger GYP to regenerate Makefiles.
$(ENVFILE): $(ENVFILE).new $(ENVFILE): $(ENVFILE).new

17
deps/v8/SConstruct

@ -33,6 +33,7 @@ import os
from os.path import join, dirname, abspath from os.path import join, dirname, abspath
from types import DictType, StringTypes from types import DictType, StringTypes
root_dir = dirname(File('SConstruct').rfile().abspath) root_dir = dirname(File('SConstruct').rfile().abspath)
src_dir = join(root_dir, 'src')
sys.path.insert(0, join(root_dir, 'tools')) sys.path.insert(0, join(root_dir, 'tools'))
import js2c, utils import js2c, utils
@ -53,7 +54,7 @@ GCC_DTOA_EXTRA_CCFLAGS = []
LIBRARY_FLAGS = { LIBRARY_FLAGS = {
'all': { 'all': {
'CPPPATH': [join(root_dir, 'src')], 'CPPPATH': [src_dir],
'regexp:interpreted': { 'regexp:interpreted': {
'CPPDEFINES': ['V8_INTERPRETED_REGEXP'] 'CPPDEFINES': ['V8_INTERPRETED_REGEXP']
}, },
@ -111,13 +112,13 @@ LIBRARY_FLAGS = {
} }
}, },
'os:freebsd': { 'os:freebsd': {
'CPPPATH' : ['/usr/local/include'], 'CPPPATH' : [src_dir, '/usr/local/include'],
'LIBPATH' : ['/usr/local/lib'], 'LIBPATH' : ['/usr/local/lib'],
'CCFLAGS': ['-ansi'], 'CCFLAGS': ['-ansi'],
'LIBS': ['execinfo'] 'LIBS': ['execinfo']
}, },
'os:openbsd': { 'os:openbsd': {
'CPPPATH' : ['/usr/local/include'], 'CPPPATH' : [src_dir, '/usr/local/include'],
'LIBPATH' : ['/usr/local/lib'], 'LIBPATH' : ['/usr/local/lib'],
'CCFLAGS': ['-ansi'], 'CCFLAGS': ['-ansi'],
}, },
@ -125,12 +126,12 @@ LIBRARY_FLAGS = {
# On Solaris, to get isinf, INFINITY, fpclassify and other macros one # On Solaris, to get isinf, INFINITY, fpclassify and other macros one
# needs to define __C99FEATURES__. # needs to define __C99FEATURES__.
'CPPDEFINES': ['__C99FEATURES__'], 'CPPDEFINES': ['__C99FEATURES__'],
'CPPPATH' : ['/usr/local/include'], 'CPPPATH' : [src_dir, '/usr/local/include'],
'LIBPATH' : ['/usr/local/lib'], 'LIBPATH' : ['/usr/local/lib'],
'CCFLAGS': ['-ansi'], 'CCFLAGS': ['-ansi'],
}, },
'os:netbsd': { 'os:netbsd': {
'CPPPATH' : ['/usr/pkg/include'], 'CPPPATH' : [src_dir, '/usr/pkg/include'],
'LIBPATH' : ['/usr/pkg/lib'], 'LIBPATH' : ['/usr/pkg/lib'],
}, },
'os:win32': { 'os:win32': {
@ -403,7 +404,7 @@ DTOA_EXTRA_FLAGS = {
CCTEST_EXTRA_FLAGS = { CCTEST_EXTRA_FLAGS = {
'all': { 'all': {
'CPPPATH': [join(root_dir, 'src')], 'CPPPATH': [src_dir],
'library:shared': { 'library:shared': {
'CPPDEFINES': ['USING_V8_SHARED'] 'CPPDEFINES': ['USING_V8_SHARED']
}, },
@ -460,7 +461,7 @@ CCTEST_EXTRA_FLAGS = {
SAMPLE_FLAGS = { SAMPLE_FLAGS = {
'all': { 'all': {
'CPPPATH': [join(abspath('.'), 'include')], 'CPPPATH': [join(root_dir, 'include')],
'library:shared': { 'library:shared': {
'CPPDEFINES': ['USING_V8_SHARED'] 'CPPDEFINES': ['USING_V8_SHARED']
}, },
@ -643,7 +644,7 @@ SAMPLE_FLAGS = {
PREPARSER_FLAGS = { PREPARSER_FLAGS = {
'all': { 'all': {
'CPPPATH': [join(abspath('.'), 'include'), join(abspath('.'), 'src')], 'CPPPATH': [join(root_dir, 'include'), src_dir],
'library:shared': { 'library:shared': {
'CPPDEFINES': ['USING_V8_SHARED'] 'CPPDEFINES': ['USING_V8_SHARED']
}, },

225
deps/v8/build/android.gypi

@ -0,0 +1,225 @@
# Copyright 2012 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.
# Definitions for building standalone V8 binaries to run on Android.
# This is mostly excerpted from:
# http://src.chromium.org/viewvc/chrome/trunk/src/build/common.gypi
{
'variables': {
# Location of Android NDK.
'variables': {
'variables': {
'android_ndk_root%': '<!(/bin/echo -n $ANDROID_NDK_ROOT)',
'android_target_arch%': 'arm', # target_arch in android terms.
# Switch between different build types, currently only '0' is
# supported.
'android_build_type%': 0,
},
'android_ndk_root%': '<(android_ndk_root)',
'android_ndk_sysroot': '<(android_ndk_root)/platforms/android-9/arch-<(android_target_arch)',
'android_build_type%': '<(android_build_type)',
},
'android_ndk_root%': '<(android_ndk_root)',
'android_ndk_sysroot': '<(android_ndk_sysroot)',
'android_ndk_include': '<(android_ndk_sysroot)/usr/include',
'android_ndk_lib': '<(android_ndk_sysroot)/usr/lib',
# Enable to use the system stlport, otherwise statically
# link the NDK one?
'use_system_stlport%': '<(android_build_type)',
'android_stlport_library': 'stlport_static',
# Copy it out one scope.
'android_build_type%': '<(android_build_type)',
'OS': 'android',
'target_arch': 'arm',
'v8_target_arch': 'arm',
'armv7': 1,
'arm_neon': 0,
'arm_fpu': 'vfpv3',
}, # variables
'target_defaults': {
'defines': [
'ANDROID',
'V8_ANDROID_LOG_STDOUT',
],
'configurations': {
'Release': {
'cflags!': [
'-O2',
'-Os',
],
'cflags': [
'-fdata-sections',
'-ffunction-sections',
'-fomit-frame-pointer',
'-O3',
],
}, # Release
}, # configurations
'cflags': [ '-Wno-abi', '-Wall', '-W', '-Wno-unused-parameter',
'-Wnon-virtual-dtor', '-fno-rtti', '-fno-exceptions', ],
'target_conditions': [
['_toolset=="target"', {
'cflags!': [
'-pthread', # Not supported by Android toolchain.
],
'cflags': [
'-U__linux__', # Don't allow toolchain to claim -D__linux__
'-ffunction-sections',
'-funwind-tables',
'-fstack-protector',
'-fno-short-enums',
'-finline-limit=64',
'-Wa,--noexecstack',
'-Wno-error=non-virtual-dtor', # TODO(michaelbai): Fix warnings.
# Note: This include is in cflags to ensure that it comes after
# all of the includes.
'-I<(android_ndk_include)',
'-march=armv7-a',
'-mtune=cortex-a8',
'-mfpu=vfp3',
],
'defines': [
'ANDROID',
#'__GNU_SOURCE=1', # Necessary for clone()
'USE_STLPORT=1',
'_STLP_USE_PTR_SPECIALIZATIONS=1',
'HAVE_OFF64_T',
'HAVE_SYS_UIO_H',
'ANDROID_BINSIZE_HACK', # Enable temporary hacks to reduce binsize.
],
'ldflags!': [
'-pthread', # Not supported by Android toolchain.
],
'ldflags': [
'-nostdlib',
'-Wl,--no-undefined',
'-Wl,--icf=safe', # Enable identical code folding to reduce size
# Don't export symbols from statically linked libraries.
'-Wl,--exclude-libs=ALL',
],
'libraries!': [
'-lrt', # librt is built into Bionic.
# Not supported by Android toolchain.
# Where do these come from? Can't find references in
# any Chromium gyp or gypi file. Maybe they come from
# gyp itself?
'-lpthread', '-lnss3', '-lnssutil3', '-lsmime3', '-lplds4', '-lplc4', '-lnspr4',
],
'libraries': [
'-l<(android_stlport_library)',
# Manually link the libgcc.a that the cross compiler uses.
'<!($CC -print-libgcc-file-name)',
'-lc',
'-ldl',
'-lstdc++',
'-lm',
],
'conditions': [
['android_build_type==0', {
'ldflags': [
'-Wl,-rpath-link=<(android_ndk_lib)',
'-L<(android_ndk_lib)',
],
}],
# NOTE: The stlport header include paths below are specified in
# cflags rather than include_dirs because they need to come
# after include_dirs. Think of them like system headers, but
# don't use '-isystem' because the arm-linux-androideabi-4.4.3
# toolchain (circa Gingerbread) will exhibit strange errors.
# The include ordering here is important; change with caution.
['use_system_stlport==0', {
'cflags': [
'-I<(android_ndk_root)/sources/cxx-stl/stlport/stlport',
],
'conditions': [
['target_arch=="arm" and armv7==1', {
'ldflags': [
'-L<(android_ndk_root)/sources/cxx-stl/stlport/libs/armeabi-v7a',
],
}],
['target_arch=="arm" and armv7==0', {
'ldflags': [
'-L<(android_ndk_root)/sources/cxx-stl/stlport/libs/armeabi',
],
}],
['target_arch=="ia32"', {
'ldflags': [
'-L<(android_ndk_root)/sources/cxx-stl/stlport/libs/x86',
],
}],
],
}],
['target_arch=="ia32"', {
# The x86 toolchain currently has problems with stack-protector.
'cflags!': [
'-fstack-protector',
],
'cflags': [
'-fno-stack-protector',
],
}],
],
'target_conditions': [
['_type=="executable"', {
'ldflags': [
'-Bdynamic',
'-Wl,-dynamic-linker,/system/bin/linker',
'-Wl,--gc-sections',
'-Wl,-z,nocopyreloc',
# crtbegin_dynamic.o should be the last item in ldflags.
'<(android_ndk_lib)/crtbegin_dynamic.o',
],
'libraries': [
# crtend_android.o needs to be the last item in libraries.
# Do not add any libraries after this!
'<(android_ndk_lib)/crtend_android.o',
],
}],
['_type=="shared_library"', {
'ldflags': [
'-Wl,-shared,-Bsymbolic',
],
}],
],
}], # _toolset=="target"
# Settings for building host targets using the system toolchain.
['_toolset=="host"', {
'cflags': [ '-m32', '-pthread' ],
'ldflags': [ '-m32', '-pthread' ],
'ldflags!': [
'-Wl,-z,noexecstack',
'-Wl,--gc-sections',
'-Wl,-O1',
'-Wl,--as-needed',
],
}],
], # target_conditions
}, # target_defaults
}

32
deps/v8/build/common.gypi

@ -73,6 +73,9 @@
# Enable profiling support. Only required on Windows. # Enable profiling support. Only required on Windows.
'v8_enable_prof%': 0, 'v8_enable_prof%': 0,
# Some versions of GCC 4.5 seem to need -fno-strict-aliasing.
'v8_no_strict_aliasing%': 0,
# Chrome needs this definition unconditionally. For standalone V8 builds, # Chrome needs this definition unconditionally. For standalone V8 builds,
# it's handled in build/standalone.gypi. # it's handled in build/standalone.gypi.
'want_separate_host_toolset%': 1, 'want_separate_host_toolset%': 1,
@ -208,6 +211,11 @@
'COMPRESS_STARTUP_DATA_BZ2', 'COMPRESS_STARTUP_DATA_BZ2',
], ],
}], }],
['OS=="win"', {
'defines': [
'WIN32',
],
}],
['OS=="win" and v8_enable_prof==1', { ['OS=="win" and v8_enable_prof==1', {
'msvs_settings': { 'msvs_settings': {
'VCLinkerTool': { 'VCLinkerTool': {
@ -222,12 +230,15 @@
'cflags': [ '-m32' ], 'cflags': [ '-m32' ],
'ldflags': [ '-m32' ], 'ldflags': [ '-m32' ],
}], }],
], [ 'v8_no_strict_aliasing==1', {
'cflags': [ '-fno-strict-aliasing' ],
}],
], # conditions
}], }],
['OS=="solaris"', { ['OS=="solaris"', {
'defines': [ '__C99FEATURES__=1' ], # isinf() etc. 'defines': [ '__C99FEATURES__=1' ], # isinf() etc.
}], }],
], ], # conditions
'configurations': { 'configurations': {
'Debug': { 'Debug': {
'defines': [ 'defines': [
@ -268,10 +279,11 @@
'-Wnon-virtual-dtor' ], '-Wnon-virtual-dtor' ],
}], }],
], ],
}, }, # Debug
'Release': { 'Release': {
'conditions': [ 'conditions': [
['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd"', { ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd" \
or OS=="android"', {
'cflags!': [ 'cflags!': [
'-O2', '-O2',
'-Os', '-Os',
@ -307,7 +319,7 @@
# is specified explicitly. # is specified explicitly.
'GCC_STRICT_ALIASING': 'YES', 'GCC_STRICT_ALIASING': 'YES',
}, },
}], }], # OS=="mac"
['OS=="win"', { ['OS=="win"', {
'msvs_configuration_attributes': { 'msvs_configuration_attributes': {
'IntermediateDirectory': '$(OutDir)\\obj\\$(ProjectName)', 'IntermediateDirectory': '$(OutDir)\\obj\\$(ProjectName)',
@ -341,9 +353,9 @@
# 'StackReserveSize': '297152', # 'StackReserveSize': '297152',
}, },
}, },
}], }], # OS=="win"
], ], # conditions
}, }, # Release
}, }, # configurations
}, }, # target_defaults
} }

1
deps/v8/build/standalone.gypi

@ -106,7 +106,6 @@
['OS=="win"', { ['OS=="win"', {
'target_defaults': { 'target_defaults': {
'defines': [ 'defines': [
'WIN32',
'_CRT_SECURE_NO_DEPRECATE', '_CRT_SECURE_NO_DEPRECATE',
'_CRT_NONSTDC_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE',
], ],

1
deps/v8/src/api.cc

@ -741,6 +741,7 @@ void Context::Exit() {
i::Context* last_context = i::Context* last_context =
isolate->handle_scope_implementer()->RestoreContext(); isolate->handle_scope_implementer()->RestoreContext();
isolate->set_context(last_context); isolate->set_context(last_context);
isolate->set_context_exit_happened(true);
} }

8
deps/v8/src/arm/code-stubs-arm.cc

@ -5821,7 +5821,7 @@ void SubStringStub::Generate(MacroAssembler* masm) {
__ b(eq, &return_r0); __ b(eq, &return_r0);
Label result_longer_than_two; Label result_longer_than_two;
// Check for special case of two character ascii string, in which case // Check for special case of two character ASCII string, in which case
// we do a lookup in the symbol table first. // we do a lookup in the symbol table first.
__ cmp(r2, Operand(2)); __ cmp(r2, Operand(2));
__ b(gt, &result_longer_than_two); __ b(gt, &result_longer_than_two);
@ -5951,7 +5951,7 @@ void SubStringStub::Generate(MacroAssembler* masm) {
__ tst(r1, Operand(kStringEncodingMask)); __ tst(r1, Operand(kStringEncodingMask));
__ b(eq, &two_byte_sequential); __ b(eq, &two_byte_sequential);
// Allocate and copy the resulting ascii string. // Allocate and copy the resulting ASCII string.
__ AllocateAsciiString(r0, r2, r4, r6, r7, &runtime); __ AllocateAsciiString(r0, r2, r4, r6, r7, &runtime);
// Locate first character of substring to copy. // Locate first character of substring to copy.
@ -6268,7 +6268,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
__ bind(&longer_than_two); __ bind(&longer_than_two);
// Check if resulting string will be flat. // Check if resulting string will be flat.
__ cmp(r6, Operand(String::kMinNonFlatLength)); __ cmp(r6, Operand(ConsString::kMinLength));
__ b(lt, &string_add_flat_result); __ b(lt, &string_add_flat_result);
// Handle exceptionally long strings in the runtime system. // Handle exceptionally long strings in the runtime system.
STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0); STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0);
@ -6322,7 +6322,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
__ jmp(&allocated); __ jmp(&allocated);
// We cannot encounter sliced strings or cons strings here since: // We cannot encounter sliced strings or cons strings here since:
STATIC_ASSERT(SlicedString::kMinLength >= String::kMinNonFlatLength); STATIC_ASSERT(SlicedString::kMinLength >= ConsString::kMinLength);
// Handle creating a flat result from either external or sequential strings. // Handle creating a flat result from either external or sequential strings.
// Locate the first characters' locations. // Locate the first characters' locations.
// r0: first string // r0: first string

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

@ -573,13 +573,13 @@ class Instruction {
// The naming of these accessor corresponds to figure A3-1. // The naming of these accessor corresponds to figure A3-1.
// //
// Two kind of accessors are declared: // Two kind of accessors are declared:
// - <Name>Field() will return the raw field, ie the field's bits at their // - <Name>Field() will return the raw field, i.e. the field's bits at their
// original place in the instruction encoding. // original place in the instruction encoding.
// eg. if instr is the 'addgt r0, r1, r2' instruction, encoded as 0xC0810002 // e.g. if instr is the 'addgt r0, r1, r2' instruction, encoded as
// ConditionField(instr) will return 0xC0000000. // 0xC0810002 ConditionField(instr) will return 0xC0000000.
// - <Name>Value() will return the field value, shifted back to bit 0. // - <Name>Value() will return the field value, shifted back to bit 0.
// eg. if instr is the 'addgt r0, r1, r2' instruction, encoded as 0xC0810002 // e.g. if instr is the 'addgt r0, r1, r2' instruction, encoded as
// ConditionField(instr) will return 0xC. // 0xC0810002 ConditionField(instr) will return 0xC.
// Generally applicable fields // Generally applicable fields

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

@ -473,7 +473,7 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
return 1; return 1;
} }
case 'i': { // 'i: immediate value from adjacent bits. case 'i': { // 'i: immediate value from adjacent bits.
// Expects tokens in the form imm%02d@%02d, ie. imm05@07, imm10@16 // Expects tokens in the form imm%02d@%02d, i.e. imm05@07, imm10@16
int width = (format[3] - '0') * 10 + (format[4] - '0'); int width = (format[3] - '0') * 10 + (format[4] - '0');
int lsb = (format[6] - '0') * 10 + (format[7] - '0'); int lsb = (format[6] - '0') * 10 + (format[7] - '0');

6
deps/v8/src/arm/full-codegen-arm.cc

@ -115,7 +115,7 @@ class JumpPatchSite BASE_EMBEDDED {
// function. // function.
// //
// The live registers are: // The live registers are:
// o r1: the JS function object being called (ie, ourselves) // o r1: the JS function object being called (i.e., ourselves)
// o cp: our context // o cp: our context
// o fp: our caller's frame pointer // o fp: our caller's frame pointer
// o sp: stack pointer // o sp: stack pointer
@ -3618,7 +3618,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
// One-character separator case // One-character separator case
__ bind(&one_char_separator); __ bind(&one_char_separator);
// Replace separator with its ascii character value. // Replace separator with its ASCII character value.
__ ldrb(separator, FieldMemOperand(separator, SeqAsciiString::kHeaderSize)); __ ldrb(separator, FieldMemOperand(separator, SeqAsciiString::kHeaderSize));
// Jump into the loop after the code that copies the separator, so the first // Jump into the loop after the code that copies the separator, so the first
// element is not preceded by a separator // element is not preceded by a separator
@ -3629,7 +3629,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
// result_pos: the position to which we are currently copying characters. // result_pos: the position to which we are currently copying characters.
// element: Current array element. // element: Current array element.
// elements_end: Array end. // elements_end: Array end.
// separator: Single separator ascii char (in lower byte). // separator: Single separator ASCII char (in lower byte).
// Copy the separator character to the result. // Copy the separator character to the result.
__ strb(separator, MemOperand(result_pos, 1, PostIndex)); __ strb(separator, MemOperand(result_pos, 1, PostIndex));

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

@ -1031,14 +1031,25 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ mov(r3, Operand(r2, ASR, KeyedLookupCache::kMapHashShift)); __ mov(r3, Operand(r2, ASR, KeyedLookupCache::kMapHashShift));
__ ldr(r4, FieldMemOperand(r0, String::kHashFieldOffset)); __ ldr(r4, FieldMemOperand(r0, String::kHashFieldOffset));
__ eor(r3, r3, Operand(r4, ASR, String::kHashShift)); __ eor(r3, r3, Operand(r4, ASR, String::kHashShift));
__ And(r3, r3, Operand(KeyedLookupCache::kCapacityMask)); int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask;
__ And(r3, r3, Operand(mask));
// Load the key (consisting of map and symbol) from the cache and // Load the key (consisting of map and symbol) from the cache and
// check for match. // check for match.
Label try_second_entry, hit_on_first_entry, load_in_object_property;
ExternalReference cache_keys = ExternalReference cache_keys =
ExternalReference::keyed_lookup_cache_keys(isolate); ExternalReference::keyed_lookup_cache_keys(isolate);
__ mov(r4, Operand(cache_keys)); __ mov(r4, Operand(cache_keys));
__ add(r4, r4, Operand(r3, LSL, kPointerSizeLog2 + 1)); __ add(r4, r4, Operand(r3, LSL, kPointerSizeLog2 + 1));
// Move r4 to second entry.
__ ldr(r5, MemOperand(r4, kPointerSize * 2, PostIndex));
__ cmp(r2, r5);
__ b(ne, &try_second_entry);
__ ldr(r5, MemOperand(r4, -kPointerSize)); // Load symbol
__ cmp(r0, r5);
__ b(eq, &hit_on_first_entry);
__ bind(&try_second_entry);
__ ldr(r5, MemOperand(r4, kPointerSize, PostIndex)); // Move r4 to symbol. __ ldr(r5, MemOperand(r4, kPointerSize, PostIndex)); // Move r4 to symbol.
__ cmp(r2, r5); __ cmp(r2, r5);
__ b(ne, &slow); __ b(ne, &slow);
@ -1053,6 +1064,18 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
// r3 : lookup cache index // r3 : lookup cache index
ExternalReference cache_field_offsets = ExternalReference cache_field_offsets =
ExternalReference::keyed_lookup_cache_field_offsets(isolate); ExternalReference::keyed_lookup_cache_field_offsets(isolate);
// Hit on second entry.
__ mov(r4, Operand(cache_field_offsets));
__ add(r3, r3, Operand(1));
__ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2));
__ ldrb(r6, FieldMemOperand(r2, Map::kInObjectPropertiesOffset));
__ sub(r5, r5, r6, SetCC);
__ b(ge, &property_array_property);
__ jmp(&load_in_object_property);
// Hit on first entry.
__ bind(&hit_on_first_entry);
__ mov(r4, Operand(cache_field_offsets)); __ mov(r4, Operand(cache_field_offsets));
__ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2)); __ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2));
__ ldrb(r6, FieldMemOperand(r2, Map::kInObjectPropertiesOffset)); __ ldrb(r6, FieldMemOperand(r2, Map::kInObjectPropertiesOffset));
@ -1060,6 +1083,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ b(ge, &property_array_property); __ b(ge, &property_array_property);
// Load in-object property. // Load in-object property.
__ bind(&load_in_object_property);
__ ldrb(r6, FieldMemOperand(r2, Map::kInstanceSizeOffset)); __ ldrb(r6, FieldMemOperand(r2, Map::kInstanceSizeOffset));
__ add(r6, r6, r5); // Index from start of object. __ add(r6, r6, r5); // Index from start of object.
__ sub(r1, r1, Operand(kHeapObjectTag)); // Remove the heap tag. __ sub(r1, r1, Operand(kHeapObjectTag)); // Remove the heap tag.

58
deps/v8/src/arm/lithium-codegen-arm.cc

@ -262,7 +262,7 @@ bool LCodeGen::GenerateDeferredCode() {
bool LCodeGen::GenerateDeoptJumpTable() { bool LCodeGen::GenerateDeoptJumpTable() {
// Check that the jump table is accessible from everywhere in the function // Check that the jump table is accessible from everywhere in the function
// code, ie that offsets to the table can be encoded in the 24bit signed // code, i.e. that offsets to the table can be encoded in the 24bit signed
// immediate of a branch instruction. // immediate of a branch instruction.
// To simplify we consider the code size from the first instruction to the // To simplify we consider the code size from the first instruction to the
// end of the jump table. We also don't consider the pc load delta. // end of the jump table. We also don't consider the pc load delta.
@ -2387,7 +2387,7 @@ void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
Handle<String> name) { Handle<String> name) {
LookupResult lookup(isolate()); LookupResult lookup(isolate());
type->LookupInDescriptors(NULL, *name, &lookup); type->LookupInDescriptors(NULL, *name, &lookup);
ASSERT(lookup.IsProperty() && ASSERT(lookup.IsFound() &&
(lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION)); (lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION));
if (lookup.type() == FIELD) { if (lookup.type() == FIELD) {
int index = lookup.GetLocalFieldIndexFromMap(*type); int index = lookup.GetLocalFieldIndexFromMap(*type);
@ -2828,7 +2828,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
this, pointers, Safepoint::kLazyDeopt); this, pointers, Safepoint::kLazyDeopt);
// The number of arguments is stored in receiver which is r0, as expected // The number of arguments is stored in receiver which is r0, as expected
// by InvokeFunction. // by InvokeFunction.
v8::internal::ParameterCount actual(receiver); ParameterCount actual(receiver);
__ InvokeFunction(function, actual, CALL_FUNCTION, __ InvokeFunction(function, actual, CALL_FUNCTION,
safepoint_generator, CALL_AS_METHOD); safepoint_generator, CALL_AS_METHOD);
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
@ -2883,31 +2883,41 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
int arity, int arity,
LInstruction* instr, LInstruction* instr,
CallKind call_kind) { CallKind call_kind) {
// Change context if needed. bool can_invoke_directly = !function->NeedsArgumentsAdaption() ||
bool change_context = function->shared()->formal_parameter_count() == arity;
(info()->closure()->context() != function->context()) ||
scope()->contains_with() ||
(scope()->num_heap_slots() > 0);
if (change_context) {
__ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
}
// Set r0 to arguments count if adaption is not needed. Assumes that r0
// is available to write to at this point.
if (!function->NeedsArgumentsAdaption()) {
__ mov(r0, Operand(arity));
}
LPointerMap* pointers = instr->pointer_map(); LPointerMap* pointers = instr->pointer_map();
RecordPosition(pointers->position()); RecordPosition(pointers->position());
// Invoke function. if (can_invoke_directly) {
__ SetCallKind(r5, call_kind); __ LoadHeapObject(r1, function);
__ ldr(ip, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); // Change context if needed.
__ Call(ip); bool change_context =
(info()->closure()->context() != function->context()) ||
scope()->contains_with() ||
(scope()->num_heap_slots() > 0);
if (change_context) {
__ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
}
// Set up deoptimization. // Set r0 to arguments count if adaption is not needed. Assumes that r0
RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); // is available to write to at this point.
if (!function->NeedsArgumentsAdaption()) {
__ mov(r0, Operand(arity));
}
// Invoke function.
__ SetCallKind(r5, call_kind);
__ ldr(ip, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
__ Call(ip);
// Set up deoptimization.
RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
} else {
SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
ParameterCount count(arity);
__ InvokeFunction(function, count, CALL_FUNCTION, generator, call_kind);
}
// Restore context. // Restore context.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
@ -2916,7 +2926,6 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
ASSERT(ToRegister(instr->result()).is(r0)); ASSERT(ToRegister(instr->result()).is(r0));
__ LoadHeapObject(r1, instr->function());
CallKnownFunction(instr->function(), CallKnownFunction(instr->function(),
instr->arity(), instr->arity(),
instr, instr,
@ -3351,7 +3360,6 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
ASSERT(ToRegister(instr->result()).is(r0)); ASSERT(ToRegister(instr->result()).is(r0));
__ LoadHeapObject(r1, instr->target());
CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION); CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
} }

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

@ -957,10 +957,12 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
Handle<Code> code_constant, Handle<Code> code_constant,
Register code_reg, Register code_reg,
Label* done, Label* done,
bool* definitely_mismatches,
InvokeFlag flag, InvokeFlag flag,
const CallWrapper& call_wrapper, const CallWrapper& call_wrapper,
CallKind call_kind) { CallKind call_kind) {
bool definitely_matches = false; bool definitely_matches = false;
*definitely_mismatches = false;
Label regular_invoke; Label regular_invoke;
// Check whether the expected and actual arguments count match. If not, // Check whether the expected and actual arguments count match. If not,
@ -991,6 +993,7 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
// arguments. // arguments.
definitely_matches = true; definitely_matches = true;
} else { } else {
*definitely_mismatches = true;
mov(r2, Operand(expected.immediate())); mov(r2, Operand(expected.immediate()));
} }
} }
@ -1018,7 +1021,9 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
SetCallKind(r5, call_kind); SetCallKind(r5, call_kind);
Call(adaptor); Call(adaptor);
call_wrapper.AfterCall(); call_wrapper.AfterCall();
b(done); if (!*definitely_mismatches) {
b(done);
}
} else { } else {
SetCallKind(r5, call_kind); SetCallKind(r5, call_kind);
Jump(adaptor, RelocInfo::CODE_TARGET); Jump(adaptor, RelocInfo::CODE_TARGET);
@ -1038,23 +1043,26 @@ void MacroAssembler::InvokeCode(Register code,
ASSERT(flag == JUMP_FUNCTION || has_frame()); ASSERT(flag == JUMP_FUNCTION || has_frame());
Label done; Label done;
bool definitely_mismatches = false;
InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag, InvokePrologue(expected, actual, Handle<Code>::null(), code,
&done, &definitely_mismatches, flag,
call_wrapper, call_kind); call_wrapper, call_kind);
if (flag == CALL_FUNCTION) { if (!definitely_mismatches) {
call_wrapper.BeforeCall(CallSize(code)); if (flag == CALL_FUNCTION) {
SetCallKind(r5, call_kind); call_wrapper.BeforeCall(CallSize(code));
Call(code); SetCallKind(r5, call_kind);
call_wrapper.AfterCall(); Call(code);
} else { call_wrapper.AfterCall();
ASSERT(flag == JUMP_FUNCTION); } else {
SetCallKind(r5, call_kind); ASSERT(flag == JUMP_FUNCTION);
Jump(code); SetCallKind(r5, call_kind);
} Jump(code);
}
// Continue here if InvokePrologue does handle the invocation due to // Continue here if InvokePrologue does handle the invocation due to
// mismatched parameter counts. // mismatched parameter counts.
bind(&done); bind(&done);
}
} }
@ -1068,20 +1076,23 @@ void MacroAssembler::InvokeCode(Handle<Code> code,
ASSERT(flag == JUMP_FUNCTION || has_frame()); ASSERT(flag == JUMP_FUNCTION || has_frame());
Label done; Label done;
bool definitely_mismatches = false;
InvokePrologue(expected, actual, code, no_reg, &done, flag, InvokePrologue(expected, actual, code, no_reg,
&done, &definitely_mismatches, flag,
NullCallWrapper(), call_kind); NullCallWrapper(), call_kind);
if (flag == CALL_FUNCTION) { if (!definitely_mismatches) {
SetCallKind(r5, call_kind); if (flag == CALL_FUNCTION) {
Call(code, rmode); SetCallKind(r5, call_kind);
} else { Call(code, rmode);
SetCallKind(r5, call_kind); } else {
Jump(code, rmode); SetCallKind(r5, call_kind);
} Jump(code, rmode);
}
// Continue here if InvokePrologue does handle the invocation due to // Continue here if InvokePrologue does handle the invocation due to
// mismatched parameter counts. // mismatched parameter counts.
bind(&done); bind(&done);
}
} }
@ -1116,6 +1127,7 @@ void MacroAssembler::InvokeFunction(Register fun,
void MacroAssembler::InvokeFunction(Handle<JSFunction> function, void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
const ParameterCount& actual, const ParameterCount& actual,
InvokeFlag flag, InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind) { CallKind call_kind) {
// You can't call a function without a valid frame. // You can't call a function without a valid frame.
ASSERT(flag == JUMP_FUNCTION || has_frame()); ASSERT(flag == JUMP_FUNCTION || has_frame());
@ -1129,7 +1141,7 @@ void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
// allow recompilation to take effect without changing any of the // allow recompilation to take effect without changing any of the
// call sites. // call sites.
ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
InvokeCode(r3, expected, actual, flag, NullCallWrapper(), call_kind); InvokeCode(r3, expected, actual, flag, call_wrapper, call_kind);
} }
@ -2387,7 +2399,7 @@ void MacroAssembler::ConvertToInt32(Register source,
b(gt, not_int32); b(gt, not_int32);
// We know the exponent is smaller than 30 (biased). If it is less than // We know the exponent is smaller than 30 (biased). If it is less than
// 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, ie // 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, i.e.
// it rounds to zero. // it rounds to zero.
const uint32_t zero_exponent = HeapNumber::kExponentBias + 0; const uint32_t zero_exponent = HeapNumber::kExponentBias + 0;
sub(scratch2, scratch2, Operand(zero_exponent - fudge_factor), SetCC); sub(scratch2, scratch2, Operand(zero_exponent - fudge_factor), SetCC);

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

@ -243,7 +243,7 @@ class MacroAssembler: public Assembler {
Register scratch3, Register scratch3,
Label* object_is_white_and_not_data); Label* object_is_white_and_not_data);
// Detects conservatively whether an object is data-only, ie it does need to // Detects conservatively whether an object is data-only, i.e. it does need to
// be scanned by the garbage collector. // be scanned by the garbage collector.
void JumpIfDataObject(Register value, void JumpIfDataObject(Register value,
Register scratch, Register scratch,
@ -539,6 +539,7 @@ class MacroAssembler: public Assembler {
void InvokeFunction(Handle<JSFunction> function, void InvokeFunction(Handle<JSFunction> function,
const ParameterCount& actual, const ParameterCount& actual,
InvokeFlag flag, InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind); CallKind call_kind);
void IsObjectJSObjectType(Register heap_object, void IsObjectJSObjectType(Register heap_object,
@ -606,7 +607,7 @@ class MacroAssembler: public Assembler {
} }
// Check if the given instruction is a 'type' marker. // Check if the given instruction is a 'type' marker.
// ie. check if is is a mov r<type>, r<type> (referenced as nop(type)) // i.e. check if is is a mov r<type>, r<type> (referenced as nop(type))
// These instructions are generated to mark special location in the code, // These instructions are generated to mark special location in the code,
// like some special IC code. // like some special IC code.
static inline bool IsMarkedCode(Instr instr, int type) { static inline bool IsMarkedCode(Instr instr, int type) {
@ -810,7 +811,7 @@ class MacroAssembler: public Assembler {
// Check if the map of an object is equal to a specified map and branch to // Check if the map of an object is equal to a specified map and branch to
// label if not. Skip the smi check if not required (object is known to be a // label if not. Skip the smi check if not required (object is known to be a
// heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
// against maps that are ElementsKind transition maps of the specificed map. // against maps that are ElementsKind transition maps of the specified map.
void CheckMap(Register obj, void CheckMap(Register obj,
Register scratch, Register scratch,
Handle<Map> map, Handle<Map> map,
@ -908,7 +909,7 @@ class MacroAssembler: public Assembler {
// Truncates a double using a specific rounding mode. // Truncates a double using a specific rounding mode.
// Clears the z flag (ne condition) if an overflow occurs. // Clears the z flag (ne condition) if an overflow occurs.
// If exact_conversion is true, the z flag is also cleared if the conversion // If exact_conversion is true, the z flag is also cleared if the conversion
// was inexact, ie. if the double value could not be converted exactly // was inexact, i.e. if the double value could not be converted exactly
// to a 32bit integer. // to a 32bit integer.
void EmitVFPTruncate(VFPRoundingMode rounding_mode, void EmitVFPTruncate(VFPRoundingMode rounding_mode,
SwVfpRegister result, SwVfpRegister result,
@ -1025,7 +1026,7 @@ class MacroAssembler: public Assembler {
// Calls an API function. Allocates HandleScope, extracts returned value // Calls an API function. Allocates HandleScope, extracts returned value
// from handle and propagates exceptions. Restores context. stack_space // from handle and propagates exceptions. Restores context. stack_space
// - space to be unwound on exit (includes the call js arguments space and // - space to be unwound on exit (includes the call JS arguments space and
// the additional space allocated for the fast call). // the additional space allocated for the fast call).
void CallApiFunctionAndReturn(ExternalReference function, int stack_space); void CallApiFunctionAndReturn(ExternalReference function, int stack_space);
@ -1248,6 +1249,7 @@ class MacroAssembler: public Assembler {
Handle<Code> code_constant, Handle<Code> code_constant,
Register code_reg, Register code_reg,
Label* done, Label* done,
bool* definitely_mismatches,
InvokeFlag flag, InvokeFlag flag,
const CallWrapper& call_wrapper, const CallWrapper& call_wrapper,
CallKind call_kind); CallKind call_kind);

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

@ -562,11 +562,11 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm,
int argc) { int argc) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- sp[0] : holder (set by CheckPrototypes) // -- sp[0] : holder (set by CheckPrototypes)
// -- sp[4] : callee js function // -- sp[4] : callee JS function
// -- sp[8] : call data // -- sp[8] : call data
// -- sp[12] : last js argument // -- sp[12] : last JS argument
// -- ... // -- ...
// -- sp[(argc + 3) * 4] : first js argument // -- sp[(argc + 3) * 4] : first JS argument
// -- sp[(argc + 4) * 4] : receiver // -- sp[(argc + 4) * 4] : receiver
// ----------------------------------- // -----------------------------------
// Get the function and setup the context. // Get the function and setup the context.
@ -583,7 +583,7 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm,
} else { } else {
__ Move(r6, call_data); __ Move(r6, call_data);
} }
// Store js function and call data. // Store JS function and call data.
__ stm(ib, sp, r5.bit() | r6.bit()); __ stm(ib, sp, r5.bit() | r6.bit());
// r2 points to call data as expected by Arguments // r2 points to call data as expected by Arguments
@ -738,7 +738,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
? CALL_AS_FUNCTION ? CALL_AS_FUNCTION
: CALL_AS_METHOD; : CALL_AS_METHOD;
__ InvokeFunction(optimization.constant_function(), arguments_, __ InvokeFunction(optimization.constant_function(), arguments_,
JUMP_FUNCTION, call_kind); JUMP_FUNCTION, NullCallWrapper(), call_kind);
} }
// Deferred code for fast API call case---clean preallocated space. // Deferred code for fast API call case---clean preallocated space.
@ -1179,7 +1179,7 @@ void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object,
// and CALLBACKS, so inline only them, other cases may be added // and CALLBACKS, so inline only them, other cases may be added
// later. // later.
bool compile_followup_inline = false; bool compile_followup_inline = false;
if (lookup->IsProperty() && lookup->IsCacheable()) { if (lookup->IsFound() && lookup->IsCacheable()) {
if (lookup->type() == FIELD) { if (lookup->type() == FIELD) {
compile_followup_inline = true; compile_followup_inline = true;
} else if (lookup->type() == CALLBACKS && } else if (lookup->type() == CALLBACKS &&
@ -1904,7 +1904,8 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
// Tail call the full function. We do not have to patch the receiver // Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it. // because the function makes no use of it.
__ bind(&slow); __ bind(&slow);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); __ InvokeFunction(
function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss); __ bind(&miss);
// r2: function name. // r2: function name.
@ -1983,7 +1984,7 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
__ vmrs(r3); __ vmrs(r3);
// Set custom FPCSR: // Set custom FPCSR:
// - Set rounding mode to "Round towards Minus Infinity" // - Set rounding mode to "Round towards Minus Infinity"
// (ie bits [23:22] = 0b10). // (i.e. bits [23:22] = 0b10).
// - Clear vfp cumulative exception flags (bits [3:0]). // - Clear vfp cumulative exception flags (bits [3:0]).
// - Make sure Flush-to-zero mode control bit is unset (bit 22). // - Make sure Flush-to-zero mode control bit is unset (bit 22).
__ bic(r9, r3, __ bic(r9, r3,
@ -2049,7 +2050,8 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
__ bind(&slow); __ bind(&slow);
// Tail call the full function. We do not have to patch the receiver // Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it. // because the function makes no use of it.
__ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); __ InvokeFunction(
function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss); __ bind(&miss);
// r2: function name. // r2: function name.
@ -2147,7 +2149,8 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
// Tail call the full function. We do not have to patch the receiver // Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it. // because the function makes no use of it.
__ bind(&slow); __ bind(&slow);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); __ InvokeFunction(
function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss); __ bind(&miss);
// r2: function name. // r2: function name.
@ -2325,7 +2328,8 @@ Handle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object,
CallKind call_kind = CallICBase::Contextual::decode(extra_state_) CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
? CALL_AS_FUNCTION ? CALL_AS_FUNCTION
: CALL_AS_METHOD; : CALL_AS_METHOD;
__ InvokeFunction(function, arguments(), JUMP_FUNCTION, call_kind); __ InvokeFunction(
function, arguments(), JUMP_FUNCTION, NullCallWrapper(), call_kind);
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);

2
deps/v8/src/array.js

@ -204,7 +204,7 @@ function ConvertToLocaleString(e) {
if (IS_NULL_OR_UNDEFINED(e)) { if (IS_NULL_OR_UNDEFINED(e)) {
return ''; return '';
} else { } else {
// According to ES5, seciton 15.4.4.3, the toLocaleString conversion // According to ES5, section 15.4.4.3, the toLocaleString conversion
// must throw a TypeError if ToObject(e).toLocaleString isn't // must throw a TypeError if ToObject(e).toLocaleString isn't
// callable. // callable.
var e_obj = ToObject(e); var e_obj = ToObject(e);

2
deps/v8/src/assembler.h

@ -271,7 +271,7 @@ class RelocInfo BASE_EMBEDDED {
INLINE(void apply(intptr_t delta)); INLINE(void apply(intptr_t delta));
// Is the pointer this relocation info refers to coded like a plain pointer // Is the pointer this relocation info refers to coded like a plain pointer
// or is it strange in some way (eg relative or patched into a series of // or is it strange in some way (e.g. relative or patched into a series of
// instructions). // instructions).
bool IsCodedSpecially(); bool IsCodedSpecially();

23
deps/v8/src/ast.cc

@ -724,17 +724,11 @@ void CaseClause::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
} }
static bool CanCallWithoutIC(Handle<JSFunction> target, int arity) {
SharedFunctionInfo* info = target->shared();
// If the number of formal parameters of the target function does
// not match the number of arguments we're passing, we don't want to
// deal with it. Otherwise, we can call it directly.
return !target->NeedsArgumentsAdaption() ||
info->formal_parameter_count() == arity;
}
bool Call::ComputeTarget(Handle<Map> type, Handle<String> name) { bool Call::ComputeTarget(Handle<Map> type, Handle<String> name) {
// If there is an interceptor, we can't compute the target for
// a direct call.
if (type->has_named_interceptor()) return false;
if (check_type_ == RECEIVER_MAP_CHECK) { if (check_type_ == RECEIVER_MAP_CHECK) {
// For primitive checks the holder is set up to point to the // For primitive checks the holder is set up to point to the
// corresponding prototype object, i.e. one step of the algorithm // corresponding prototype object, i.e. one step of the algorithm
@ -752,9 +746,9 @@ bool Call::ComputeTarget(Handle<Map> type, Handle<String> name) {
&& type->prototype()->IsJSObject()) { && type->prototype()->IsJSObject()) {
holder_ = Handle<JSObject>(JSObject::cast(type->prototype())); holder_ = Handle<JSObject>(JSObject::cast(type->prototype()));
type = Handle<Map>(holder()->map()); type = Handle<Map>(holder()->map());
} else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) { } else if (lookup.IsFound() && lookup.type() == CONSTANT_FUNCTION) {
target_ = Handle<JSFunction>(lookup.GetConstantFunctionFromMap(*type)); target_ = Handle<JSFunction>(lookup.GetConstantFunctionFromMap(*type));
return CanCallWithoutIC(target_, arguments()->length()); return true;
} else { } else {
return false; return false;
} }
@ -766,7 +760,7 @@ bool Call::ComputeGlobalTarget(Handle<GlobalObject> global,
LookupResult* lookup) { LookupResult* lookup) {
target_ = Handle<JSFunction>::null(); target_ = Handle<JSFunction>::null();
cell_ = Handle<JSGlobalPropertyCell>::null(); cell_ = Handle<JSGlobalPropertyCell>::null();
ASSERT(lookup->IsProperty() && ASSERT(lookup->IsFound() &&
lookup->type() == NORMAL && lookup->type() == NORMAL &&
lookup->holder() == *global); lookup->holder() == *global);
cell_ = Handle<JSGlobalPropertyCell>(global->GetPropertyCell(lookup)); cell_ = Handle<JSGlobalPropertyCell>(global->GetPropertyCell(lookup));
@ -774,8 +768,7 @@ bool Call::ComputeGlobalTarget(Handle<GlobalObject> global,
Handle<JSFunction> candidate(JSFunction::cast(cell_->value())); Handle<JSFunction> candidate(JSFunction::cast(cell_->value()));
// If the function is in new space we assume it's more likely to // If the function is in new space we assume it's more likely to
// change and thus prefer the general IC code. // change and thus prefer the general IC code.
if (!HEAP->InNewSpace(*candidate) && if (!HEAP->InNewSpace(*candidate)) {
CanCallWithoutIC(candidate, arguments()->length())) {
target_ = candidate; target_ = candidate;
return true; return true;
} }

2
deps/v8/src/bignum-dtoa.h

@ -44,7 +44,7 @@ enum BignumDtoaMode {
BIGNUM_DTOA_PRECISION BIGNUM_DTOA_PRECISION
}; };
// Converts the given double 'v' to ascii. // Converts the given double 'v' to ASCII.
// The result should be interpreted as buffer * 10^(point-length). // The result should be interpreted as buffer * 10^(point-length).
// The buffer will be null-terminated. // The buffer will be null-terminated.
// //

6
deps/v8/src/bootstrapper.cc

@ -1099,11 +1099,11 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
#ifdef DEBUG #ifdef DEBUG
LookupResult lookup(isolate); LookupResult lookup(isolate);
result->LocalLookup(heap->callee_symbol(), &lookup); result->LocalLookup(heap->callee_symbol(), &lookup);
ASSERT(lookup.IsProperty() && (lookup.type() == FIELD)); ASSERT(lookup.IsFound() && (lookup.type() == FIELD));
ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsCalleeIndex); ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsCalleeIndex);
result->LocalLookup(heap->length_symbol(), &lookup); result->LocalLookup(heap->length_symbol(), &lookup);
ASSERT(lookup.IsProperty() && (lookup.type() == FIELD)); ASSERT(lookup.IsFound() && (lookup.type() == FIELD));
ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsLengthIndex); ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsLengthIndex);
ASSERT(result->map()->inobject_properties() > Heap::kArgumentsCalleeIndex); ASSERT(result->map()->inobject_properties() > Heap::kArgumentsCalleeIndex);
@ -1197,7 +1197,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
#ifdef DEBUG #ifdef DEBUG
LookupResult lookup(isolate); LookupResult lookup(isolate);
result->LocalLookup(heap->length_symbol(), &lookup); result->LocalLookup(heap->length_symbol(), &lookup);
ASSERT(lookup.IsProperty() && (lookup.type() == FIELD)); ASSERT(lookup.IsFound() && (lookup.type() == FIELD));
ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsLengthIndex); ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsLengthIndex);
ASSERT(result->map()->inobject_properties() > Heap::kArgumentsLengthIndex); ASSERT(result->map()->inobject_properties() > Heap::kArgumentsLengthIndex);

2
deps/v8/src/builtins.cc

@ -411,7 +411,7 @@ static FixedArray* LeftTrimFixedArray(Heap* heap,
int size_delta = to_trim * kPointerSize; int size_delta = to_trim * kPointerSize;
if (heap->marking()->TransferMark(elms->address(), if (heap->marking()->TransferMark(elms->address(),
elms->address() + size_delta)) { elms->address() + size_delta)) {
MemoryChunk::IncrementLiveBytes(elms->address(), -size_delta); MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta);
} }
return FixedArray::cast(HeapObject::FromAddress( return FixedArray::cast(HeapObject::FromAddress(

6
deps/v8/src/d8-debug.cc

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -310,9 +310,7 @@ void RemoteDebugger::HandleKeyboardCommand(char* command) {
Handle<Value> request = Handle<Value> request =
Shell::DebugCommandToJSONRequest(String::New(command)); Shell::DebugCommandToJSONRequest(String::New(command));
if (try_catch.HasCaught()) { if (try_catch.HasCaught()) {
v8::String::Utf8Value exception(try_catch.Exception()); Shell::ReportException(&try_catch);
const char* exception_string = Shell::ToCString(exception);
printf("%s\n", exception_string);
PrintPrompt(); PrintPrompt();
return; return;
} }

37
deps/v8/src/d8-readline.cc

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -49,10 +49,14 @@ namespace v8 {
class ReadLineEditor: public LineEditor { class ReadLineEditor: public LineEditor {
public: public:
ReadLineEditor() : LineEditor(LineEditor::READLINE, "readline") { } ReadLineEditor() : LineEditor(LineEditor::READLINE, "readline") { }
virtual i::SmartArrayPointer<char> Prompt(const char* prompt); virtual Handle<String> Prompt(const char* prompt);
virtual bool Open(); virtual bool Open();
virtual bool Close(); virtual bool Close();
virtual void AddHistory(const char* str); virtual void AddHistory(const char* str);
static const char* kHistoryFileName;
static const int kMaxHistoryEntries;
private: private:
static char** AttemptedCompletion(const char* text, int start, int end); static char** AttemptedCompletion(const char* text, int start, int end);
static char* CompletionGenerator(const char* text, int state); static char* CompletionGenerator(const char* text, int state);
@ -66,25 +70,38 @@ char ReadLineEditor::kWordBreakCharacters[] = {' ', '\t', '\n', '"',
'\0'}; '\0'};
const char* ReadLineEditor::kHistoryFileName = ".d8_history";
const int ReadLineEditor::kMaxHistoryEntries = 1000;
bool ReadLineEditor::Open() { bool ReadLineEditor::Open() {
rl_initialize(); rl_initialize();
rl_attempted_completion_function = AttemptedCompletion; rl_attempted_completion_function = AttemptedCompletion;
rl_completer_word_break_characters = kWordBreakCharacters; rl_completer_word_break_characters = kWordBreakCharacters;
rl_bind_key('\t', rl_complete); rl_bind_key('\t', rl_complete);
using_history(); using_history();
stifle_history(Shell::kMaxHistoryEntries); stifle_history(kMaxHistoryEntries);
return read_history(Shell::kHistoryFileName) == 0; return read_history(kHistoryFileName) == 0;
} }
bool ReadLineEditor::Close() { bool ReadLineEditor::Close() {
return write_history(Shell::kHistoryFileName) == 0; return write_history(kHistoryFileName) == 0;
} }
i::SmartArrayPointer<char> ReadLineEditor::Prompt(const char* prompt) { Handle<String> ReadLineEditor::Prompt(const char* prompt) {
char* result = readline(prompt); char* result = NULL;
return i::SmartArrayPointer<char>(result); { // Release lock for blocking input.
Unlocker unlock(Isolate::GetCurrent());
result = readline(prompt);
}
if (result != NULL) {
AddHistory(result);
} else {
return Handle<String>();
}
return String::New(result);
} }
@ -118,10 +135,10 @@ char* ReadLineEditor::CompletionGenerator(const char* text, int state) {
static unsigned current_index; static unsigned current_index;
static Persistent<Array> current_completions; static Persistent<Array> current_completions;
if (state == 0) { if (state == 0) {
i::SmartArrayPointer<char> full_text(i::StrNDup(rl_line_buffer, rl_point));
HandleScope scope; HandleScope scope;
Local<String> full_text = String::New(rl_line_buffer, rl_point);
Handle<Array> completions = Handle<Array> completions =
Shell::GetCompletions(String::New(text), String::New(*full_text)); Shell::GetCompletions(String::New(text), full_text);
current_completions = Persistent<Array>::New(completions); current_completions = Persistent<Array>::New(completions);
current_index = 0; current_index = 0;
} }

58
deps/v8/src/d8.cc

@ -66,11 +66,7 @@
namespace v8 { namespace v8 {
#ifndef V8_SHARED
LineEditor *LineEditor::first_ = NULL; LineEditor *LineEditor::first_ = NULL;
const char* Shell::kHistoryFileName = ".d8_history";
const int Shell::kMaxHistoryEntries = 1000;
LineEditor::LineEditor(Type type, const char* name) LineEditor::LineEditor(Type type, const char* name)
@ -96,31 +92,29 @@ LineEditor* LineEditor::Get() {
class DumbLineEditor: public LineEditor { class DumbLineEditor: public LineEditor {
public: public:
DumbLineEditor() : LineEditor(LineEditor::DUMB, "dumb") { } DumbLineEditor() : LineEditor(LineEditor::DUMB, "dumb") { }
virtual i::SmartArrayPointer<char> Prompt(const char* prompt); virtual Handle<String> Prompt(const char* prompt);
}; };
static DumbLineEditor dumb_line_editor; static DumbLineEditor dumb_line_editor;
i::SmartArrayPointer<char> DumbLineEditor::Prompt(const char* prompt) { Handle<String> DumbLineEditor::Prompt(const char* prompt) {
static const int kBufferSize = 256;
char buffer[kBufferSize];
printf("%s", prompt); printf("%s", prompt);
char* str = fgets(buffer, kBufferSize, stdin); return Shell::ReadFromStdin();
return i::SmartArrayPointer<char>(str ? i::StrDup(str) : str);
} }
#ifndef V8_SHARED
CounterMap* Shell::counter_map_; CounterMap* Shell::counter_map_;
i::OS::MemoryMappedFile* Shell::counters_file_ = NULL; i::OS::MemoryMappedFile* Shell::counters_file_ = NULL;
CounterCollection Shell::local_counters_; CounterCollection Shell::local_counters_;
CounterCollection* Shell::counters_ = &local_counters_; CounterCollection* Shell::counters_ = &local_counters_;
i::Mutex* Shell::context_mutex_(i::OS::CreateMutex()); i::Mutex* Shell::context_mutex_(i::OS::CreateMutex());
Persistent<Context> Shell::utility_context_; Persistent<Context> Shell::utility_context_;
LineEditor* Shell::console = NULL;
#endif // V8_SHARED #endif // V8_SHARED
LineEditor* Shell::console = NULL;
Persistent<Context> Shell::evaluation_context_; Persistent<Context> Shell::evaluation_context_;
ShellOptions Shell::options; ShellOptions Shell::options;
const char* Shell::kPrompt = "d8> "; const char* Shell::kPrompt = "d8> ";
@ -238,7 +232,7 @@ Handle<Value> Shell::Read(const Arguments& args) {
} }
Handle<Value> Shell::ReadLine(const Arguments& args) { Handle<String> Shell::ReadFromStdin() {
static const int kBufferSize = 256; static const int kBufferSize = 256;
char buffer[kBufferSize]; char buffer[kBufferSize];
Handle<String> accumulator = String::New(""); Handle<String> accumulator = String::New("");
@ -247,7 +241,12 @@ Handle<Value> Shell::ReadLine(const Arguments& args) {
// Continue reading if the line ends with an escape '\\' or the line has // Continue reading if the line ends with an escape '\\' or the line has
// not been fully read into the buffer yet (does not end with '\n'). // not been fully read into the buffer yet (does not end with '\n').
// If fgets gets an error, just give up. // If fgets gets an error, just give up.
if (fgets(buffer, kBufferSize, stdin) == NULL) return Null(); char* input = NULL;
{ // Release lock for blocking input.
Unlocker unlock(Isolate::GetCurrent());
input = fgets(buffer, kBufferSize, stdin);
}
if (input == NULL) return Handle<String>();
length = static_cast<int>(strlen(buffer)); length = static_cast<int>(strlen(buffer));
if (length == 0) { if (length == 0) {
return accumulator; return accumulator;
@ -532,6 +531,10 @@ Handle<Value> Shell::Version(const Arguments& args) {
void Shell::ReportException(v8::TryCatch* try_catch) { void Shell::ReportException(v8::TryCatch* try_catch) {
HandleScope handle_scope; HandleScope handle_scope;
#if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
bool enter_context = !Context::InContext();
if (enter_context) utility_context_->Enter();
#endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
v8::String::Utf8Value exception(try_catch->Exception()); v8::String::Utf8Value exception(try_catch->Exception());
const char* exception_string = ToCString(exception); const char* exception_string = ToCString(exception);
Handle<Message> message = try_catch->Message(); Handle<Message> message = try_catch->Message();
@ -566,6 +569,9 @@ void Shell::ReportException(v8::TryCatch* try_catch) {
} }
} }
printf("\n"); printf("\n");
#if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
if (enter_context) utility_context_->Exit();
#endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
} }
@ -603,6 +609,12 @@ Handle<Value> Shell::DebugCommandToJSONRequest(Handle<String> command) {
Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv); Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
return val; return val;
} }
void Shell::DispatchDebugMessages() {
v8::Context::Scope scope(Shell::evaluation_context_);
v8::Debug::ProcessDebugMessages();
}
#endif // ENABLE_DEBUGGER_SUPPORT #endif // ENABLE_DEBUGGER_SUPPORT
#endif // V8_SHARED #endif // V8_SHARED
@ -872,6 +884,7 @@ void Shell::Initialize() {
// Start the debugger agent if requested. // Start the debugger agent if requested.
if (i::FLAG_debugger_agent) { if (i::FLAG_debugger_agent) {
v8::Debug::EnableAgent("d8 shell", i::FLAG_debugger_port, true); v8::Debug::EnableAgent("d8 shell", i::FLAG_debugger_port, true);
v8::Debug::SetDebugMessageDispatchHandler(DispatchDebugMessages, true);
} }
#endif // ENABLE_DEBUGGER_SUPPORT #endif // ENABLE_DEBUGGER_SUPPORT
#endif // V8_SHARED #endif // V8_SHARED
@ -1047,28 +1060,15 @@ void Shell::RunShell() {
Context::Scope context_scope(evaluation_context_); Context::Scope context_scope(evaluation_context_);
HandleScope outer_scope; HandleScope outer_scope;
Handle<String> name = String::New("(d8)"); Handle<String> name = String::New("(d8)");
#ifndef V8_SHARED
console = LineEditor::Get(); console = LineEditor::Get();
printf("V8 version %s [console: %s]\n", V8::GetVersion(), console->name()); printf("V8 version %s [console: %s]\n", V8::GetVersion(), console->name());
console->Open(); console->Open();
while (true) { while (true) {
i::SmartArrayPointer<char> input = console->Prompt(Shell::kPrompt);
if (input.is_empty()) break;
console->AddHistory(*input);
HandleScope inner_scope; HandleScope inner_scope;
ExecuteString(String::New(*input), name, true, true); Handle<String> input = console->Prompt(Shell::kPrompt);
if (input.IsEmpty()) break;
ExecuteString(input, name, true, true);
} }
#else
printf("V8 version %s [D8 light using shared library]\n", V8::GetVersion());
static const int kBufferSize = 256;
while (true) {
char buffer[kBufferSize];
printf("%s", Shell::kPrompt);
if (fgets(buffer, kBufferSize, stdin) == NULL) break;
HandleScope inner_scope;
ExecuteString(String::New(buffer), name, true, true);
}
#endif // V8_SHARED
printf("\n"); printf("\n");
} }

2
deps/v8/src/d8.gyp

@ -1,4 +1,4 @@
# Copyright 2010 the V8 project authors. All rights reserved. # Copyright 2012 the V8 project authors. All rights reserved.
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are # modification, are permitted provided that the following conditions are
# met: # met:

19
deps/v8/src/d8.h

@ -116,14 +116,13 @@ class CounterMap {
#endif // V8_SHARED #endif // V8_SHARED
#ifndef V8_SHARED
class LineEditor { class LineEditor {
public: public:
enum Type { DUMB = 0, READLINE = 1 }; enum Type { DUMB = 0, READLINE = 1 };
LineEditor(Type type, const char* name); LineEditor(Type type, const char* name);
virtual ~LineEditor() { } virtual ~LineEditor() { }
virtual i::SmartArrayPointer<char> Prompt(const char* prompt) = 0; virtual Handle<String> Prompt(const char* prompt) = 0;
virtual bool Open() { return true; } virtual bool Open() { return true; }
virtual bool Close() { return true; } virtual bool Close() { return true; }
virtual void AddHistory(const char* str) { } virtual void AddHistory(const char* str) { }
@ -136,7 +135,6 @@ class LineEditor {
LineEditor* next_; LineEditor* next_;
static LineEditor* first_; static LineEditor* first_;
}; };
#endif // V8_SHARED
class SourceGroup { class SourceGroup {
@ -268,12 +266,13 @@ class Shell : public i::AllStatic {
size_t buckets); size_t buckets);
static void AddHistogramSample(void* histogram, int sample); static void AddHistogramSample(void* histogram, int sample);
static void MapCounters(const char* name); static void MapCounters(const char* name);
#endif // V8_SHARED
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
static Handle<Object> DebugMessageDetails(Handle<String> message); static Handle<Object> DebugMessageDetails(Handle<String> message);
static Handle<Value> DebugCommandToJSONRequest(Handle<String> command); static Handle<Value> DebugCommandToJSONRequest(Handle<String> command);
#endif static void DispatchDebugMessages();
#endif // ENABLE_DEBUGGER_SUPPORT
#endif // V8_SHARED
#ifdef WIN32 #ifdef WIN32
#undef Yield #undef Yield
@ -287,7 +286,10 @@ class Shell : public i::AllStatic {
static Handle<Value> EnableProfiler(const Arguments& args); static Handle<Value> EnableProfiler(const Arguments& args);
static Handle<Value> DisableProfiler(const Arguments& args); static Handle<Value> DisableProfiler(const Arguments& args);
static Handle<Value> Read(const Arguments& args); static Handle<Value> Read(const Arguments& args);
static Handle<Value> ReadLine(const Arguments& args); static Handle<String> ReadFromStdin();
static Handle<Value> ReadLine(const Arguments& args) {
return ReadFromStdin();
}
static Handle<Value> Load(const Arguments& args); static Handle<Value> Load(const Arguments& args);
static Handle<Value> ArrayBuffer(const Arguments& args); static Handle<Value> ArrayBuffer(const Arguments& args);
static Handle<Value> Int8Array(const Arguments& args); static Handle<Value> Int8Array(const Arguments& args);
@ -335,11 +337,8 @@ class Shell : public i::AllStatic {
static Handle<Value> RemoveDirectory(const Arguments& args); static Handle<Value> RemoveDirectory(const Arguments& args);
static void AddOSMethods(Handle<ObjectTemplate> os_template); static void AddOSMethods(Handle<ObjectTemplate> os_template);
#ifndef V8_SHARED
static const char* kHistoryFileName;
static const int kMaxHistoryEntries;
static LineEditor* console; static LineEditor* console;
#endif // V8_SHARED
static const char* kPrompt; static const char* kPrompt;
static ShellOptions options; static ShellOptions options;

2
deps/v8/src/dtoa.h

@ -49,7 +49,7 @@ enum DtoaMode {
// be at least kBase10MaximalLength + 1 characters long. // be at least kBase10MaximalLength + 1 characters long.
const int kBase10MaximalLength = 17; const int kBase10MaximalLength = 17;
// Converts the given double 'v' to ascii. // Converts the given double 'v' to ASCII.
// The result should be interpreted as buffer * 10^(point-length). // The result should be interpreted as buffer * 10^(point-length).
// //
// The output depends on the given mode: // The output depends on the given mode:

2
deps/v8/src/execution.cc

@ -356,7 +356,7 @@ void StackGuard::EnableInterrupts() {
void StackGuard::SetStackLimit(uintptr_t limit) { void StackGuard::SetStackLimit(uintptr_t limit) {
ExecutionAccess access(isolate_); ExecutionAccess access(isolate_);
// If the current limits are special (eg due to a pending interrupt) then // If the current limits are special (e.g. due to a pending interrupt) then
// leave them alone. // leave them alone.
uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit); uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
if (thread_local_.jslimit_ == thread_local_.real_jslimit_) { if (thread_local_.jslimit_ == thread_local_.real_jslimit_) {

252
deps/v8/src/extensions/experimental/break-iterator.cc

@ -1,252 +0,0 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "src/extensions/experimental/break-iterator.h"
#include <string.h>
#include "unicode/brkiter.h"
#include "unicode/locid.h"
#include "unicode/rbbi.h"
namespace v8 {
namespace internal {
v8::Persistent<v8::FunctionTemplate> BreakIterator::break_iterator_template_;
icu::BreakIterator* BreakIterator::UnpackBreakIterator(
v8::Handle<v8::Object> obj) {
if (break_iterator_template_->HasInstance(obj)) {
return static_cast<icu::BreakIterator*>(
obj->GetPointerFromInternalField(0));
}
return NULL;
}
icu::UnicodeString* BreakIterator::ResetAdoptedText(
v8::Handle<v8::Object> obj, v8::Handle<v8::Value> value) {
// Get the previous value from the internal field.
icu::UnicodeString* text = static_cast<icu::UnicodeString*>(
obj->GetPointerFromInternalField(1));
delete text;
// Assign new value to the internal pointer.
v8::String::Value text_value(value);
text = new icu::UnicodeString(
reinterpret_cast<const UChar*>(*text_value), text_value.length());
obj->SetPointerInInternalField(1, text);
// Return new unicode string pointer.
return text;
}
void BreakIterator::DeleteBreakIterator(v8::Persistent<v8::Value> object,
void* param) {
v8::Persistent<v8::Object> persistent_object =
v8::Persistent<v8::Object>::Cast(object);
// First delete the hidden C++ object.
// Unpacking should never return NULL here. That would only happen if
// this method is used as the weak callback for persistent handles not
// pointing to a break iterator.
delete UnpackBreakIterator(persistent_object);
delete static_cast<icu::UnicodeString*>(
persistent_object->GetPointerFromInternalField(1));
// Then dispose of the persistent handle to JS object.
persistent_object.Dispose();
}
// Throws a JavaScript exception.
static v8::Handle<v8::Value> ThrowUnexpectedObjectError() {
// Returns undefined, and schedules an exception to be thrown.
return v8::ThrowException(v8::Exception::Error(
v8::String::New("BreakIterator method called on an object "
"that is not a BreakIterator.")));
}
v8::Handle<v8::Value> BreakIterator::BreakIteratorAdoptText(
const v8::Arguments& args) {
if (args.Length() != 1 || !args[0]->IsString()) {
return v8::ThrowException(v8::Exception::SyntaxError(
v8::String::New("Text input is required.")));
}
icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder());
if (!break_iterator) {
return ThrowUnexpectedObjectError();
}
break_iterator->setText(*ResetAdoptedText(args.Holder(), args[0]));
return v8::Undefined();
}
v8::Handle<v8::Value> BreakIterator::BreakIteratorFirst(
const v8::Arguments& args) {
icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder());
if (!break_iterator) {
return ThrowUnexpectedObjectError();
}
return v8::Int32::New(break_iterator->first());
}
v8::Handle<v8::Value> BreakIterator::BreakIteratorNext(
const v8::Arguments& args) {
icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder());
if (!break_iterator) {
return ThrowUnexpectedObjectError();
}
return v8::Int32::New(break_iterator->next());
}
v8::Handle<v8::Value> BreakIterator::BreakIteratorCurrent(
const v8::Arguments& args) {
icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder());
if (!break_iterator) {
return ThrowUnexpectedObjectError();
}
return v8::Int32::New(break_iterator->current());
}
v8::Handle<v8::Value> BreakIterator::BreakIteratorBreakType(
const v8::Arguments& args) {
icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder());
if (!break_iterator) {
return ThrowUnexpectedObjectError();
}
// TODO(cira): Remove cast once ICU fixes base BreakIterator class.
icu::RuleBasedBreakIterator* rule_based_iterator =
static_cast<icu::RuleBasedBreakIterator*>(break_iterator);
int32_t status = rule_based_iterator->getRuleStatus();
// Keep return values in sync with JavaScript BreakType enum.
if (status >= UBRK_WORD_NONE && status < UBRK_WORD_NONE_LIMIT) {
return v8::Int32::New(UBRK_WORD_NONE);
} else if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) {
return v8::Int32::New(UBRK_WORD_NUMBER);
} else if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) {
return v8::Int32::New(UBRK_WORD_LETTER);
} else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) {
return v8::Int32::New(UBRK_WORD_KANA);
} else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) {
return v8::Int32::New(UBRK_WORD_IDEO);
} else {
return v8::Int32::New(-1);
}
}
v8::Handle<v8::Value> BreakIterator::JSBreakIterator(
const v8::Arguments& args) {
v8::HandleScope handle_scope;
if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) {
return v8::ThrowException(v8::Exception::SyntaxError(
v8::String::New("Locale and iterator type are required.")));
}
v8::String::Utf8Value locale(args[0]);
icu::Locale icu_locale(*locale);
UErrorCode status = U_ZERO_ERROR;
icu::BreakIterator* break_iterator = NULL;
v8::String::Utf8Value type(args[1]);
if (!strcmp(*type, "character")) {
break_iterator =
icu::BreakIterator::createCharacterInstance(icu_locale, status);
} else if (!strcmp(*type, "word")) {
break_iterator =
icu::BreakIterator::createWordInstance(icu_locale, status);
} else if (!strcmp(*type, "sentence")) {
break_iterator =
icu::BreakIterator::createSentenceInstance(icu_locale, status);
} else if (!strcmp(*type, "line")) {
break_iterator =
icu::BreakIterator::createLineInstance(icu_locale, status);
} else {
return v8::ThrowException(v8::Exception::SyntaxError(
v8::String::New("Invalid iterator type.")));
}
if (U_FAILURE(status)) {
delete break_iterator;
return v8::ThrowException(v8::Exception::Error(
v8::String::New("Failed to create break iterator.")));
}
if (break_iterator_template_.IsEmpty()) {
v8::Local<v8::FunctionTemplate> raw_template(v8::FunctionTemplate::New());
raw_template->SetClassName(v8::String::New("v8Locale.v8BreakIterator"));
// Define internal field count on instance template.
v8::Local<v8::ObjectTemplate> object_template =
raw_template->InstanceTemplate();
// Set aside internal fields for icu break iterator and adopted text.
object_template->SetInternalFieldCount(2);
// Define all of the prototype methods on prototype template.
v8::Local<v8::ObjectTemplate> proto = raw_template->PrototypeTemplate();
proto->Set(v8::String::New("adoptText"),
v8::FunctionTemplate::New(BreakIteratorAdoptText));
proto->Set(v8::String::New("first"),
v8::FunctionTemplate::New(BreakIteratorFirst));
proto->Set(v8::String::New("next"),
v8::FunctionTemplate::New(BreakIteratorNext));
proto->Set(v8::String::New("current"),
v8::FunctionTemplate::New(BreakIteratorCurrent));
proto->Set(v8::String::New("breakType"),
v8::FunctionTemplate::New(BreakIteratorBreakType));
break_iterator_template_ =
v8::Persistent<v8::FunctionTemplate>::New(raw_template);
}
// Create an empty object wrapper.
v8::Local<v8::Object> local_object =
break_iterator_template_->GetFunction()->NewInstance();
v8::Persistent<v8::Object> wrapper =
v8::Persistent<v8::Object>::New(local_object);
// Set break iterator as internal field of the resulting JS object.
wrapper->SetPointerInInternalField(0, break_iterator);
// Make sure that the pointer to adopted text is NULL.
wrapper->SetPointerInInternalField(1, NULL);
// Make object handle weak so we can delete iterator once GC kicks in.
wrapper.MakeWeak(NULL, DeleteBreakIterator);
return wrapper;
}
} } // namespace v8::internal

89
deps/v8/src/extensions/experimental/break-iterator.h

@ -1,89 +0,0 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_EXTENSIONS_EXPERIMENTAL_BREAK_ITERATOR_H_
#define V8_EXTENSIONS_EXPERIMENTAL_BREAK_ITERATOR_H_
#include "include/v8.h"
#include "unicode/uversion.h"
namespace U_ICU_NAMESPACE {
class BreakIterator;
class UnicodeString;
}
namespace v8 {
namespace internal {
class BreakIterator {
public:
static v8::Handle<v8::Value> JSBreakIterator(const v8::Arguments& args);
// Helper methods for various bindings.
// Unpacks break iterator object from corresponding JavaScript object.
static icu::BreakIterator* UnpackBreakIterator(v8::Handle<v8::Object> obj);
// Deletes the old value and sets the adopted text in
// corresponding JavaScript object.
static icu::UnicodeString* ResetAdoptedText(v8::Handle<v8::Object> obj,
v8::Handle<v8::Value> text_value);
// Release memory we allocated for the BreakIterator once the JS object that
// holds the pointer gets garbage collected.
static void DeleteBreakIterator(v8::Persistent<v8::Value> object,
void* param);
// Assigns new text to the iterator.
static v8::Handle<v8::Value> BreakIteratorAdoptText(
const v8::Arguments& args);
// Moves iterator to the beginning of the string and returns new position.
static v8::Handle<v8::Value> BreakIteratorFirst(const v8::Arguments& args);
// Moves iterator to the next position and returns it.
static v8::Handle<v8::Value> BreakIteratorNext(const v8::Arguments& args);
// Returns current iterator's current position.
static v8::Handle<v8::Value> BreakIteratorCurrent(
const v8::Arguments& args);
// Returns type of the item from current position.
// This call is only valid for word break iterators. Others just return 0.
static v8::Handle<v8::Value> BreakIteratorBreakType(
const v8::Arguments& args);
private:
BreakIterator() {}
static v8::Persistent<v8::FunctionTemplate> break_iterator_template_;
};
} } // namespace v8::internal
#endif // V8_EXTENSIONS_EXPERIMENTAL_BREAK_ITERATOR_H_

222
deps/v8/src/extensions/experimental/collator.cc

@ -1,222 +0,0 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "src/extensions/experimental/collator.h"
#include "unicode/coll.h"
#include "unicode/locid.h"
#include "unicode/ucol.h"
namespace v8 {
namespace internal {
v8::Persistent<v8::FunctionTemplate> Collator::collator_template_;
icu::Collator* Collator::UnpackCollator(v8::Handle<v8::Object> obj) {
if (collator_template_->HasInstance(obj)) {
return static_cast<icu::Collator*>(obj->GetPointerFromInternalField(0));
}
return NULL;
}
void Collator::DeleteCollator(v8::Persistent<v8::Value> object, void* param) {
v8::Persistent<v8::Object> persistent_object =
v8::Persistent<v8::Object>::Cast(object);
// First delete the hidden C++ object.
// Unpacking should never return NULL here. That would only happen if
// this method is used as the weak callback for persistent handles not
// pointing to a collator.
delete UnpackCollator(persistent_object);
// Then dispose of the persistent handle to JS object.
persistent_object.Dispose();
}
// Throws a JavaScript exception.
static v8::Handle<v8::Value> ThrowUnexpectedObjectError() {
// Returns undefined, and schedules an exception to be thrown.
return v8::ThrowException(v8::Exception::Error(
v8::String::New("Collator method called on an object "
"that is not a Collator.")));
}
// Extract a boolean option named in |option| and set it to |result|.
// Return true if it's specified. Otherwise, return false.
static bool ExtractBooleanOption(const v8::Local<v8::Object>& options,
const char* option,
bool* result) {
v8::HandleScope handle_scope;
v8::TryCatch try_catch;
v8::Handle<v8::Value> value = options->Get(v8::String::New(option));
if (try_catch.HasCaught()) {
return false;
}
// No need to check if |value| is empty because it's taken care of
// by TryCatch above.
if (!value->IsUndefined() && !value->IsNull()) {
if (value->IsBoolean()) {
*result = value->BooleanValue();
return true;
}
}
return false;
}
// When there's an ICU error, throw a JavaScript error with |message|.
static v8::Handle<v8::Value> ThrowExceptionForICUError(const char* message) {
return v8::ThrowException(v8::Exception::Error(v8::String::New(message)));
}
v8::Handle<v8::Value> Collator::CollatorCompare(const v8::Arguments& args) {
if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) {
return v8::ThrowException(v8::Exception::SyntaxError(
v8::String::New("Two string arguments are required.")));
}
icu::Collator* collator = UnpackCollator(args.Holder());
if (!collator) {
return ThrowUnexpectedObjectError();
}
v8::String::Value string_value1(args[0]);
v8::String::Value string_value2(args[1]);
const UChar* string1 = reinterpret_cast<const UChar*>(*string_value1);
const UChar* string2 = reinterpret_cast<const UChar*>(*string_value2);
UErrorCode status = U_ZERO_ERROR;
UCollationResult result = collator->compare(
string1, string_value1.length(), string2, string_value2.length(), status);
if (U_FAILURE(status)) {
return ThrowExceptionForICUError(
"Unexpected failure in Collator.compare.");
}
return v8::Int32::New(result);
}
v8::Handle<v8::Value> Collator::JSCollator(const v8::Arguments& args) {
v8::HandleScope handle_scope;
if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsObject()) {
return v8::ThrowException(v8::Exception::SyntaxError(
v8::String::New("Locale and collation options are required.")));
}
v8::String::AsciiValue locale(args[0]);
icu::Locale icu_locale(*locale);
icu::Collator* collator = NULL;
UErrorCode status = U_ZERO_ERROR;
collator = icu::Collator::createInstance(icu_locale, status);
if (U_FAILURE(status)) {
delete collator;
return ThrowExceptionForICUError("Failed to create collator.");
}
v8::Local<v8::Object> options(args[1]->ToObject());
// Below, we change collation options that are explicitly specified
// by a caller in JavaScript. Otherwise, we don't touch because
// we don't want to change the locale-dependent default value.
// The three options below are very likely to have the same default
// across locales, but I haven't checked them all. Others we may add
// in the future have certainly locale-dependent default (e.g.
// caseFirst is upperFirst for Danish while is off for most other locales).
bool ignore_case, ignore_accents, numeric;
if (ExtractBooleanOption(options, "ignoreCase", &ignore_case)) {
// We need to explicitly set the level to secondary to get case ignored.
// The default L3 ignores UCOL_CASE_LEVEL == UCOL_OFF !
if (ignore_case) {
collator->setStrength(icu::Collator::SECONDARY);
}
collator->setAttribute(UCOL_CASE_LEVEL, ignore_case ? UCOL_OFF : UCOL_ON,
status);
if (U_FAILURE(status)) {
delete collator;
return ThrowExceptionForICUError("Failed to set ignoreCase.");
}
}
// Accents are taken into account with strength secondary or higher.
if (ExtractBooleanOption(options, "ignoreAccents", &ignore_accents)) {
if (!ignore_accents) {
collator->setStrength(icu::Collator::SECONDARY);
} else {
collator->setStrength(icu::Collator::PRIMARY);
}
}
if (ExtractBooleanOption(options, "numeric", &numeric)) {
collator->setAttribute(UCOL_NUMERIC_COLLATION,
numeric ? UCOL_ON : UCOL_OFF, status);
if (U_FAILURE(status)) {
delete collator;
return ThrowExceptionForICUError("Failed to set numeric sort option.");
}
}
if (collator_template_.IsEmpty()) {
v8::Local<v8::FunctionTemplate> raw_template(v8::FunctionTemplate::New());
raw_template->SetClassName(v8::String::New("v8Locale.Collator"));
// Define internal field count on instance template.
v8::Local<v8::ObjectTemplate> object_template =
raw_template->InstanceTemplate();
// Set aside internal fields for icu collator.
object_template->SetInternalFieldCount(1);
// Define all of the prototype methods on prototype template.
v8::Local<v8::ObjectTemplate> proto = raw_template->PrototypeTemplate();
proto->Set(v8::String::New("compare"),
v8::FunctionTemplate::New(CollatorCompare));
collator_template_ =
v8::Persistent<v8::FunctionTemplate>::New(raw_template);
}
// Create an empty object wrapper.
v8::Local<v8::Object> local_object =
collator_template_->GetFunction()->NewInstance();
v8::Persistent<v8::Object> wrapper =
v8::Persistent<v8::Object>::New(local_object);
// Set collator as internal field of the resulting JS object.
wrapper->SetPointerInInternalField(0, collator);
// Make object handle weak so we can delete iterator once GC kicks in.
wrapper.MakeWeak(NULL, DeleteCollator);
return wrapper;
}
} } // namespace v8::internal

68
deps/v8/src/extensions/experimental/collator.h

@ -1,68 +0,0 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_EXTENSIONS_EXPERIMENTAL_COLLATOR_H
#define V8_EXTENSIONS_EXPERIMENTAL_COLLATOR_H_
#include "include/v8.h"
#include "unicode/uversion.h"
namespace U_ICU_NAMESPACE {
class Collator;
class UnicodeString;
}
namespace v8 {
namespace internal {
class Collator {
public:
static v8::Handle<v8::Value> JSCollator(const v8::Arguments& args);
// Helper methods for various bindings.
// Unpacks collator object from corresponding JavaScript object.
static icu::Collator* UnpackCollator(v8::Handle<v8::Object> obj);
// Release memory we allocated for the Collator once the JS object that
// holds the pointer gets garbage collected.
static void DeleteCollator(v8::Persistent<v8::Value> object, void* param);
// Compare two strings and returns -1, 0 and 1 depending on
// whether string1 is smaller than, equal to or larger than string2.
static v8::Handle<v8::Value> CollatorCompare(const v8::Arguments& args);
private:
Collator() {}
static v8::Persistent<v8::FunctionTemplate> collator_template_;
};
} } // namespace v8::internal
#endif // V8_EXTENSIONS_EXPERIMENTAL_COLLATOR

384
deps/v8/src/extensions/experimental/datetime-format.cc

@ -1,384 +0,0 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "src/extensions/experimental/datetime-format.h"
#include <string.h>
#include "src/extensions/experimental/i18n-utils.h"
#include "unicode/dtfmtsym.h"
#include "unicode/dtptngen.h"
#include "unicode/locid.h"
#include "unicode/smpdtfmt.h"
namespace v8 {
namespace internal {
v8::Persistent<v8::FunctionTemplate> DateTimeFormat::datetime_format_template_;
static icu::DateFormat* CreateDateTimeFormat(v8::Handle<v8::String>,
v8::Handle<v8::Object>);
static v8::Handle<v8::Value> GetSymbols(
const v8::Arguments&,
const icu::UnicodeString*, int32_t,
const icu::UnicodeString*, int32_t,
const icu::UnicodeString*, int32_t);
static v8::Handle<v8::Value> ThrowUnexpectedObjectError();
static icu::DateFormat::EStyle GetDateTimeStyle(const icu::UnicodeString&);
icu::SimpleDateFormat* DateTimeFormat::UnpackDateTimeFormat(
v8::Handle<v8::Object> obj) {
if (datetime_format_template_->HasInstance(obj)) {
return static_cast<icu::SimpleDateFormat*>(
obj->GetPointerFromInternalField(0));
}
return NULL;
}
void DateTimeFormat::DeleteDateTimeFormat(v8::Persistent<v8::Value> object,
void* param) {
v8::Persistent<v8::Object> persistent_object =
v8::Persistent<v8::Object>::Cast(object);
// First delete the hidden C++ object.
// Unpacking should never return NULL here. That would only happen if
// this method is used as the weak callback for persistent handles not
// pointing to a date time formatter.
delete UnpackDateTimeFormat(persistent_object);
// Then dispose of the persistent handle to JS object.
persistent_object.Dispose();
}
v8::Handle<v8::Value> DateTimeFormat::Format(const v8::Arguments& args) {
v8::HandleScope handle_scope;
double millis = 0.0;
if (args.Length() != 1 || !args[0]->IsDate()) {
// Create a new date.
v8::TryCatch try_catch;
v8::Local<v8::Script> date_script =
v8::Script::Compile(v8::String::New("eval('new Date()')"));
millis = date_script->Run()->NumberValue();
if (try_catch.HasCaught()) {
return try_catch.ReThrow();
}
} else {
millis = v8::Date::Cast(*args[0])->NumberValue();
}
icu::SimpleDateFormat* date_format = UnpackDateTimeFormat(args.Holder());
if (!date_format) {
return ThrowUnexpectedObjectError();
}
icu::UnicodeString result;
date_format->format(millis, result);
return v8::String::New(
reinterpret_cast<const uint16_t*>(result.getBuffer()), result.length());
}
v8::Handle<v8::Value> DateTimeFormat::GetMonths(const v8::Arguments& args) {
icu::SimpleDateFormat* date_format = UnpackDateTimeFormat(args.Holder());
if (!date_format) {
return ThrowUnexpectedObjectError();
}
const icu::DateFormatSymbols* symbols = date_format->getDateFormatSymbols();
int32_t narrow_count;
const icu::UnicodeString* narrow = symbols->getMonths(
narrow_count,
icu::DateFormatSymbols::STANDALONE,
icu::DateFormatSymbols::NARROW);
int32_t abbrev_count;
const icu::UnicodeString* abbrev = symbols->getMonths(
abbrev_count,
icu::DateFormatSymbols::STANDALONE,
icu::DateFormatSymbols::ABBREVIATED);
int32_t wide_count;
const icu::UnicodeString* wide = symbols->getMonths(
wide_count,
icu::DateFormatSymbols::STANDALONE,
icu::DateFormatSymbols::WIDE);
return GetSymbols(
args, narrow, narrow_count, abbrev, abbrev_count, wide, wide_count);
}
v8::Handle<v8::Value> DateTimeFormat::GetWeekdays(const v8::Arguments& args) {
icu::SimpleDateFormat* date_format = UnpackDateTimeFormat(args.Holder());
if (!date_format) {
return ThrowUnexpectedObjectError();
}
const icu::DateFormatSymbols* symbols = date_format->getDateFormatSymbols();
int32_t narrow_count;
const icu::UnicodeString* narrow = symbols->getWeekdays(
narrow_count,
icu::DateFormatSymbols::STANDALONE,
icu::DateFormatSymbols::NARROW);
int32_t abbrev_count;
const icu::UnicodeString* abbrev = symbols->getWeekdays(
abbrev_count,
icu::DateFormatSymbols::STANDALONE,
icu::DateFormatSymbols::ABBREVIATED);
int32_t wide_count;
const icu::UnicodeString* wide = symbols->getWeekdays(
wide_count,
icu::DateFormatSymbols::STANDALONE,
icu::DateFormatSymbols::WIDE);
// getXXXWeekdays always returns 8 elements - ICU stable API.
// We can't use ASSERT_EQ(8, narrow_count) because ASSERT is internal to v8.
if (narrow_count != 8 || abbrev_count != 8 || wide_count != 8) {
return v8::ThrowException(v8::Exception::Error(
v8::String::New("Failed to get weekday information.")));
}
// ICU documentation says we should ignore element 0 of the returned array.
return GetSymbols(args, narrow + 1, narrow_count - 1, abbrev + 1,
abbrev_count -1 , wide + 1, wide_count - 1);
}
v8::Handle<v8::Value> DateTimeFormat::GetEras(const v8::Arguments& args) {
icu::SimpleDateFormat* date_format = UnpackDateTimeFormat(args.Holder());
if (!date_format) {
return ThrowUnexpectedObjectError();
}
const icu::DateFormatSymbols* symbols = date_format->getDateFormatSymbols();
int32_t narrow_count;
const icu::UnicodeString* narrow = symbols->getNarrowEras(narrow_count);
int32_t abbrev_count;
const icu::UnicodeString* abbrev = symbols->getEras(abbrev_count);
int32_t wide_count;
const icu::UnicodeString* wide = symbols->getEraNames(wide_count);
return GetSymbols(
args, narrow, narrow_count, abbrev, abbrev_count, wide, wide_count);
}
v8::Handle<v8::Value> DateTimeFormat::GetAmPm(const v8::Arguments& args) {
icu::SimpleDateFormat* date_format = UnpackDateTimeFormat(args.Holder());
if (!date_format) {
return ThrowUnexpectedObjectError();
}
const icu::DateFormatSymbols* symbols = date_format->getDateFormatSymbols();
// In this case narrow == abbreviated == wide
int32_t count;
const icu::UnicodeString* wide = symbols->getAmPmStrings(count);
return GetSymbols(args, wide, count, wide, count, wide, count);
}
v8::Handle<v8::Value> DateTimeFormat::JSDateTimeFormat(
const v8::Arguments& args) {
v8::HandleScope handle_scope;
if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsObject()) {
return v8::ThrowException(v8::Exception::SyntaxError(
v8::String::New("Locale and date/time options are required.")));
}
icu::SimpleDateFormat* date_format = static_cast<icu::SimpleDateFormat*>(
CreateDateTimeFormat(args[0]->ToString(), args[1]->ToObject()));
if (datetime_format_template_.IsEmpty()) {
v8::Local<v8::FunctionTemplate> raw_template(v8::FunctionTemplate::New());
raw_template->SetClassName(v8::String::New("v8Locale.DateTimeFormat"));
// Define internal field count on instance template.
v8::Local<v8::ObjectTemplate> object_template =
raw_template->InstanceTemplate();
// Set aside internal field for icu date time formatter.
object_template->SetInternalFieldCount(1);
// Define all of the prototype methods on prototype template.
v8::Local<v8::ObjectTemplate> proto = raw_template->PrototypeTemplate();
proto->Set(v8::String::New("format"),
v8::FunctionTemplate::New(Format));
proto->Set(v8::String::New("getMonths"),
v8::FunctionTemplate::New(GetMonths));
proto->Set(v8::String::New("getWeekdays"),
v8::FunctionTemplate::New(GetWeekdays));
proto->Set(v8::String::New("getEras"),
v8::FunctionTemplate::New(GetEras));
proto->Set(v8::String::New("getAmPm"),
v8::FunctionTemplate::New(GetAmPm));
datetime_format_template_ =
v8::Persistent<v8::FunctionTemplate>::New(raw_template);
}
// Create an empty object wrapper.
v8::Local<v8::Object> local_object =
datetime_format_template_->GetFunction()->NewInstance();
v8::Persistent<v8::Object> wrapper =
v8::Persistent<v8::Object>::New(local_object);
// Set date time formatter as internal field of the resulting JS object.
wrapper->SetPointerInInternalField(0, date_format);
// Set resolved pattern in options.pattern.
icu::UnicodeString pattern;
date_format->toPattern(pattern);
v8::Local<v8::Object> options = v8::Object::New();
options->Set(v8::String::New("pattern"),
v8::String::New(reinterpret_cast<const uint16_t*>(
pattern.getBuffer()), pattern.length()));
wrapper->Set(v8::String::New("options"), options);
// Make object handle weak so we can delete iterator once GC kicks in.
wrapper.MakeWeak(NULL, DeleteDateTimeFormat);
return wrapper;
}
// Returns SimpleDateFormat.
static icu::DateFormat* CreateDateTimeFormat(
v8::Handle<v8::String> locale, v8::Handle<v8::Object> settings) {
v8::HandleScope handle_scope;
v8::String::AsciiValue ascii_locale(locale);
icu::Locale icu_locale(*ascii_locale);
// Make formatter from skeleton.
icu::SimpleDateFormat* date_format = NULL;
UErrorCode status = U_ZERO_ERROR;
icu::UnicodeString skeleton;
if (I18NUtils::ExtractStringSetting(settings, "skeleton", &skeleton)) {
v8::Local<icu::DateTimePatternGenerator> generator(
icu::DateTimePatternGenerator::createInstance(icu_locale, status));
icu::UnicodeString pattern =
generator->getBestPattern(skeleton, status);
date_format = new icu::SimpleDateFormat(pattern, icu_locale, status);
if (U_SUCCESS(status)) {
return date_format;
} else {
delete date_format;
}
}
// Extract date style and time style from settings.
icu::UnicodeString date_style;
icu::DateFormat::EStyle icu_date_style = icu::DateFormat::kNone;
if (I18NUtils::ExtractStringSetting(settings, "dateStyle", &date_style)) {
icu_date_style = GetDateTimeStyle(date_style);
}
icu::UnicodeString time_style;
icu::DateFormat::EStyle icu_time_style = icu::DateFormat::kNone;
if (I18NUtils::ExtractStringSetting(settings, "timeStyle", &time_style)) {
icu_time_style = GetDateTimeStyle(time_style);
}
// Try all combinations of date/time styles.
if (icu_date_style == icu::DateFormat::kNone &&
icu_time_style == icu::DateFormat::kNone) {
// Return default short date, short
return icu::DateFormat::createDateTimeInstance(
icu::DateFormat::kShort, icu::DateFormat::kShort, icu_locale);
} else if (icu_date_style != icu::DateFormat::kNone &&
icu_time_style != icu::DateFormat::kNone) {
return icu::DateFormat::createDateTimeInstance(
icu_date_style, icu_time_style, icu_locale);
} else if (icu_date_style != icu::DateFormat::kNone) {
return icu::DateFormat::createDateInstance(icu_date_style, icu_locale);
} else {
// icu_time_style != icu::DateFormat::kNone
return icu::DateFormat::createTimeInstance(icu_time_style, icu_locale);
}
}
// Creates a v8::Array of narrow, abbrev or wide symbols.
static v8::Handle<v8::Value> GetSymbols(const v8::Arguments& args,
const icu::UnicodeString* narrow,
int32_t narrow_count,
const icu::UnicodeString* abbrev,
int32_t abbrev_count,
const icu::UnicodeString* wide,
int32_t wide_count) {
v8::HandleScope handle_scope;
// Make wide width default.
const icu::UnicodeString* result = wide;
int32_t count = wide_count;
if (args.Length() == 1 && args[0]->IsString()) {
v8::String::AsciiValue ascii_value(args[0]);
if (strcmp(*ascii_value, "abbreviated") == 0) {
result = abbrev;
count = abbrev_count;
} else if (strcmp(*ascii_value, "narrow") == 0) {
result = narrow;
count = narrow_count;
}
}
v8::Handle<v8::Array> symbols = v8::Array::New();
for (int32_t i = 0; i < count; ++i) {
symbols->Set(i, v8::String::New(
reinterpret_cast<const uint16_t*>(result[i].getBuffer()),
result[i].length()));
}
return handle_scope.Close(symbols);
}
// Throws a JavaScript exception.
static v8::Handle<v8::Value> ThrowUnexpectedObjectError() {
// Returns undefined, and schedules an exception to be thrown.
return v8::ThrowException(v8::Exception::Error(
v8::String::New("DateTimeFormat method called on an object "
"that is not a DateTimeFormat.")));
}
// Returns icu date/time style.
static icu::DateFormat::EStyle GetDateTimeStyle(
const icu::UnicodeString& type) {
if (type == UNICODE_STRING_SIMPLE("medium")) {
return icu::DateFormat::kMedium;
} else if (type == UNICODE_STRING_SIMPLE("long")) {
return icu::DateFormat::kLong;
} else if (type == UNICODE_STRING_SIMPLE("full")) {
return icu::DateFormat::kFull;
}
return icu::DateFormat::kShort;
}
} } // namespace v8::internal

83
deps/v8/src/extensions/experimental/datetime-format.h

@ -1,83 +0,0 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_EXTENSIONS_EXPERIMENTAL_DATETIME_FORMAT_H_
#define V8_EXTENSIONS_EXPERIMENTAL_DATETIME_FORMAT_H_
#include "include/v8.h"
#include "unicode/uversion.h"
namespace U_ICU_NAMESPACE {
class SimpleDateFormat;
}
namespace v8 {
namespace internal {
class DateTimeFormat {
public:
static v8::Handle<v8::Value> JSDateTimeFormat(const v8::Arguments& args);
// Helper methods for various bindings.
// Unpacks date format object from corresponding JavaScript object.
static icu::SimpleDateFormat* UnpackDateTimeFormat(
v8::Handle<v8::Object> obj);
// Release memory we allocated for the DateFormat once the JS object that
// holds the pointer gets garbage collected.
static void DeleteDateTimeFormat(v8::Persistent<v8::Value> object,
void* param);
// Formats date and returns corresponding string.
static v8::Handle<v8::Value> Format(const v8::Arguments& args);
// All date time symbol methods below return stand-alone names in
// either narrow, abbreviated or wide width.
// Get list of months.
static v8::Handle<v8::Value> GetMonths(const v8::Arguments& args);
// Get list of weekdays.
static v8::Handle<v8::Value> GetWeekdays(const v8::Arguments& args);
// Get list of eras.
static v8::Handle<v8::Value> GetEras(const v8::Arguments& args);
// Get list of day periods.
static v8::Handle<v8::Value> GetAmPm(const v8::Arguments& args);
private:
DateTimeFormat();
static v8::Persistent<v8::FunctionTemplate> datetime_format_template_;
};
} } // namespace v8::internal
#endif // V8_EXTENSIONS_EXPERIMENTAL_DATETIME_FORMAT_H_

105
deps/v8/src/extensions/experimental/experimental.gyp

@ -1,105 +0,0 @@
# Copyright 2011 the V8 project authors. All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
'variables': {
# TODO(cira): Find out how to pass this value for arbitrary embedder.
# Chromium sets it in common.gypi and does force include of that file for
# all sub projects.
'icu_src_dir%': '../../../../third_party/icu',
},
'targets': [
{
'target_name': 'i18n_api',
'type': 'static_library',
'sources': [
'break-iterator.cc',
'break-iterator.h',
'collator.cc',
'collator.h',
'datetime-format.cc',
'datetime-format.h',
'i18n-extension.cc',
'i18n-extension.h',
'i18n-locale.cc',
'i18n-locale.h',
'i18n-natives.h',
'i18n-utils.cc',
'i18n-utils.h',
'language-matcher.cc',
'language-matcher.h',
'number-format.cc',
'number-format.h',
'<(SHARED_INTERMEDIATE_DIR)/i18n-js.cc',
],
'include_dirs': [
'<(icu_src_dir)/public/common',
# v8/ is root for all includes.
'../../..'
],
'dependencies': [
'<(icu_src_dir)/icu.gyp:*',
'js2c_i18n#host',
'../../../tools/gyp/v8.gyp:v8',
],
'direct_dependent_settings': {
# Adds -Iv8 for embedders.
'include_dirs': [
'../../..'
],
},
},
{
'target_name': 'js2c_i18n',
'type': 'none',
'toolsets': ['host'],
'variables': {
'js_files': [
'i18n.js'
],
},
'actions': [
{
'action_name': 'js2c_i18n',
'inputs': [
'i18n-js2c.py',
'<@(js_files)',
],
'outputs': [
'<(SHARED_INTERMEDIATE_DIR)/i18n-js.cc',
],
'action': [
'python',
'i18n-js2c.py',
'<@(_outputs)',
'<@(js_files)'
],
},
],
},
], # targets
}

74
deps/v8/src/extensions/experimental/i18n-extension.cc

@ -1,74 +0,0 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "src/extensions/experimental/i18n-extension.h"
#include "src/extensions/experimental/break-iterator.h"
#include "src/extensions/experimental/collator.h"
#include "src/extensions/experimental/datetime-format.h"
#include "src/extensions/experimental/i18n-locale.h"
#include "src/extensions/experimental/i18n-natives.h"
#include "src/extensions/experimental/number-format.h"
namespace v8 {
namespace internal {
I18NExtension* I18NExtension::extension_ = NULL;
I18NExtension::I18NExtension()
: v8::Extension("v8/i18n", I18Natives::GetScriptSource()) {
}
v8::Handle<v8::FunctionTemplate> I18NExtension::GetNativeFunction(
v8::Handle<v8::String> name) {
if (name->Equals(v8::String::New("NativeJSLocale"))) {
return v8::FunctionTemplate::New(I18NLocale::JSLocale);
} else if (name->Equals(v8::String::New("NativeJSBreakIterator"))) {
return v8::FunctionTemplate::New(BreakIterator::JSBreakIterator);
} else if (name->Equals(v8::String::New("NativeJSCollator"))) {
return v8::FunctionTemplate::New(Collator::JSCollator);
} else if (name->Equals(v8::String::New("NativeJSDateTimeFormat"))) {
return v8::FunctionTemplate::New(DateTimeFormat::JSDateTimeFormat);
} else if (name->Equals(v8::String::New("NativeJSNumberFormat"))) {
return v8::FunctionTemplate::New(NumberFormat::JSNumberFormat);
}
return v8::Handle<v8::FunctionTemplate>();
}
I18NExtension* I18NExtension::get() {
if (!extension_) {
extension_ = new I18NExtension();
}
return extension_;
}
void I18NExtension::Register() {
static v8::DeclareExtension i18n_extension_declaration(I18NExtension::get());
}
} } // namespace v8::internal

54
deps/v8/src/extensions/experimental/i18n-extension.h

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

126
deps/v8/src/extensions/experimental/i18n-js2c.py

@ -1,126 +0,0 @@
#!/usr/bin/env python
#
# Copyright 2011 the V8 project authors. All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# This is a utility for converting I18N JavaScript source code into C-style
# char arrays. It is used for embedded JavaScript code in the V8
# library.
# This is a pared down copy of v8/tools/js2c.py that avoids use of
# v8/src/natives.h and produces different cc template.
import os, re, sys, string
def ToCArray(lines):
result = []
for chr in lines:
value = ord(chr)
assert value < 128
result.append(str(value))
result.append("0")
return ", ".join(result)
def RemoveCommentsAndTrailingWhitespace(lines):
lines = re.sub(r'//.*\n', '\n', lines) # end-of-line comments
lines = re.sub(re.compile(r'/\*.*?\*/', re.DOTALL), '', lines) # comments.
lines = re.sub(r'\s+\n+', '\n', lines) # trailing whitespace
return lines
def ReadFile(filename):
file = open(filename, "rt")
try:
lines = file.read()
finally:
file.close()
return lines
EVAL_PATTERN = re.compile(r'\beval\s*\(');
WITH_PATTERN = re.compile(r'\bwith\s*\(');
def Validate(lines, file):
lines = RemoveCommentsAndTrailingWhitespace(lines)
# Because of simplified context setup, eval and with is not
# allowed in the natives files.
eval_match = EVAL_PATTERN.search(lines)
if eval_match:
raise ("Eval disallowed in natives: %s" % file)
with_match = WITH_PATTERN.search(lines)
if with_match:
raise ("With statements disallowed in natives: %s" % file)
HEADER_TEMPLATE = """\
// Copyright 2011 Google Inc. All Rights Reserved.
// This file was generated from .js source files by gyp. If you
// want to make changes to this file you should either change the
// javascript source files or the i18n-js2c.py script.
#include "src/extensions/experimental/i18n-natives.h"
namespace v8 {
namespace internal {
// static
const char* I18Natives::GetScriptSource() {
// JavaScript source gets injected here.
static const char i18n_source[] = {%s};
return i18n_source;
}
} // internal
} // v8
"""
def JS2C(source, target):
filename = str(source)
lines = ReadFile(filename)
Validate(lines, filename)
data = ToCArray(lines)
# Emit result
output = open(target, "w")
output.write(HEADER_TEMPLATE % data)
output.close()
def main():
target = sys.argv[1]
source = sys.argv[2]
JS2C(source, target)
if __name__ == "__main__":
main()

111
deps/v8/src/extensions/experimental/i18n-locale.cc

@ -1,111 +0,0 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "src/extensions/experimental/i18n-locale.h"
#include "src/extensions/experimental/i18n-utils.h"
#include "src/extensions/experimental/language-matcher.h"
#include "unicode/locid.h"
#include "unicode/uloc.h"
namespace v8 {
namespace internal {
const char* const I18NLocale::kLocaleID = "localeID";
const char* const I18NLocale::kRegionID = "regionID";
const char* const I18NLocale::kICULocaleID = "icuLocaleID";
v8::Handle<v8::Value> I18NLocale::JSLocale(const v8::Arguments& args) {
v8::HandleScope handle_scope;
if (args.Length() != 1 || !args[0]->IsObject()) {
return v8::Undefined();
}
v8::Local<v8::Object> settings = args[0]->ToObject();
// Get best match for locale.
v8::TryCatch try_catch;
v8::Handle<v8::Value> locale_id = settings->Get(v8::String::New(kLocaleID));
if (try_catch.HasCaught()) {
return v8::Undefined();
}
LocaleIDMatch result;
if (locale_id->IsArray()) {
LanguageMatcher::GetBestMatchForPriorityList(
v8::Handle<v8::Array>::Cast(locale_id), &result);
} else if (locale_id->IsString()) {
LanguageMatcher::GetBestMatchForString(locale_id->ToString(), &result);
} else {
LanguageMatcher::GetBestMatchForString(v8::String::New(""), &result);
}
// Get best match for region.
char region_id[ULOC_COUNTRY_CAPACITY];
I18NUtils::StrNCopy(region_id, ULOC_COUNTRY_CAPACITY, "");
v8::Handle<v8::Value> region = settings->Get(v8::String::New(kRegionID));
if (try_catch.HasCaught()) {
return v8::Undefined();
}
if (!GetBestMatchForRegionID(result.icu_id, region, region_id)) {
// Set region id to empty string because region couldn't be inferred.
I18NUtils::StrNCopy(region_id, ULOC_COUNTRY_CAPACITY, "");
}
// Build JavaScript object that contains bcp and icu locale ID and region ID.
v8::Handle<v8::Object> locale = v8::Object::New();
locale->Set(v8::String::New(kLocaleID), v8::String::New(result.bcp47_id));
locale->Set(v8::String::New(kICULocaleID), v8::String::New(result.icu_id));
locale->Set(v8::String::New(kRegionID), v8::String::New(region_id));
return handle_scope.Close(locale);
}
bool I18NLocale::GetBestMatchForRegionID(
const char* locale_id, v8::Handle<v8::Value> region_id, char* result) {
if (region_id->IsString() && region_id->ToString()->Length() != 0) {
icu::Locale user_locale(
icu::Locale("und", *v8::String::Utf8Value(region_id->ToString())));
I18NUtils::StrNCopy(
result, ULOC_COUNTRY_CAPACITY, user_locale.getCountry());
return true;
}
// Maximize locale_id to infer the region (e.g. expand "de" to "de-Latn-DE"
// and grab "DE" from the result).
UErrorCode status = U_ZERO_ERROR;
char maximized_locale[ULOC_FULLNAME_CAPACITY];
uloc_addLikelySubtags(
locale_id, maximized_locale, ULOC_FULLNAME_CAPACITY, &status);
uloc_getCountry(maximized_locale, result, ULOC_COUNTRY_CAPACITY, &status);
return !U_FAILURE(status);
}
} } // namespace v8::internal

60
deps/v8/src/extensions/experimental/i18n-locale.h

@ -1,60 +0,0 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_EXTENSIONS_EXPERIMENTAL_I18N_LOCALE_H_
#define V8_EXTENSIONS_EXPERIMENTAL_I18N_LOCALE_H_
#include "include/v8.h"
namespace v8 {
namespace internal {
class I18NLocale {
public:
I18NLocale() {}
// Implementations of window.Locale methods.
static v8::Handle<v8::Value> JSLocale(const v8::Arguments& args);
// Infers region id given the locale id, or uses user specified region id.
// Result is canonicalized.
// Returns status of ICU operation (maximizing locale or get region call).
static bool GetBestMatchForRegionID(
const char* locale_id, v8::Handle<v8::Value> regions, char* result);
private:
// Key name for localeID parameter.
static const char* const kLocaleID;
// Key name for regionID parameter.
static const char* const kRegionID;
// Key name for the icuLocaleID result.
static const char* const kICULocaleID;
};
} } // namespace v8::internal
#endif // V8_EXTENSIONS_EXPERIMENTAL_I18N_LOCALE_H_

87
deps/v8/src/extensions/experimental/i18n-utils.cc

@ -1,87 +0,0 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "src/extensions/experimental/i18n-utils.h"
#include <string.h>
#include "unicode/unistr.h"
namespace v8 {
namespace internal {
// static
void I18NUtils::StrNCopy(char* dest, int length, const char* src) {
if (!dest || !src) return;
strncpy(dest, src, length);
dest[length - 1] = '\0';
}
// static
bool I18NUtils::ExtractStringSetting(const v8::Handle<v8::Object>& settings,
const char* setting,
icu::UnicodeString* result) {
if (!setting || !result) return false;
v8::HandleScope handle_scope;
v8::TryCatch try_catch;
v8::Handle<v8::Value> value = settings->Get(v8::String::New(setting));
if (try_catch.HasCaught()) {
return false;
}
// No need to check if |value| is empty because it's taken care of
// by TryCatch above.
if (!value->IsUndefined() && !value->IsNull() && value->IsString()) {
v8::String::Utf8Value utf8_value(value);
if (*utf8_value == NULL) return false;
result->setTo(icu::UnicodeString::fromUTF8(*utf8_value));
return true;
}
return false;
}
// static
void I18NUtils::AsciiToUChar(const char* source,
int32_t source_length,
UChar* target,
int32_t target_length) {
int32_t length =
source_length < target_length ? source_length : target_length;
if (length <= 0) {
return;
}
for (int32_t i = 0; i < length - 1; ++i) {
target[i] = static_cast<UChar>(source[i]);
}
target[length - 1] = 0x0u;
}
} } // namespace v8::internal

69
deps/v8/src/extensions/experimental/i18n-utils.h

@ -1,69 +0,0 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_EXTENSIONS_EXPERIMENTAL_I18N_UTILS_H_
#define V8_EXTENSIONS_EXPERIMENTAL_I18N_UTILS_H_
#include "include/v8.h"
#include "unicode/uversion.h"
namespace U_ICU_NAMESPACE {
class UnicodeString;
}
namespace v8 {
namespace internal {
class I18NUtils {
public:
// Safe string copy. Null terminates the destination. Copies at most
// (length - 1) bytes.
// We can't use snprintf since it's not supported on all relevant platforms.
// We can't use OS::SNPrintF, it's only for internal code.
static void StrNCopy(char* dest, int length, const char* src);
// Extract a string setting named in |settings| and set it to |result|.
// Return true if it's specified. Otherwise, return false.
static bool ExtractStringSetting(const v8::Handle<v8::Object>& settings,
const char* setting,
icu::UnicodeString* result);
// Converts ASCII array into UChar array.
// Target is always \0 terminated.
static void AsciiToUChar(const char* source,
int32_t source_length,
UChar* target,
int32_t target_length);
private:
I18NUtils() {}
};
} } // namespace v8::internal
#endif // V8_EXTENSIONS_EXPERIMENTAL_I18N_UTILS_H_

380
deps/v8/src/extensions/experimental/i18n.js

@ -1,380 +0,0 @@
// Copyright 2006-2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// TODO(cira): Rename v8Locale into LocaleInfo once we have stable API.
/**
* LocaleInfo class is an aggregate class of all i18n API calls.
* @param {Object} settings - localeID and regionID to create LocaleInfo from.
* {Array.<string>|string} settings.localeID -
* Unicode identifier of the locale.
* See http://unicode.org/reports/tr35/#BCP_47_Conformance
* {string} settings.regionID - ISO3166 region ID with addition of
* invalid, undefined and reserved region codes.
* @constructor
*/
v8Locale = function(settings) {
native function NativeJSLocale();
// Assume user wanted to do v8Locale("sr");
if (typeof(settings) === "string") {
settings = {'localeID': settings};
}
var properties = NativeJSLocale(
v8Locale.__createSettingsOrDefault(settings, {'localeID': 'root'}));
// Keep the resolved ICU locale ID around to avoid resolving localeID to
// ICU locale ID every time BreakIterator, Collator and so forth are called.
this.__icuLocaleID = properties.icuLocaleID;
this.options = {'localeID': properties.localeID,
'regionID': properties.regionID};
};
/**
* Clones existing locale with possible overrides for some of the options.
* @param {!Object} settings - overrides for current locale settings.
* @returns {Object} - new LocaleInfo object.
*/
v8Locale.prototype.derive = function(settings) {
return new v8Locale(
v8Locale.__createSettingsOrDefault(settings, this.options));
};
/**
* v8BreakIterator class implements locale aware segmenatation.
* It is not part of EcmaScript proposal.
* @param {Object} locale - locale object to pass to break
* iterator implementation.
* @param {string} type - type of segmenatation:
* - character
* - word
* - sentence
* - line
* @private
* @constructor
*/
v8Locale.v8BreakIterator = function(locale, type) {
native function NativeJSBreakIterator();
locale = v8Locale.__createLocaleOrDefault(locale);
// BCP47 ID would work in this case, but we use ICU locale for consistency.
var iterator = NativeJSBreakIterator(locale.__icuLocaleID, type);
iterator.type = type;
return iterator;
};
/**
* Type of the break we encountered during previous iteration.
* @type{Enum}
*/
v8Locale.v8BreakIterator.BreakType = {
'unknown': -1,
'none': 0,
'number': 100,
'word': 200,
'kana': 300,
'ideo': 400
};
/**
* Creates new v8BreakIterator based on current locale.
* @param {string} - type of segmentation. See constructor.
* @returns {Object} - new v8BreakIterator object.
*/
v8Locale.prototype.v8CreateBreakIterator = function(type) {
return new v8Locale.v8BreakIterator(this, type);
};
// TODO(jungshik): Set |collator.options| to actually recognized / resolved
// values.
/**
* Collator class implements locale-aware sort.
* @param {Object} locale - locale object to pass to collator implementation.
* @param {Object} settings - collation flags:
* - ignoreCase
* - ignoreAccents
* - numeric
* @private
* @constructor
*/
v8Locale.Collator = function(locale, settings) {
native function NativeJSCollator();
locale = v8Locale.__createLocaleOrDefault(locale);
var collator = NativeJSCollator(
locale.__icuLocaleID, v8Locale.__createSettingsOrDefault(settings, {}));
return collator;
};
/**
* Creates new Collator based on current locale.
* @param {Object} - collation flags. See constructor.
* @returns {Object} - new Collator object.
*/
v8Locale.prototype.createCollator = function(settings) {
return new v8Locale.Collator(this, settings);
};
/**
* DateTimeFormat class implements locale-aware date and time formatting.
* Constructor is not part of public API.
* @param {Object} locale - locale object to pass to formatter.
* @param {Object} settings - formatting flags:
* - skeleton
* - dateStyle
* - timeStyle
* @private
* @constructor
*/
v8Locale.__DateTimeFormat = function(locale, settings) {
native function NativeJSDateTimeFormat();
settings = v8Locale.__createSettingsOrDefault(settings, {});
var cleanSettings = {};
if (settings.hasOwnProperty('skeleton')) {
cleanSettings['skeleton'] = settings['skeleton'];
} else {
cleanSettings = {};
if (settings.hasOwnProperty('dateStyle')) {
var ds = settings['dateStyle'];
if (!/^(short|medium|long|full)$/.test(ds)) ds = 'short';
cleanSettings['dateStyle'] = ds;
} else if (settings.hasOwnProperty('dateType')) {
// Obsolete. New spec requires dateStyle, but we'll keep this around
// for current users.
// TODO(cira): Remove when all internal users switch to dateStyle.
var dt = settings['dateType'];
if (!/^(short|medium|long|full)$/.test(dt)) dt = 'short';
cleanSettings['dateStyle'] = dt;
}
if (settings.hasOwnProperty('timeStyle')) {
var ts = settings['timeStyle'];
if (!/^(short|medium|long|full)$/.test(ts)) ts = 'short';
cleanSettings['timeStyle'] = ts;
} else if (settings.hasOwnProperty('timeType')) {
// TODO(cira): Remove when all internal users switch to timeStyle.
var tt = settings['timeType'];
if (!/^(short|medium|long|full)$/.test(tt)) tt = 'short';
cleanSettings['timeStyle'] = tt;
}
}
// Default is to show short date and time.
if (!cleanSettings.hasOwnProperty('skeleton') &&
!cleanSettings.hasOwnProperty('dateStyle') &&
!cleanSettings.hasOwnProperty('timeStyle')) {
cleanSettings = {'dateStyle': 'short',
'timeStyle': 'short'};
}
locale = v8Locale.__createLocaleOrDefault(locale);
var formatter = NativeJSDateTimeFormat(locale.__icuLocaleID, cleanSettings);
// NativeJSDateTimeFormat creates formatter.options for us, we just need
// to append actual settings to it.
for (key in cleanSettings) {
formatter.options[key] = cleanSettings[key];
}
/**
* Clones existing date time format with possible overrides for some
* of the options.
* @param {!Object} overrideSettings - overrides for current format settings.
* @returns {Object} - new DateTimeFormat object.
* @public
*/
formatter.derive = function(overrideSettings) {
// To remove a setting user can specify undefined as its value. We'll remove
// it from the map in that case.
for (var prop in overrideSettings) {
if (settings.hasOwnProperty(prop) && !overrideSettings[prop]) {
delete settings[prop];
}
}
return new v8Locale.__DateTimeFormat(
locale, v8Locale.__createSettingsOrDefault(overrideSettings, settings));
};
return formatter;
};
/**
* Creates new DateTimeFormat based on current locale.
* @param {Object} - formatting flags. See constructor.
* @returns {Object} - new DateTimeFormat object.
*/
v8Locale.prototype.createDateTimeFormat = function(settings) {
return new v8Locale.__DateTimeFormat(this, settings);
};
/**
* NumberFormat class implements locale-aware number formatting.
* Constructor is not part of public API.
* @param {Object} locale - locale object to pass to formatter.
* @param {Object} settings - formatting flags:
* - skeleton
* - pattern
* - style - decimal, currency, percent or scientific
* - currencyCode - ISO 4217 3-letter currency code
* @private
* @constructor
*/
v8Locale.__NumberFormat = function(locale, settings) {
native function NativeJSNumberFormat();
settings = v8Locale.__createSettingsOrDefault(settings, {});
var cleanSettings = {};
if (settings.hasOwnProperty('skeleton')) {
// Assign skeleton to cleanSettings and fix invalid currency pattern
// if present - 'ooxo' becomes 'o'.
cleanSettings['skeleton'] =
settings['skeleton'].replace(/\u00a4+[^\u00a4]+\u00a4+/g, '\u00a4');
} else if (settings.hasOwnProperty('pattern')) {
cleanSettings['pattern'] = settings['pattern'];
} else if (settings.hasOwnProperty('style')) {
var style = settings['style'];
if (!/^(decimal|currency|percent|scientific)$/.test(style)) {
style = 'decimal';
}
cleanSettings['style'] = style;
}
// Default is to show decimal style.
if (!cleanSettings.hasOwnProperty('skeleton') &&
!cleanSettings.hasOwnProperty('pattern') &&
!cleanSettings.hasOwnProperty('style')) {
cleanSettings = {'style': 'decimal'};
}
// Add currency code if available and valid (3-letter ASCII code).
if (settings.hasOwnProperty('currencyCode') &&
/^[a-zA-Z]{3}$/.test(settings['currencyCode'])) {
cleanSettings['currencyCode'] = settings['currencyCode'].toUpperCase();
}
locale = v8Locale.__createLocaleOrDefault(locale);
// Pass in region ID for proper currency detection. Use ZZ if region is empty.
var region = locale.options.regionID !== '' ? locale.options.regionID : 'ZZ';
var formatter = NativeJSNumberFormat(
locale.__icuLocaleID, 'und_' + region, cleanSettings);
// ICU doesn't always uppercase the currency code.
if (formatter.options.hasOwnProperty('currencyCode')) {
formatter.options['currencyCode'] =
formatter.options['currencyCode'].toUpperCase();
}
for (key in cleanSettings) {
// Don't overwrite keys that are alredy in.
if (formatter.options.hasOwnProperty(key)) continue;
formatter.options[key] = cleanSettings[key];
}
/**
* Clones existing number format with possible overrides for some
* of the options.
* @param {!Object} overrideSettings - overrides for current format settings.
* @returns {Object} - new or cached NumberFormat object.
* @public
*/
formatter.derive = function(overrideSettings) {
// To remove a setting user can specify undefined as its value. We'll remove
// it from the map in that case.
for (var prop in overrideSettings) {
if (settings.hasOwnProperty(prop) && !overrideSettings[prop]) {
delete settings[prop];
}
}
return new v8Locale.__NumberFormat(
locale, v8Locale.__createSettingsOrDefault(overrideSettings, settings));
};
return formatter;
};
/**
* Creates new NumberFormat based on current locale.
* @param {Object} - formatting flags. See constructor.
* @returns {Object} - new or cached NumberFormat object.
*/
v8Locale.prototype.createNumberFormat = function(settings) {
return new v8Locale.__NumberFormat(this, settings);
};
/**
* Merges user settings and defaults.
* Settings that are not of object type are rejected.
* Actual property values are not validated, but whitespace is trimmed if they
* are strings.
* @param {!Object} settings - user provided settings.
* @param {!Object} defaults - default values for this type of settings.
* @returns {Object} - valid settings object.
* @private
*/
v8Locale.__createSettingsOrDefault = function(settings, defaults) {
if (!settings || typeof(settings) !== 'object' ) {
return defaults;
}
for (var key in defaults) {
if (!settings.hasOwnProperty(key)) {
settings[key] = defaults[key];
}
}
// Clean up settings.
for (var key in settings) {
// Trim whitespace.
if (typeof(settings[key]) === "string") {
settings[key] = settings[key].trim();
}
// Remove all properties that are set to undefined/null. This allows
// derive method to remove a setting we don't need anymore.
if (!settings[key]) {
delete settings[key];
}
}
return settings;
};
/**
* If locale is valid (defined and of v8Locale type) we return it. If not
* we create default locale and return it.
* @param {!Object} locale - user provided locale.
* @returns {Object} - v8Locale object.
* @private
*/
v8Locale.__createLocaleOrDefault = function(locale) {
if (!locale || !(locale instanceof v8Locale)) {
return new v8Locale();
} else {
return locale;
}
};

252
deps/v8/src/extensions/experimental/language-matcher.cc

@ -1,252 +0,0 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// TODO(cira): Remove LanguageMatcher from v8 when ICU implements
// language matching API.
#include "src/extensions/experimental/language-matcher.h"
#include <string.h>
#include "src/extensions/experimental/i18n-utils.h"
#include "unicode/datefmt.h" // For getAvailableLocales
#include "unicode/locid.h"
#include "unicode/uloc.h"
namespace v8 {
namespace internal {
const unsigned int LanguageMatcher::kLanguageWeight = 75;
const unsigned int LanguageMatcher::kScriptWeight = 20;
const unsigned int LanguageMatcher::kRegionWeight = 5;
const unsigned int LanguageMatcher::kThreshold = 50;
const unsigned int LanguageMatcher::kPositionBonus = 1;
const char* const LanguageMatcher::kDefaultLocale = "root";
static const char* GetLanguageException(const char*);
static bool BCP47ToICUFormat(const char*, char*);
static int CompareLocaleSubtags(const char*, const char*);
static bool BuildLocaleName(const char*, const char*, LocaleIDMatch*);
LocaleIDMatch::LocaleIDMatch()
: score(-1) {
I18NUtils::StrNCopy(
bcp47_id, ULOC_FULLNAME_CAPACITY, LanguageMatcher::kDefaultLocale);
I18NUtils::StrNCopy(
icu_id, ULOC_FULLNAME_CAPACITY, LanguageMatcher::kDefaultLocale);
}
LocaleIDMatch& LocaleIDMatch::operator=(const LocaleIDMatch& rhs) {
I18NUtils::StrNCopy(this->bcp47_id, ULOC_FULLNAME_CAPACITY, rhs.bcp47_id);
I18NUtils::StrNCopy(this->icu_id, ULOC_FULLNAME_CAPACITY, rhs.icu_id);
this->score = rhs.score;
return *this;
}
// static
void LanguageMatcher::GetBestMatchForPriorityList(
v8::Handle<v8::Array> locales, LocaleIDMatch* result) {
v8::HandleScope handle_scope;
unsigned int position_bonus = locales->Length() * kPositionBonus;
int max_score = 0;
LocaleIDMatch match;
for (unsigned int i = 0; i < locales->Length(); ++i) {
position_bonus -= kPositionBonus;
v8::TryCatch try_catch;
v8::Local<v8::Value> locale_id = locales->Get(v8::Integer::New(i));
// Return default if exception is raised when reading parameter.
if (try_catch.HasCaught()) break;
// JavaScript arrays can be heterogenous so check each item
// if it's a string.
if (!locale_id->IsString()) continue;
if (!CompareToSupportedLocaleIDList(locale_id->ToString(), &match)) {
continue;
}
// Skip items under threshold.
if (match.score < kThreshold) continue;
match.score += position_bonus;
if (match.score > max_score) {
*result = match;
max_score = match.score;
}
}
}
// static
void LanguageMatcher::GetBestMatchForString(
v8::Handle<v8::String> locale, LocaleIDMatch* result) {
LocaleIDMatch match;
if (CompareToSupportedLocaleIDList(locale, &match) &&
match.score >= kThreshold) {
*result = match;
}
}
// static
bool LanguageMatcher::CompareToSupportedLocaleIDList(
v8::Handle<v8::String> locale_id, LocaleIDMatch* result) {
static int32_t available_count = 0;
// Depending on how ICU data is built, locales returned by
// Locale::getAvailableLocale() are not guaranteed to support DateFormat,
// Collation and other services. We can call getAvailableLocale() of all the
// services we want to support and take the intersection of them all, but
// using DateFormat::getAvailableLocales() should suffice.
// TODO(cira): Maybe make this thread-safe?
static const icu::Locale* available_locales =
icu::DateFormat::getAvailableLocales(available_count);
// Skip this locale_id if it's not in ASCII.
static LocaleIDMatch default_match;
v8::String::AsciiValue ascii_value(locale_id);
if (*ascii_value == NULL) return false;
char locale[ULOC_FULLNAME_CAPACITY];
if (!BCP47ToICUFormat(*ascii_value, locale)) return false;
icu::Locale input_locale(locale);
// Position of the best match locale in list of available locales.
int position = -1;
const char* language = GetLanguageException(input_locale.getLanguage());
const char* script = input_locale.getScript();
const char* region = input_locale.getCountry();
for (int32_t i = 0; i < available_count; ++i) {
int current_score = 0;
int sign =
CompareLocaleSubtags(language, available_locales[i].getLanguage());
current_score += sign * kLanguageWeight;
sign = CompareLocaleSubtags(script, available_locales[i].getScript());
current_score += sign * kScriptWeight;
sign = CompareLocaleSubtags(region, available_locales[i].getCountry());
current_score += sign * kRegionWeight;
if (current_score >= kThreshold && current_score > result->score) {
result->score = current_score;
position = i;
}
}
// Didn't find any good matches so use defaults.
if (position == -1) return false;
return BuildLocaleName(available_locales[position].getBaseName(),
input_locale.getName(), result);
}
// For some unsupported language subtags it is better to fallback to related
// language that is supported than to default.
static const char* GetLanguageException(const char* language) {
// Serbo-croatian to Serbian.
if (!strcmp(language, "sh")) return "sr";
// Norweigan to Norweiaan to Norwegian Bokmal.
if (!strcmp(language, "no")) return "nb";
// Moldavian to Romanian.
if (!strcmp(language, "mo")) return "ro";
// Tagalog to Filipino.
if (!strcmp(language, "tl")) return "fil";
return language;
}
// Converts user input from BCP47 locale id format to ICU compatible format.
// Returns false if uloc_forLanguageTag call fails or if extension is too long.
static bool BCP47ToICUFormat(const char* locale_id, char* result) {
UErrorCode status = U_ZERO_ERROR;
int32_t locale_size = 0;
char locale[ULOC_FULLNAME_CAPACITY];
I18NUtils::StrNCopy(locale, ULOC_FULLNAME_CAPACITY, locale_id);
// uloc_forLanguageTag has a bug where long extension can crash the code.
// We need to check if extension part of language id conforms to the length.
// ICU bug: http://bugs.icu-project.org/trac/ticket/8519
const char* extension = strstr(locale_id, "-u-");
if (extension != NULL &&
strlen(extension) > ULOC_KEYWORD_AND_VALUES_CAPACITY) {
// Truncate to get non-crashing string, but still preserve base language.
int base_length = strlen(locale_id) - strlen(extension);
locale[base_length] = '\0';
}
uloc_forLanguageTag(locale, result, ULOC_FULLNAME_CAPACITY,
&locale_size, &status);
return !U_FAILURE(status);
}
// Compares locale id subtags.
// Returns 1 for match or -1 for mismatch.
static int CompareLocaleSubtags(const char* lsubtag, const char* rsubtag) {
return strcmp(lsubtag, rsubtag) == 0 ? 1 : -1;
}
// Builds a BCP47 compliant locale id from base name of matched locale and
// full user specified locale.
// Returns false if uloc_toLanguageTag failed to convert locale id.
// Example:
// base_name of matched locale (ICU ID): de_DE
// input_locale_name (ICU ID): de_AT@collation=phonebk
// result (ICU ID): de_DE@collation=phonebk
// result (BCP47 ID): de-DE-u-co-phonebk
static bool BuildLocaleName(const char* base_name,
const char* input_locale_name,
LocaleIDMatch* result) {
I18NUtils::StrNCopy(result->icu_id, ULOC_LANG_CAPACITY, base_name);
// Get extensions (if any) from the original locale.
const char* extension = strchr(input_locale_name, ULOC_KEYWORD_SEPARATOR);
if (extension != NULL) {
I18NUtils::StrNCopy(result->icu_id + strlen(base_name),
ULOC_KEYWORD_AND_VALUES_CAPACITY, extension);
} else {
I18NUtils::StrNCopy(result->icu_id, ULOC_LANG_CAPACITY, base_name);
}
// Convert ICU locale name into BCP47 format.
UErrorCode status = U_ZERO_ERROR;
uloc_toLanguageTag(result->icu_id, result->bcp47_id,
ULOC_FULLNAME_CAPACITY, false, &status);
return !U_FAILURE(status);
}
} } // namespace v8::internal

95
deps/v8/src/extensions/experimental/language-matcher.h

@ -1,95 +0,0 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_EXTENSIONS_EXPERIMENTAL_LANGUAGE_MATCHER_H_
#define V8_EXTENSIONS_EXPERIMENTAL_LANGUAGE_MATCHER_H_
#include "include/v8.h"
#include "unicode/uloc.h"
namespace v8 {
namespace internal {
struct LocaleIDMatch {
LocaleIDMatch();
LocaleIDMatch& operator=(const LocaleIDMatch& rhs);
// Bcp47 locale id - "de-Latn-DE-u-co-phonebk".
char bcp47_id[ULOC_FULLNAME_CAPACITY];
// ICU locale id - "de_Latn_DE@collation=phonebk".
char icu_id[ULOC_FULLNAME_CAPACITY];
// Score for this locale.
int score;
};
class LanguageMatcher {
public:
// Default locale.
static const char* const kDefaultLocale;
// Finds best supported locale for a given a list of locale identifiers.
// It preserves the extension for the locale id.
static void GetBestMatchForPriorityList(
v8::Handle<v8::Array> locale_list, LocaleIDMatch* result);
// Finds best supported locale for a single locale identifier.
// It preserves the extension for the locale id.
static void GetBestMatchForString(
v8::Handle<v8::String> locale_id, LocaleIDMatch* result);
private:
// If langauge subtags match add this amount to the score.
static const unsigned int kLanguageWeight;
// If script subtags match add this amount to the score.
static const unsigned int kScriptWeight;
// If region subtags match add this amount to the score.
static const unsigned int kRegionWeight;
// LocaleID match score has to be over this number to accept the match.
static const unsigned int kThreshold;
// For breaking ties in priority queue.
static const unsigned int kPositionBonus;
LanguageMatcher();
// Compares locale_id to the supported list of locales and returns best
// match.
// Returns false if it fails to convert locale id from ICU to BCP47 format.
static bool CompareToSupportedLocaleIDList(v8::Handle<v8::String> locale_id,
LocaleIDMatch* result);
};
} } // namespace v8::internal
#endif // V8_EXTENSIONS_EXPERIMENTAL_LANGUAGE_MATCHER_H_

374
deps/v8/src/extensions/experimental/number-format.cc

@ -1,374 +0,0 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "src/extensions/experimental/number-format.h"
#include <string.h>
#include "src/extensions/experimental/i18n-utils.h"
#include "unicode/dcfmtsym.h"
#include "unicode/decimfmt.h"
#include "unicode/locid.h"
#include "unicode/numfmt.h"
#include "unicode/uchar.h"
#include "unicode/ucurr.h"
#include "unicode/unum.h"
#include "unicode/uversion.h"
namespace v8 {
namespace internal {
const int NumberFormat::kCurrencyCodeLength = 4;
v8::Persistent<v8::FunctionTemplate> NumberFormat::number_format_template_;
static icu::DecimalFormat* CreateNumberFormat(v8::Handle<v8::String>,
v8::Handle<v8::String>,
v8::Handle<v8::Object>);
static icu::DecimalFormat* CreateFormatterFromSkeleton(
const icu::Locale&, const icu::UnicodeString&, UErrorCode*);
static icu::DecimalFormatSymbols* GetFormatSymbols(const icu::Locale&);
static bool GetCurrencyCode(const icu::Locale&,
const char* const,
v8::Handle<v8::Object>,
UChar*);
static v8::Handle<v8::Value> ThrowUnexpectedObjectError();
icu::DecimalFormat* NumberFormat::UnpackNumberFormat(
v8::Handle<v8::Object> obj) {
if (number_format_template_->HasInstance(obj)) {
return static_cast<icu::DecimalFormat*>(
obj->GetPointerFromInternalField(0));
}
return NULL;
}
void NumberFormat::DeleteNumberFormat(v8::Persistent<v8::Value> object,
void* param) {
v8::Persistent<v8::Object> persistent_object =
v8::Persistent<v8::Object>::Cast(object);
// First delete the hidden C++ object.
// Unpacking should never return NULL here. That would only happen if
// this method is used as the weak callback for persistent handles not
// pointing to a number formatter.
delete UnpackNumberFormat(persistent_object);
// Then dispose of the persistent handle to JS object.
persistent_object.Dispose();
}
v8::Handle<v8::Value> NumberFormat::Format(const v8::Arguments& args) {
v8::HandleScope handle_scope;
if (args.Length() != 1 || !args[0]->IsNumber()) {
// Just return NaN on invalid input.
return v8::String::New("NaN");
}
icu::DecimalFormat* number_format = UnpackNumberFormat(args.Holder());
if (!number_format) {
return ThrowUnexpectedObjectError();
}
// ICU will handle actual NaN value properly and return NaN string.
icu::UnicodeString result;
number_format->format(args[0]->NumberValue(), result);
return v8::String::New(
reinterpret_cast<const uint16_t*>(result.getBuffer()), result.length());
}
v8::Handle<v8::Value> NumberFormat::JSNumberFormat(const v8::Arguments& args) {
v8::HandleScope handle_scope;
// Expect locale id, region id and settings.
if (args.Length() != 3 ||
!args[0]->IsString() || !args[1]->IsString() || !args[2]->IsObject()) {
return v8::ThrowException(v8::Exception::SyntaxError(
v8::String::New("Locale, region and number settings are required.")));
}
icu::DecimalFormat* number_format = CreateNumberFormat(
args[0]->ToString(), args[1]->ToString(), args[2]->ToObject());
if (number_format_template_.IsEmpty()) {
v8::Local<v8::FunctionTemplate> raw_template(v8::FunctionTemplate::New());
raw_template->SetClassName(v8::String::New("v8Locale.NumberFormat"));
// Define internal field count on instance template.
v8::Local<v8::ObjectTemplate> object_template =
raw_template->InstanceTemplate();
// Set aside internal field for icu number formatter.
object_template->SetInternalFieldCount(1);
// Define all of the prototype methods on prototype template.
v8::Local<v8::ObjectTemplate> proto = raw_template->PrototypeTemplate();
proto->Set(v8::String::New("format"),
v8::FunctionTemplate::New(Format));
number_format_template_ =
v8::Persistent<v8::FunctionTemplate>::New(raw_template);
}
// Create an empty object wrapper.
v8::Local<v8::Object> local_object =
number_format_template_->GetFunction()->NewInstance();
v8::Persistent<v8::Object> wrapper =
v8::Persistent<v8::Object>::New(local_object);
// Set number formatter as internal field of the resulting JS object.
wrapper->SetPointerInInternalField(0, number_format);
// Create options key.
v8::Local<v8::Object> options = v8::Object::New();
// Show what ICU decided to use for easier problem tracking.
// Keep it as v8 specific extension.
icu::UnicodeString pattern;
number_format->toPattern(pattern);
options->Set(v8::String::New("v8ResolvedPattern"),
v8::String::New(reinterpret_cast<const uint16_t*>(
pattern.getBuffer()), pattern.length()));
// Set resolved currency code in options.currency if not empty.
icu::UnicodeString currency(number_format->getCurrency());
if (!currency.isEmpty()) {
options->Set(v8::String::New("currencyCode"),
v8::String::New(reinterpret_cast<const uint16_t*>(
currency.getBuffer()), currency.length()));
}
wrapper->Set(v8::String::New("options"), options);
// Make object handle weak so we can delete iterator once GC kicks in.
wrapper.MakeWeak(NULL, DeleteNumberFormat);
return wrapper;
}
// Returns DecimalFormat.
static icu::DecimalFormat* CreateNumberFormat(v8::Handle<v8::String> locale,
v8::Handle<v8::String> region,
v8::Handle<v8::Object> settings) {
v8::HandleScope handle_scope;
v8::String::AsciiValue ascii_locale(locale);
icu::Locale icu_locale(*ascii_locale);
// Make formatter from skeleton.
icu::DecimalFormat* number_format = NULL;
UErrorCode status = U_ZERO_ERROR;
icu::UnicodeString setting;
if (I18NUtils::ExtractStringSetting(settings, "skeleton", &setting)) {
// TODO(cira): Use ICU skeleton once
// http://bugs.icu-project.org/trac/ticket/8610 is resolved.
number_format = CreateFormatterFromSkeleton(icu_locale, setting, &status);
} else if (I18NUtils::ExtractStringSetting(settings, "pattern", &setting)) {
number_format =
new icu::DecimalFormat(setting, GetFormatSymbols(icu_locale), status);
} else if (I18NUtils::ExtractStringSetting(settings, "style", &setting)) {
if (setting == UNICODE_STRING_SIMPLE("currency")) {
number_format = static_cast<icu::DecimalFormat*>(
icu::NumberFormat::createCurrencyInstance(icu_locale, status));
} else if (setting == UNICODE_STRING_SIMPLE("percent")) {
number_format = static_cast<icu::DecimalFormat*>(
icu::NumberFormat::createPercentInstance(icu_locale, status));
} else if (setting == UNICODE_STRING_SIMPLE("scientific")) {
number_format = static_cast<icu::DecimalFormat*>(
icu::NumberFormat::createScientificInstance(icu_locale, status));
} else {
// Make it decimal in any other case.
number_format = static_cast<icu::DecimalFormat*>(
icu::NumberFormat::createInstance(icu_locale, status));
}
}
if (U_FAILURE(status)) {
delete number_format;
status = U_ZERO_ERROR;
number_format = static_cast<icu::DecimalFormat*>(
icu::NumberFormat::createInstance(icu_locale, status));
}
// Attach appropriate currency code to the formatter.
// It affects currency formatters only.
// Region is full language identifier in form 'und_' + region id.
v8::String::AsciiValue ascii_region(region);
UChar currency_code[NumberFormat::kCurrencyCodeLength];
if (GetCurrencyCode(icu_locale, *ascii_region, settings, currency_code)) {
number_format->setCurrency(currency_code, status);
}
return number_format;
}
// Generates ICU number format pattern from given skeleton.
// TODO(cira): Remove once ICU includes equivalent method
// (see http://bugs.icu-project.org/trac/ticket/8610).
static icu::DecimalFormat* CreateFormatterFromSkeleton(
const icu::Locale& icu_locale,
const icu::UnicodeString& skeleton,
UErrorCode* status) {
icu::DecimalFormat skeleton_format(
skeleton, GetFormatSymbols(icu_locale), *status);
// Find out if skeleton contains currency or percent symbol and create
// proper instance to tweak.
icu::DecimalFormat* base_format = NULL;
// UChar representation of U+00A4 currency symbol.
const UChar currency_symbol = 0xA4u;
int32_t index = skeleton.indexOf(currency_symbol);
if (index != -1) {
// Find how many U+00A4 are there. There is at least one.
// Case of non-consecutive U+00A4 is taken care of in i18n.js.
int32_t end_index = skeleton.lastIndexOf(currency_symbol, index);
#if (U_ICU_VERSION_MAJOR_NUM == 4) && (U_ICU_VERSION_MINOR_NUM <= 6)
icu::NumberFormat::EStyles style;
switch (end_index - index) {
case 0:
style = icu::NumberFormat::kCurrencyStyle;
break;
case 1:
style = icu::NumberFormat::kIsoCurrencyStyle;
break;
default:
style = icu::NumberFormat::kPluralCurrencyStyle;
}
#else // ICU version is 4.8 or above (we ignore versions below 4.0).
UNumberFormatStyle style;
switch (end_index - index) {
case 0:
style = UNUM_CURRENCY;
break;
case 1:
style = UNUM_CURRENCY_ISO;
break;
default:
style = UNUM_CURRENCY_PLURAL;
}
#endif
base_format = static_cast<icu::DecimalFormat*>(
icu::NumberFormat::createInstance(icu_locale, style, *status));
} else if (skeleton.indexOf('%') != -1) {
base_format = static_cast<icu::DecimalFormat*>(
icu::NumberFormat::createPercentInstance(icu_locale, *status));
} else {
// TODO(cira): Handle scientific skeleton.
base_format = static_cast<icu::DecimalFormat*>(
icu::NumberFormat::createInstance(icu_locale, *status));
}
if (U_FAILURE(*status)) {
delete base_format;
return NULL;
}
// Copy important information from skeleton to the new formatter.
// TODO(cira): copy rounding information from skeleton?
base_format->setGroupingUsed(skeleton_format.isGroupingUsed());
base_format->setMinimumIntegerDigits(
skeleton_format.getMinimumIntegerDigits());
base_format->setMinimumFractionDigits(
skeleton_format.getMinimumFractionDigits());
base_format->setMaximumFractionDigits(
skeleton_format.getMaximumFractionDigits());
return base_format;
}
// Gets decimal symbols for a locale.
static icu::DecimalFormatSymbols* GetFormatSymbols(
const icu::Locale& icu_locale) {
UErrorCode status = U_ZERO_ERROR;
icu::DecimalFormatSymbols* symbols =
new icu::DecimalFormatSymbols(icu_locale, status);
if (U_FAILURE(status)) {
delete symbols;
// Use symbols from default locale.
symbols = new icu::DecimalFormatSymbols(status);
}
return symbols;
}
// Gets currency ISO 4217 3-letter code.
// Check currencyCode setting first, then @currency=code and in the end
// try to infer currency code from locale in the form 'und_' + region id.
// Returns false in case of error.
static bool GetCurrencyCode(const icu::Locale& icu_locale,
const char* const und_region_locale,
v8::Handle<v8::Object> settings,
UChar* code) {
UErrorCode status = U_ZERO_ERROR;
// If there is user specified currency code, use it.
icu::UnicodeString currency;
if (I18NUtils::ExtractStringSetting(settings, "currencyCode", &currency)) {
currency.extract(code, NumberFormat::kCurrencyCodeLength, status);
return true;
}
// If ICU locale has -cu- currency code use it.
char currency_code[NumberFormat::kCurrencyCodeLength];
int32_t length = icu_locale.getKeywordValue(
"currency", currency_code, NumberFormat::kCurrencyCodeLength, status);
if (length != 0) {
I18NUtils::AsciiToUChar(currency_code, length + 1,
code, NumberFormat::kCurrencyCodeLength);
return true;
}
// Otherwise infer currency code from the region id.
ucurr_forLocale(
und_region_locale, code, NumberFormat::kCurrencyCodeLength, &status);
return !!U_SUCCESS(status);
}
// Throws a JavaScript exception.
static v8::Handle<v8::Value> ThrowUnexpectedObjectError() {
// Returns undefined, and schedules an exception to be thrown.
return v8::ThrowException(v8::Exception::Error(
v8::String::New("NumberFormat method called on an object "
"that is not a NumberFormat.")));
}
} } // namespace v8::internal

71
deps/v8/src/extensions/experimental/number-format.h

@ -1,71 +0,0 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_EXTENSIONS_EXPERIMENTAL_NUMBER_FORMAT_H_
#define V8_EXTENSIONS_EXPERIMENTAL_NUMBER_FORMAT_H_
#include "include/v8.h"
#include "unicode/uversion.h"
namespace U_ICU_NAMESPACE {
class DecimalFormat;
}
namespace v8 {
namespace internal {
class NumberFormat {
public:
// 3-letter ISO 4217 currency code plus \0.
static const int kCurrencyCodeLength;
static v8::Handle<v8::Value> JSNumberFormat(const v8::Arguments& args);
// Helper methods for various bindings.
// Unpacks date format object from corresponding JavaScript object.
static icu::DecimalFormat* UnpackNumberFormat(
v8::Handle<v8::Object> obj);
// Release memory we allocated for the NumberFormat once the JS object that
// holds the pointer gets garbage collected.
static void DeleteNumberFormat(v8::Persistent<v8::Value> object,
void* param);
// Formats number and returns corresponding string.
static v8::Handle<v8::Value> Format(const v8::Arguments& args);
private:
NumberFormat();
static v8::Persistent<v8::FunctionTemplate> number_format_template_;
};
} } // namespace v8::internal
#endif // V8_EXTENSIONS_EXPERIMENTAL_NUMBER_FORMAT_H_

2
deps/v8/src/factory.h

@ -233,7 +233,7 @@ class Factory {
Handle<FixedDoubleArray> CopyFixedDoubleArray( Handle<FixedDoubleArray> CopyFixedDoubleArray(
Handle<FixedDoubleArray> array); Handle<FixedDoubleArray> array);
// Numbers (eg, literals) are pretenured by the parser. // Numbers (e.g. literals) are pretenured by the parser.
Handle<Object> NewNumber(double value, Handle<Object> NewNumber(double value,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);

10
deps/v8/src/full-codegen.h

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -142,11 +142,13 @@ class FullCodeGenerator: public AstVisitor {
return previous_; return previous_;
} }
protected: protected:
MacroAssembler* masm() { return codegen_->masm(); } MacroAssembler* masm() { return codegen_->masm(); }
FullCodeGenerator* codegen_; FullCodeGenerator* codegen_;
NestedStatement* previous_; NestedStatement* previous_;
private:
DISALLOW_COPY_AND_ASSIGN(NestedStatement); DISALLOW_COPY_AND_ASSIGN(NestedStatement);
}; };
@ -618,8 +620,8 @@ class FullCodeGenerator: public AstVisitor {
Label** if_false, Label** if_false,
Label** fall_through) const = 0; Label** fall_through) const = 0;
// Returns true if we are evaluating only for side effects (ie if the result // Returns true if we are evaluating only for side effects (i.e. if the
// will be discarded). // result will be discarded).
virtual bool IsEffect() const { return false; } virtual bool IsEffect() const { return false; }
// Returns true if we are evaluating for the value (in accu/on stack). // Returns true if we are evaluating for the value (in accu/on stack).

2
deps/v8/src/global-handles.cc

@ -232,7 +232,7 @@ class GlobalHandles::Node {
VMState state(isolate, EXTERNAL); VMState state(isolate, EXTERNAL);
func(object, par); func(object, par);
} }
// Absense of explicit cleanup or revival of weak handle // Absence of explicit cleanup or revival of weak handle
// in most of the cases would lead to memory leak. // in most of the cases would lead to memory leak.
ASSERT(state_ != NEAR_DEATH); ASSERT(state_ != NEAR_DEATH);
return true; return true;

49
deps/v8/src/heap.cc

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -583,7 +583,9 @@ void Heap::ReserveSpace(
PagedSpace* cell_space = Heap::cell_space(); PagedSpace* cell_space = Heap::cell_space();
LargeObjectSpace* lo_space = Heap::lo_space(); LargeObjectSpace* lo_space = Heap::lo_space();
bool gc_performed = true; bool gc_performed = true;
while (gc_performed) { int counter = 0;
static const int kThreshold = 20;
while (gc_performed && counter++ < kThreshold) {
gc_performed = false; gc_performed = false;
if (!new_space->ReserveSpace(new_space_size)) { if (!new_space->ReserveSpace(new_space_size)) {
Heap::CollectGarbage(NEW_SPACE); Heap::CollectGarbage(NEW_SPACE);
@ -622,6 +624,11 @@ void Heap::ReserveSpace(
gc_performed = true; gc_performed = true;
} }
} }
if (gc_performed) {
// Failed to reserve the space after several attempts.
V8::FatalProcessOutOfMemory("Heap::ReserveSpace");
}
} }
@ -872,6 +879,8 @@ void Heap::MarkCompact(GCTracer* tracer) {
isolate_->counters()->objs_since_last_full()->Set(0); isolate_->counters()->objs_since_last_full()->Set(0);
contexts_disposed_ = 0; contexts_disposed_ = 0;
isolate_->set_context_exit_happened(false);
} }
@ -1552,7 +1561,7 @@ class ScavengingVisitor : public StaticVisitorBase {
if (marks_handling == TRANSFER_MARKS) { if (marks_handling == TRANSFER_MARKS) {
if (Marking::TransferColor(source, target)) { if (Marking::TransferColor(source, target)) {
MemoryChunk::IncrementLiveBytes(target->address(), size); MemoryChunk::IncrementLiveBytesFromGC(target->address(), size);
} }
} }
} }
@ -2923,8 +2932,8 @@ MaybeObject* Heap::AllocateConsString(String* first, String* second) {
bool is_ascii_data_in_two_byte_string = false; bool is_ascii_data_in_two_byte_string = false;
if (!is_ascii) { if (!is_ascii) {
// At least one of the strings uses two-byte representation so we // At least one of the strings uses two-byte representation so we
// can't use the fast case code for short ascii strings below, but // can't use the fast case code for short ASCII strings below, but
// we can try to save memory if all chars actually fit in ascii. // we can try to save memory if all chars actually fit in ASCII.
is_ascii_data_in_two_byte_string = is_ascii_data_in_two_byte_string =
first->HasOnlyAsciiChars() && second->HasOnlyAsciiChars(); first->HasOnlyAsciiChars() && second->HasOnlyAsciiChars();
if (is_ascii_data_in_two_byte_string) { if (is_ascii_data_in_two_byte_string) {
@ -2933,9 +2942,9 @@ MaybeObject* Heap::AllocateConsString(String* first, String* second) {
} }
// If the resulting string is small make a flat string. // If the resulting string is small make a flat string.
if (length < String::kMinNonFlatLength) { if (length < ConsString::kMinLength) {
// Note that neither of the two inputs can be a slice because: // Note that neither of the two inputs can be a slice because:
STATIC_ASSERT(String::kMinNonFlatLength <= SlicedString::kMinLength); STATIC_ASSERT(ConsString::kMinLength <= SlicedString::kMinLength);
ASSERT(first->IsFlat()); ASSERT(first->IsFlat());
ASSERT(second->IsFlat()); ASSERT(second->IsFlat());
if (is_ascii) { if (is_ascii) {
@ -3011,7 +3020,7 @@ MaybeObject* Heap::AllocateSubString(String* buffer,
int end, int end,
PretenureFlag pretenure) { PretenureFlag pretenure) {
int length = end - start; int length = end - start;
if (length == 0) { if (length <= 0) {
return empty_string(); return empty_string();
} else if (length == 1) { } else if (length == 1) {
return LookupSingleCharacterStringFromCode(buffer->Get(start)); return LookupSingleCharacterStringFromCode(buffer->Get(start));
@ -3635,8 +3644,8 @@ void Heap::InitializeJSObjectFromMap(JSObject* obj,
// TODO(1240798): Initialize the object's body using valid initial values // TODO(1240798): Initialize the object's body using valid initial values
// according to the object's initial map. For example, if the map's // according to the object's initial map. For example, if the map's
// instance type is JS_ARRAY_TYPE, the length field should be initialized // instance type is JS_ARRAY_TYPE, the length field should be initialized
// to a number (eg, Smi::FromInt(0)) and the elements initialized to a // to a number (e.g. Smi::FromInt(0)) and the elements initialized to a
// fixed array (eg, Heap::empty_fixed_array()). Currently, the object // fixed array (e.g. Heap::empty_fixed_array()). Currently, the object
// verification code has to cope with (temporarily) invalid objects. See // verification code has to cope with (temporarily) invalid objects. See
// for example, JSArray::JSArrayVerify). // for example, JSArray::JSArrayVerify).
Object* filler; Object* filler;
@ -4103,7 +4112,7 @@ MaybeObject* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer,
ASSERT(chars >= 0); ASSERT(chars >= 0);
// Ensure the chars matches the number of characters in the buffer. // Ensure the chars matches the number of characters in the buffer.
ASSERT(static_cast<unsigned>(chars) == buffer->Length()); ASSERT(static_cast<unsigned>(chars) == buffer->Length());
// Determine whether the string is ascii. // Determine whether the string is ASCII.
bool is_ascii = true; bool is_ascii = true;
while (buffer->has_more()) { while (buffer->has_more()) {
if (buffer->GetNext() > unibrow::Utf8::kMaxOneByteChar) { if (buffer->GetNext() > unibrow::Utf8::kMaxOneByteChar) {
@ -5596,7 +5605,7 @@ bool Heap::SetUp(bool create_heap_objects) {
// goes wrong, just return false. The caller should check the results and // goes wrong, just return false. The caller should check the results and
// call Heap::TearDown() to release allocated memory. // call Heap::TearDown() to release allocated memory.
// //
// If the heap is not yet configured (eg, through the API), configure it. // If the heap is not yet configured (e.g. through the API), configure it.
// Configuration is based on the flags new-space-size (really the semispace // Configuration is based on the flags new-space-size (really the semispace
// size) and old-space-size if set or the initial values of semispace_size_ // size) and old-space-size if set or the initial values of semispace_size_
// and old_generation_size_ otherwise. // and old_generation_size_ otherwise.
@ -6513,11 +6522,17 @@ int KeyedLookupCache::Hash(Map* map, String* name) {
int KeyedLookupCache::Lookup(Map* map, String* name) { int KeyedLookupCache::Lookup(Map* map, String* name) {
int index = Hash(map, name); int index = (Hash(map, name) & kHashMask);
Key& key = keys_[index]; Key& key = keys_[index];
if ((key.map == map) && key.name->Equals(name)) { if ((key.map == map) && key.name->Equals(name)) {
return field_offsets_[index]; return field_offsets_[index];
} }
ASSERT(kEntriesPerBucket == 2); // There are two entries to check.
// First entry in the bucket missed, check the second.
Key& key2 = keys_[index + 1];
if ((key2.map == map) && key2.name->Equals(name)) {
return field_offsets_[index + 1];
}
return kNotFound; return kNotFound;
} }
@ -6525,8 +6540,14 @@ int KeyedLookupCache::Lookup(Map* map, String* name) {
void KeyedLookupCache::Update(Map* map, String* name, int field_offset) { void KeyedLookupCache::Update(Map* map, String* name, int field_offset) {
String* symbol; String* symbol;
if (HEAP->LookupSymbolIfExists(name, &symbol)) { if (HEAP->LookupSymbolIfExists(name, &symbol)) {
int index = Hash(map, symbol); int index = (Hash(map, symbol) & kHashMask);
Key& key = keys_[index]; Key& key = keys_[index];
Key& key2 = keys_[index + 1]; // Second entry in the bucket.
// Demote the first entry to the second in the bucket.
key2.map = key.map;
key2.name = key.name;
field_offsets_[index + 1] = field_offsets_[index];
// Write the new first entry.
key.map = map; key.map = map;
key.name = symbol; key.name = symbol;
field_offsets_[index] = field_offset; field_offsets_[index] = field_offset;

13
deps/v8/src/heap.h

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -690,7 +690,7 @@ class Heap {
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
// Computes a single character string where the character has code. // Computes a single character string where the character has code.
// A cache is used for ascii codes. // A cache is used for ASCII codes.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. Please note this does not perform a garbage collection. // failed. Please note this does not perform a garbage collection.
MUST_USE_RESULT MaybeObject* LookupSingleCharacterStringFromCode( MUST_USE_RESULT MaybeObject* LookupSingleCharacterStringFromCode(
@ -2135,9 +2135,11 @@ class KeyedLookupCache {
// Clear the cache. // Clear the cache.
void Clear(); void Clear();
static const int kLength = 64; static const int kLength = 128;
static const int kCapacityMask = kLength - 1; static const int kCapacityMask = kLength - 1;
static const int kMapHashShift = 2; static const int kMapHashShift = 5;
static const int kHashMask = -2; // Zero the last bit.
static const int kEntriesPerBucket = 2;
static const int kNotFound = -1; static const int kNotFound = -1;
private: private:
@ -2376,7 +2378,7 @@ class GCTracer BASE_EMBEDDED {
intptr_t start_size_; // Size of objects in heap set in constructor. intptr_t start_size_; // Size of objects in heap set in constructor.
GarbageCollector collector_; // Type of collector. GarbageCollector collector_; // Type of collector.
// A count (including this one, eg, the first collection is 1) of the // A count (including this one, e.g. the first collection is 1) of the
// number of garbage collections. // number of garbage collections.
unsigned int gc_count_; unsigned int gc_count_;
@ -2613,6 +2615,7 @@ class PathTracer : public ObjectVisitor {
AssertNoAllocation no_alloc; // i.e. no gc allowed. AssertNoAllocation no_alloc; // i.e. no gc allowed.
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PathTracer); DISALLOW_IMPLICIT_CONSTRUCTORS(PathTracer);
}; };
#endif // DEBUG || LIVE_OBJECT_LIST #endif // DEBUG || LIVE_OBJECT_LIST

24
deps/v8/src/hydrogen-instructions.cc

@ -416,18 +416,18 @@ void HValue::PrintRangeTo(StringStream* stream) {
void HValue::PrintChangesTo(StringStream* stream) { void HValue::PrintChangesTo(StringStream* stream) {
int changes_flags = ChangesFlags(); GVNFlagSet changes_flags = ChangesFlags();
if (changes_flags == 0) return; if (changes_flags.IsEmpty()) return;
stream->Add(" changes["); stream->Add(" changes[");
if (changes_flags == AllSideEffects()) { if (changes_flags == AllSideEffectsFlagSet()) {
stream->Add("*"); stream->Add("*");
} else { } else {
bool add_comma = false; bool add_comma = false;
#define PRINT_DO(type) \ #define PRINT_DO(type) \
if (changes_flags & (1 << kChanges##type)) { \ if (changes_flags.Contains(kChanges##type)) { \
if (add_comma) stream->Add(","); \ if (add_comma) stream->Add(","); \
add_comma = true; \ add_comma = true; \
stream->Add(#type); \ stream->Add(#type); \
} }
GVN_FLAG_LIST(PRINT_DO); GVN_FLAG_LIST(PRINT_DO);
#undef PRINT_DO #undef PRINT_DO
@ -1408,21 +1408,21 @@ HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
SetOperandAt(0, context); SetOperandAt(0, context);
SetOperandAt(1, object); SetOperandAt(1, object);
set_representation(Representation::Tagged()); set_representation(Representation::Tagged());
SetFlag(kDependsOnMaps); SetGVNFlag(kDependsOnMaps);
for (int i = 0; for (int i = 0;
i < types->length() && types_.length() < kMaxLoadPolymorphism; i < types->length() && types_.length() < kMaxLoadPolymorphism;
++i) { ++i) {
Handle<Map> map = types->at(i); Handle<Map> map = types->at(i);
LookupResult lookup(map->GetIsolate()); LookupResult lookup(map->GetIsolate());
map->LookupInDescriptors(NULL, *name, &lookup); map->LookupInDescriptors(NULL, *name, &lookup);
if (lookup.IsProperty()) { if (lookup.IsFound()) {
switch (lookup.type()) { switch (lookup.type()) {
case FIELD: { case FIELD: {
int index = lookup.GetLocalFieldIndexFromMap(*map); int index = lookup.GetLocalFieldIndexFromMap(*map);
if (index < 0) { if (index < 0) {
SetFlag(kDependsOnInobjectFields); SetGVNFlag(kDependsOnInobjectFields);
} else { } else {
SetFlag(kDependsOnBackingStoreFields); SetGVNFlag(kDependsOnBackingStoreFields);
} }
types_.Add(types->at(i)); types_.Add(types->at(i));
break; break;

138
deps/v8/src/hydrogen-instructions.h

@ -492,18 +492,26 @@ class HUseIterator BASE_EMBEDDED {
}; };
// There must be one corresponding kDepends flag for every kChanges flag and
// the order of the kChanges flags must be exactly the same as of the kDepends
// flags.
enum GVNFlag {
// Declare global value numbering flags.
#define DECLARE_FLAG(type) kChanges##type, kDependsOn##type,
GVN_FLAG_LIST(DECLARE_FLAG)
#undef DECLARE_FLAG
kAfterLastFlag,
kLastFlag = kAfterLastFlag - 1
};
typedef EnumSet<GVNFlag> GVNFlagSet;
class HValue: public ZoneObject { class HValue: public ZoneObject {
public: public:
static const int kNoNumber = -1; static const int kNoNumber = -1;
// There must be one corresponding kDepends flag for every kChanges flag and
// the order of the kChanges flags must be exactly the same as of the kDepends
// flags.
enum Flag { enum Flag {
// Declare global value numbering flags.
#define DECLARE_DO(type) kChanges##type, kDependsOn##type,
GVN_FLAG_LIST(DECLARE_DO)
#undef DECLARE_DO
kFlexibleRepresentation, kFlexibleRepresentation,
// Participate in Global Value Numbering, i.e. elimination of // Participate in Global Value Numbering, i.e. elimination of
// unnecessary recomputations. If an instruction sets this flag, it must // unnecessary recomputations. If an instruction sets this flag, it must
@ -523,8 +531,8 @@ class HValue: public ZoneObject {
static const int kChangesToDependsFlagsLeftShift = 1; static const int kChangesToDependsFlagsLeftShift = 1;
static int ConvertChangesToDependsFlags(int flags) { static GVNFlagSet ConvertChangesToDependsFlags(GVNFlagSet flags) {
return flags << kChangesToDependsFlagsLeftShift; return GVNFlagSet(flags.ToIntegral() << kChangesToDependsFlagsLeftShift);
} }
static HValue* cast(HValue* value) { return value; } static HValue* cast(HValue* value) { return value; }
@ -622,16 +630,32 @@ class HValue: public ZoneObject {
void ClearFlag(Flag f) { flags_ &= ~(1 << f); } void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; } bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
void SetAllSideEffects() { flags_ |= AllSideEffects(); } GVNFlagSet gvn_flags() const { return gvn_flags_; }
void ClearAllSideEffects() { flags_ &= ~AllSideEffects(); } void SetGVNFlag(GVNFlag f) { gvn_flags_.Add(f); }
bool HasSideEffects() const { return (flags_ & AllSideEffects()) != 0; } void ClearGVNFlag(GVNFlag f) { gvn_flags_.Remove(f); }
bool CheckGVNFlag(GVNFlag f) const { return gvn_flags_.Contains(f); }
void SetAllSideEffects() { gvn_flags_.Add(AllSideEffectsFlagSet()); }
void ClearAllSideEffects() {
gvn_flags_.Remove(AllSideEffectsFlagSet());
}
bool HasSideEffects() const {
return gvn_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
}
bool HasObservableSideEffects() const { bool HasObservableSideEffects() const {
return (flags_ & ObservableSideEffects()) != 0; return gvn_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
} }
int ChangesFlags() const { return flags_ & ChangesFlagsMask(); } GVNFlagSet ChangesFlags() const {
int ObservableChangesFlags() const { GVNFlagSet result = gvn_flags_;
return flags_ & ChangesFlagsMask() & ObservableSideEffects(); result.Intersect(AllChangesFlagSet());
return result;
}
GVNFlagSet ObservableChangesFlags() const {
GVNFlagSet result = gvn_flags_;
result.Intersect(AllChangesFlagSet());
result.Intersect(AllObservableSideEffectsFlagSet());
return result;
} }
Range* range() const { return range_; } Range* range() const { return range_; }
@ -697,25 +721,28 @@ class HValue: public ZoneObject {
representation_ = r; representation_ = r;
} }
private: static GVNFlagSet AllChangesFlagSet() {
static int ChangesFlagsMask() { GVNFlagSet result;
int result = 0;
// Create changes mask. // Create changes mask.
#define ADD_FLAG(type) result |= (1 << kChanges##type); #define ADD_FLAG(type) result.Add(kChanges##type);
GVN_FLAG_LIST(ADD_FLAG) GVN_FLAG_LIST(ADD_FLAG)
#undef ADD_FLAG #undef ADD_FLAG
return result; return result;
} }
// A flag mask to mark an instruction as having arbitrary side effects. // A flag mask to mark an instruction as having arbitrary side effects.
static int AllSideEffects() { static GVNFlagSet AllSideEffectsFlagSet() {
return ChangesFlagsMask() & ~(1 << kChangesOsrEntries); GVNFlagSet result = AllChangesFlagSet();
result.Remove(kChangesOsrEntries);
return result;
} }
// A flag mask of all side effects that can make observable changes in // A flag mask of all side effects that can make observable changes in
// an executing program (i.e. are not safe to repeat, move or remove); // an executing program (i.e. are not safe to repeat, move or remove);
static int ObservableSideEffects() { static GVNFlagSet AllObservableSideEffectsFlagSet() {
return ChangesFlagsMask() & ~(1 << kChangesElementsKind); GVNFlagSet result = AllChangesFlagSet();
result.Remove(kChangesElementsKind);
return result;
} }
// Remove the matching use from the use list if present. Returns the // Remove the matching use from the use list if present. Returns the
@ -735,6 +762,7 @@ class HValue: public ZoneObject {
HUseListNode* use_list_; HUseListNode* use_list_;
Range* range_; Range* range_;
int flags_; int flags_;
GVNFlagSet gvn_flags_;
DISALLOW_COPY_AND_ASSIGN(HValue); DISALLOW_COPY_AND_ASSIGN(HValue);
}; };
@ -772,7 +800,7 @@ class HInstruction: public HValue {
: next_(NULL), : next_(NULL),
previous_(NULL), previous_(NULL),
position_(RelocInfo::kNoPosition) { position_(RelocInfo::kNoPosition) {
SetFlag(kDependsOnOsrEntries); SetGVNFlag(kDependsOnOsrEntries);
} }
virtual void DeleteFromGraph() { Unlink(); } virtual void DeleteFromGraph() { Unlink(); }
@ -1716,8 +1744,8 @@ class HJSArrayLength: public HTemplateInstruction<2> {
SetOperandAt(1, typecheck); SetOperandAt(1, typecheck);
set_representation(Representation::Tagged()); set_representation(Representation::Tagged());
SetFlag(kUseGVN); SetFlag(kUseGVN);
SetFlag(kDependsOnArrayLengths); SetGVNFlag(kDependsOnArrayLengths);
SetFlag(kDependsOnMaps); SetGVNFlag(kDependsOnMaps);
} }
virtual Representation RequiredInputRepresentation(int index) { virtual Representation RequiredInputRepresentation(int index) {
@ -1741,7 +1769,7 @@ class HFixedArrayBaseLength: public HUnaryOperation {
explicit HFixedArrayBaseLength(HValue* value) : HUnaryOperation(value) { explicit HFixedArrayBaseLength(HValue* value) : HUnaryOperation(value) {
set_representation(Representation::Tagged()); set_representation(Representation::Tagged());
SetFlag(kUseGVN); SetFlag(kUseGVN);
SetFlag(kDependsOnArrayLengths); SetGVNFlag(kDependsOnArrayLengths);
} }
virtual Representation RequiredInputRepresentation(int index) { virtual Representation RequiredInputRepresentation(int index) {
@ -1760,7 +1788,7 @@ class HElementsKind: public HUnaryOperation {
explicit HElementsKind(HValue* value) : HUnaryOperation(value) { explicit HElementsKind(HValue* value) : HUnaryOperation(value) {
set_representation(Representation::Integer32()); set_representation(Representation::Integer32());
SetFlag(kUseGVN); SetFlag(kUseGVN);
SetFlag(kDependsOnElementsKind); SetGVNFlag(kDependsOnElementsKind);
} }
virtual Representation RequiredInputRepresentation(int index) { virtual Representation RequiredInputRepresentation(int index) {
@ -1886,8 +1914,8 @@ class HLoadElements: public HUnaryOperation {
explicit HLoadElements(HValue* value) : HUnaryOperation(value) { explicit HLoadElements(HValue* value) : HUnaryOperation(value) {
set_representation(Representation::Tagged()); set_representation(Representation::Tagged());
SetFlag(kUseGVN); SetFlag(kUseGVN);
SetFlag(kDependsOnMaps); SetGVNFlag(kDependsOnMaps);
SetFlag(kDependsOnElementsKind); SetGVNFlag(kDependsOnElementsKind);
} }
virtual Representation RequiredInputRepresentation(int index) { virtual Representation RequiredInputRepresentation(int index) {
@ -1937,7 +1965,7 @@ class HCheckMap: public HTemplateInstruction<2> {
SetOperandAt(1, typecheck != NULL ? typecheck : value); SetOperandAt(1, typecheck != NULL ? typecheck : value);
set_representation(Representation::Tagged()); set_representation(Representation::Tagged());
SetFlag(kUseGVN); SetFlag(kUseGVN);
SetFlag(kDependsOnMaps); SetGVNFlag(kDependsOnMaps);
has_element_transitions_ = has_element_transitions_ =
map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL) != NULL || map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL) != NULL ||
map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL) != NULL; map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL) != NULL;
@ -2105,7 +2133,7 @@ class HCheckPrototypeMaps: public HTemplateInstruction<0> {
HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder) HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder)
: prototype_(prototype), holder_(holder) { : prototype_(prototype), holder_(holder) {
SetFlag(kUseGVN); SetFlag(kUseGVN);
SetFlag(kDependsOnMaps); SetGVNFlag(kDependsOnMaps);
} }
#ifdef DEBUG #ifdef DEBUG
@ -3255,7 +3283,7 @@ class HSar: public HBitwiseBinaryOperation {
class HOsrEntry: public HTemplateInstruction<0> { class HOsrEntry: public HTemplateInstruction<0> {
public: public:
explicit HOsrEntry(int ast_id) : ast_id_(ast_id) { explicit HOsrEntry(int ast_id) : ast_id_(ast_id) {
SetFlag(kChangesOsrEntries); SetGVNFlag(kChangesOsrEntries);
} }
int ast_id() const { return ast_id_; } int ast_id() const { return ast_id_; }
@ -3343,7 +3371,7 @@ class HLoadGlobalCell: public HTemplateInstruction<0> {
: cell_(cell), details_(details) { : cell_(cell), details_(details) {
set_representation(Representation::Tagged()); set_representation(Representation::Tagged());
SetFlag(kUseGVN); SetFlag(kUseGVN);
SetFlag(kDependsOnGlobalVars); SetGVNFlag(kDependsOnGlobalVars);
} }
Handle<JSGlobalPropertyCell> cell() const { return cell_; } Handle<JSGlobalPropertyCell> cell() const { return cell_; }
@ -3422,7 +3450,7 @@ class HStoreGlobalCell: public HUnaryOperation {
: HUnaryOperation(value), : HUnaryOperation(value),
cell_(cell), cell_(cell),
details_(details) { details_(details) {
SetFlag(kChangesGlobalVars); SetGVNFlag(kChangesGlobalVars);
} }
Handle<JSGlobalPropertyCell> cell() const { return cell_; } Handle<JSGlobalPropertyCell> cell() const { return cell_; }
@ -3513,7 +3541,7 @@ class HLoadContextSlot: public HUnaryOperation {
} }
set_representation(Representation::Tagged()); set_representation(Representation::Tagged());
SetFlag(kUseGVN); SetFlag(kUseGVN);
SetFlag(kDependsOnContextSlots); SetGVNFlag(kDependsOnContextSlots);
} }
int slot_index() const { return slot_index_; } int slot_index() const { return slot_index_; }
@ -3566,7 +3594,7 @@ class HStoreContextSlot: public HTemplateInstruction<2> {
: slot_index_(slot_index), mode_(mode) { : slot_index_(slot_index), mode_(mode) {
SetOperandAt(0, context); SetOperandAt(0, context);
SetOperandAt(1, value); SetOperandAt(1, value);
SetFlag(kChangesContextSlots); SetGVNFlag(kChangesContextSlots);
} }
HValue* context() { return OperandAt(0); } HValue* context() { return OperandAt(0); }
@ -3608,11 +3636,11 @@ class HLoadNamedField: public HUnaryOperation {
offset_(offset) { offset_(offset) {
set_representation(Representation::Tagged()); set_representation(Representation::Tagged());
SetFlag(kUseGVN); SetFlag(kUseGVN);
SetFlag(kDependsOnMaps); SetGVNFlag(kDependsOnMaps);
if (is_in_object) { if (is_in_object) {
SetFlag(kDependsOnInobjectFields); SetGVNFlag(kDependsOnInobjectFields);
} else { } else {
SetFlag(kDependsOnBackingStoreFields); SetGVNFlag(kDependsOnBackingStoreFields);
} }
} }
@ -3706,7 +3734,7 @@ class HLoadFunctionPrototype: public HUnaryOperation {
: HUnaryOperation(function) { : HUnaryOperation(function) {
set_representation(Representation::Tagged()); set_representation(Representation::Tagged());
SetFlag(kUseGVN); SetFlag(kUseGVN);
SetFlag(kDependsOnCalls); SetGVNFlag(kDependsOnCalls);
} }
HValue* function() { return OperandAt(0); } HValue* function() { return OperandAt(0); }
@ -3728,7 +3756,7 @@ class HLoadKeyedFastElement: public HTemplateInstruction<2> {
SetOperandAt(0, obj); SetOperandAt(0, obj);
SetOperandAt(1, key); SetOperandAt(1, key);
set_representation(Representation::Tagged()); set_representation(Representation::Tagged());
SetFlag(kDependsOnArrayElements); SetGVNFlag(kDependsOnArrayElements);
SetFlag(kUseGVN); SetFlag(kUseGVN);
} }
@ -3759,7 +3787,7 @@ class HLoadKeyedFastDoubleElement: public HTemplateInstruction<2> {
SetOperandAt(0, elements); SetOperandAt(0, elements);
SetOperandAt(1, key); SetOperandAt(1, key);
set_representation(Representation::Double()); set_representation(Representation::Double());
SetFlag(kDependsOnDoubleArrayElements); SetGVNFlag(kDependsOnDoubleArrayElements);
SetFlag(kUseGVN); SetFlag(kUseGVN);
} }
@ -3796,9 +3824,9 @@ class HLoadKeyedSpecializedArrayElement: public HTemplateInstruction<2> {
} else { } else {
set_representation(Representation::Integer32()); set_representation(Representation::Integer32());
} }
SetFlag(kDependsOnSpecializedArrayElements); SetGVNFlag(kDependsOnSpecializedArrayElements);
// Native code could change the specialized array. // Native code could change the specialized array.
SetFlag(kDependsOnCalls); SetGVNFlag(kDependsOnCalls);
SetFlag(kUseGVN); SetFlag(kUseGVN);
} }
@ -3868,9 +3896,9 @@ class HStoreNamedField: public HTemplateInstruction<2> {
SetOperandAt(0, obj); SetOperandAt(0, obj);
SetOperandAt(1, val); SetOperandAt(1, val);
if (is_in_object_) { if (is_in_object_) {
SetFlag(kChangesInobjectFields); SetGVNFlag(kChangesInobjectFields);
} else { } else {
SetFlag(kChangesBackingStoreFields); SetGVNFlag(kChangesBackingStoreFields);
} }
} }
@ -3945,7 +3973,7 @@ class HStoreKeyedFastElement: public HTemplateInstruction<3> {
SetOperandAt(0, obj); SetOperandAt(0, obj);
SetOperandAt(1, key); SetOperandAt(1, key);
SetOperandAt(2, val); SetOperandAt(2, val);
SetFlag(kChangesArrayElements); SetGVNFlag(kChangesArrayElements);
} }
virtual Representation RequiredInputRepresentation(int index) { virtual Representation RequiredInputRepresentation(int index) {
@ -3987,7 +4015,7 @@ class HStoreKeyedFastDoubleElement: public HTemplateInstruction<3> {
SetOperandAt(0, elements); SetOperandAt(0, elements);
SetOperandAt(1, key); SetOperandAt(1, key);
SetOperandAt(2, val); SetOperandAt(2, val);
SetFlag(kChangesDoubleArrayElements); SetGVNFlag(kChangesDoubleArrayElements);
} }
virtual Representation RequiredInputRepresentation(int index) { virtual Representation RequiredInputRepresentation(int index) {
@ -4021,7 +4049,7 @@ class HStoreKeyedSpecializedArrayElement: public HTemplateInstruction<3> {
HValue* val, HValue* val,
ElementsKind elements_kind) ElementsKind elements_kind)
: elements_kind_(elements_kind) { : elements_kind_(elements_kind) {
SetFlag(kChangesSpecializedArrayElements); SetGVNFlag(kChangesSpecializedArrayElements);
SetOperandAt(0, external_elements); SetOperandAt(0, external_elements);
SetOperandAt(1, key); SetOperandAt(1, key);
SetOperandAt(2, val); SetOperandAt(2, val);
@ -4099,7 +4127,7 @@ class HTransitionElementsKind: public HTemplateInstruction<1> {
transitioned_map_(transitioned_map) { transitioned_map_(transitioned_map) {
SetOperandAt(0, object); SetOperandAt(0, object);
SetFlag(kUseGVN); SetFlag(kUseGVN);
SetFlag(kChangesElementsKind); SetGVNFlag(kChangesElementsKind);
set_representation(Representation::Tagged()); set_representation(Representation::Tagged());
} }
@ -4134,7 +4162,7 @@ class HStringAdd: public HBinaryOperation {
: HBinaryOperation(context, left, right) { : HBinaryOperation(context, left, right) {
set_representation(Representation::Tagged()); set_representation(Representation::Tagged());
SetFlag(kUseGVN); SetFlag(kUseGVN);
SetFlag(kDependsOnMaps); SetGVNFlag(kDependsOnMaps);
} }
virtual Representation RequiredInputRepresentation(int index) { virtual Representation RequiredInputRepresentation(int index) {
@ -4160,7 +4188,7 @@ class HStringCharCodeAt: public HTemplateInstruction<3> {
SetOperandAt(2, index); SetOperandAt(2, index);
set_representation(Representation::Integer32()); set_representation(Representation::Integer32());
SetFlag(kUseGVN); SetFlag(kUseGVN);
SetFlag(kDependsOnMaps); SetGVNFlag(kDependsOnMaps);
} }
virtual Representation RequiredInputRepresentation(int index) { virtual Representation RequiredInputRepresentation(int index) {
@ -4215,7 +4243,7 @@ class HStringLength: public HUnaryOperation {
explicit HStringLength(HValue* string) : HUnaryOperation(string) { explicit HStringLength(HValue* string) : HUnaryOperation(string) {
set_representation(Representation::Tagged()); set_representation(Representation::Tagged());
SetFlag(kUseGVN); SetFlag(kUseGVN);
SetFlag(kDependsOnMaps); SetGVNFlag(kDependsOnMaps);
} }
virtual Representation RequiredInputRepresentation(int index) { virtual Representation RequiredInputRepresentation(int index) {

132
deps/v8/src/hydrogen.cc

@ -1110,10 +1110,10 @@ HValueMap::HValueMap(Zone* zone, const HValueMap* other)
} }
void HValueMap::Kill(int flags) { void HValueMap::Kill(GVNFlagSet flags) {
int depends_flags = HValue::ConvertChangesToDependsFlags(flags); GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(flags);
if ((present_flags_ & depends_flags) == 0) return; if (!present_flags_.ContainsAnyOf(depends_flags)) return;
present_flags_ = 0; present_flags_.RemoveAll();
for (int i = 0; i < array_size_; ++i) { for (int i = 0; i < array_size_; ++i) {
HValue* value = array_[i].value; HValue* value = array_[i].value;
if (value != NULL) { if (value != NULL) {
@ -1122,7 +1122,8 @@ void HValueMap::Kill(int flags) {
int next; int next;
for (int current = array_[i].next; current != kNil; current = next) { for (int current = array_[i].next; current != kNil; current = next) {
next = lists_[current].next; next = lists_[current].next;
if ((lists_[current].value->flags() & depends_flags) != 0) { HValue* value = lists_[current].value;
if (value->gvn_flags().ContainsAnyOf(depends_flags)) {
// Drop it. // Drop it.
count_--; count_--;
lists_[current].next = free_list_head_; lists_[current].next = free_list_head_;
@ -1131,13 +1132,14 @@ void HValueMap::Kill(int flags) {
// Keep it. // Keep it.
lists_[current].next = kept; lists_[current].next = kept;
kept = current; kept = current;
present_flags_ |= lists_[current].value->flags(); present_flags_.Add(value->gvn_flags());
} }
} }
array_[i].next = kept; array_[i].next = kept;
// Now possibly drop directly indexed element. // Now possibly drop directly indexed element.
if ((array_[i].value->flags() & depends_flags) != 0) { // Drop it. value = array_[i].value;
if (value->gvn_flags().ContainsAnyOf(depends_flags)) { // Drop it.
count_--; count_--;
int head = array_[i].next; int head = array_[i].next;
if (head == kNil) { if (head == kNil) {
@ -1149,7 +1151,7 @@ void HValueMap::Kill(int flags) {
free_list_head_ = head; free_list_head_ = head;
} }
} else { } else {
present_flags_ |= array_[i].value->flags(); // Keep it. present_flags_.Add(value->gvn_flags()); // Keep it.
} }
} }
} }
@ -1356,8 +1358,8 @@ class HGlobalValueNumberer BASE_EMBEDDED {
loop_side_effects_(graph->blocks()->length()), loop_side_effects_(graph->blocks()->length()),
visited_on_paths_(graph->zone(), graph->blocks()->length()) { visited_on_paths_(graph->zone(), graph->blocks()->length()) {
ASSERT(info->isolate()->heap()->allow_allocation(false)); ASSERT(info->isolate()->heap()->allow_allocation(false));
block_side_effects_.AddBlock(0, graph_->blocks()->length()); block_side_effects_.AddBlock(GVNFlagSet(), graph_->blocks()->length());
loop_side_effects_.AddBlock(0, graph_->blocks()->length()); loop_side_effects_.AddBlock(GVNFlagSet(), graph_->blocks()->length());
} }
~HGlobalValueNumberer() { ~HGlobalValueNumberer() {
ASSERT(!info_->isolate()->heap()->allow_allocation(true)); ASSERT(!info_->isolate()->heap()->allow_allocation(true));
@ -1367,14 +1369,15 @@ class HGlobalValueNumberer BASE_EMBEDDED {
bool Analyze(); bool Analyze();
private: private:
int CollectSideEffectsOnPathsToDominatedBlock(HBasicBlock* dominator, GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock(
HBasicBlock* dominated); HBasicBlock* dominator,
HBasicBlock* dominated);
void AnalyzeBlock(HBasicBlock* block, HValueMap* map); void AnalyzeBlock(HBasicBlock* block, HValueMap* map);
void ComputeBlockSideEffects(); void ComputeBlockSideEffects();
void LoopInvariantCodeMotion(); void LoopInvariantCodeMotion();
void ProcessLoopBlock(HBasicBlock* block, void ProcessLoopBlock(HBasicBlock* block,
HBasicBlock* before_loop, HBasicBlock* before_loop,
int loop_kills); GVNFlagSet loop_kills);
bool AllowCodeMotion(); bool AllowCodeMotion();
bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header);
@ -1387,10 +1390,10 @@ class HGlobalValueNumberer BASE_EMBEDDED {
bool removed_side_effects_; bool removed_side_effects_;
// A map of block IDs to their side effects. // A map of block IDs to their side effects.
ZoneList<int> block_side_effects_; ZoneList<GVNFlagSet> block_side_effects_;
// A map of loop header block IDs to their loop's side effects. // A map of loop header block IDs to their loop's side effects.
ZoneList<int> loop_side_effects_; ZoneList<GVNFlagSet> loop_side_effects_;
// Used when collecting side effects on paths from dominator to // Used when collecting side effects on paths from dominator to
// dominated. // dominated.
@ -1415,23 +1418,24 @@ void HGlobalValueNumberer::ComputeBlockSideEffects() {
HBasicBlock* block = graph_->blocks()->at(i); HBasicBlock* block = graph_->blocks()->at(i);
HInstruction* instr = block->first(); HInstruction* instr = block->first();
int id = block->block_id(); int id = block->block_id();
int side_effects = 0; GVNFlagSet side_effects;
while (instr != NULL) { while (instr != NULL) {
side_effects |= instr->ChangesFlags(); side_effects.Add(instr->ChangesFlags());
instr = instr->next(); instr = instr->next();
} }
block_side_effects_[id] |= side_effects; block_side_effects_[id].Add(side_effects);
// Loop headers are part of their loop. // Loop headers are part of their loop.
if (block->IsLoopHeader()) { if (block->IsLoopHeader()) {
loop_side_effects_[id] |= side_effects; loop_side_effects_[id].Add(side_effects);
} }
// Propagate loop side effects upwards. // Propagate loop side effects upwards.
if (block->HasParentLoopHeader()) { if (block->HasParentLoopHeader()) {
int header_id = block->parent_loop_header()->block_id(); int header_id = block->parent_loop_header()->block_id();
loop_side_effects_[header_id] |= loop_side_effects_[header_id].Add(block->IsLoopHeader()
block->IsLoopHeader() ? loop_side_effects_[id] : side_effects; ? loop_side_effects_[id]
: side_effects);
} }
} }
} }
@ -1441,10 +1445,10 @@ void HGlobalValueNumberer::LoopInvariantCodeMotion() {
for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { for (int i = graph_->blocks()->length() - 1; i >= 0; --i) {
HBasicBlock* block = graph_->blocks()->at(i); HBasicBlock* block = graph_->blocks()->at(i);
if (block->IsLoopHeader()) { if (block->IsLoopHeader()) {
int side_effects = loop_side_effects_[block->block_id()]; GVNFlagSet side_effects = loop_side_effects_[block->block_id()];
TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n", TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n",
block->block_id(), block->block_id(),
side_effects); side_effects.ToIntegral());
HBasicBlock* last = block->loop_information()->GetLastBackEdge(); HBasicBlock* last = block->loop_information()->GetLastBackEdge();
for (int j = block->block_id(); j <= last->block_id(); ++j) { for (int j = block->block_id(); j <= last->block_id(); ++j) {
@ -1457,17 +1461,17 @@ void HGlobalValueNumberer::LoopInvariantCodeMotion() {
void HGlobalValueNumberer::ProcessLoopBlock(HBasicBlock* block, void HGlobalValueNumberer::ProcessLoopBlock(HBasicBlock* block,
HBasicBlock* loop_header, HBasicBlock* loop_header,
int loop_kills) { GVNFlagSet loop_kills) {
HBasicBlock* pre_header = loop_header->predecessors()->at(0); HBasicBlock* pre_header = loop_header->predecessors()->at(0);
int depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills); GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills);
TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n", TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n",
block->block_id(), block->block_id(),
depends_flags); depends_flags.ToIntegral());
HInstruction* instr = block->first(); HInstruction* instr = block->first();
while (instr != NULL) { while (instr != NULL) {
HInstruction* next = instr->next(); HInstruction* next = instr->next();
if (instr->CheckFlag(HValue::kUseGVN) && if (instr->CheckFlag(HValue::kUseGVN) &&
(instr->flags() & depends_flags) == 0) { !instr->gvn_flags().ContainsAnyOf(depends_flags)) {
TraceGVN("Checking instruction %d (%s)\n", TraceGVN("Checking instruction %d (%s)\n",
instr->id(), instr->id(),
instr->Mnemonic()); instr->Mnemonic());
@ -1503,20 +1507,20 @@ bool HGlobalValueNumberer::ShouldMove(HInstruction* instr,
} }
int HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock( GVNFlagSet HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock(
HBasicBlock* dominator, HBasicBlock* dominated) { HBasicBlock* dominator, HBasicBlock* dominated) {
int side_effects = 0; GVNFlagSet side_effects;
for (int i = 0; i < dominated->predecessors()->length(); ++i) { for (int i = 0; i < dominated->predecessors()->length(); ++i) {
HBasicBlock* block = dominated->predecessors()->at(i); HBasicBlock* block = dominated->predecessors()->at(i);
if (dominator->block_id() < block->block_id() && if (dominator->block_id() < block->block_id() &&
block->block_id() < dominated->block_id() && block->block_id() < dominated->block_id() &&
visited_on_paths_.Add(block->block_id())) { visited_on_paths_.Add(block->block_id())) {
side_effects |= block_side_effects_[block->block_id()]; side_effects.Add(block_side_effects_[block->block_id()]);
if (block->IsLoopHeader()) { if (block->IsLoopHeader()) {
side_effects |= loop_side_effects_[block->block_id()]; side_effects.Add(loop_side_effects_[block->block_id()]);
} }
side_effects |= CollectSideEffectsOnPathsToDominatedBlock( side_effects.Add(CollectSideEffectsOnPathsToDominatedBlock(
dominator, block); dominator, block));
} }
} }
return side_effects; return side_effects;
@ -1537,8 +1541,8 @@ void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
HInstruction* instr = block->first(); HInstruction* instr = block->first();
while (instr != NULL) { while (instr != NULL) {
HInstruction* next = instr->next(); HInstruction* next = instr->next();
int flags = instr->ChangesFlags(); GVNFlagSet flags = instr->ChangesFlags();
if (flags != 0) { if (!flags.IsEmpty()) {
// Clear all instructions in the map that are affected by side effects. // Clear all instructions in the map that are affected by side effects.
map->Kill(flags); map->Kill(flags);
TraceGVN("Instruction %d kills\n", instr->id()); TraceGVN("Instruction %d kills\n", instr->id());
@ -3203,7 +3207,7 @@ HGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty(
} }
Handle<GlobalObject> global(info()->global_object()); Handle<GlobalObject> global(info()->global_object());
global->Lookup(*var->name(), lookup); global->Lookup(*var->name(), lookup);
if (!lookup->IsProperty() || if (!lookup->IsFound() ||
lookup->type() != NORMAL || lookup->type() != NORMAL ||
(is_store && lookup->IsReadOnly()) || (is_store && lookup->IsReadOnly()) ||
lookup->holder() != *global) { lookup->holder() != *global) {
@ -3548,7 +3552,7 @@ static bool ComputeStoredField(Handle<Map> type,
Handle<String> name, Handle<String> name,
LookupResult* lookup) { LookupResult* lookup) {
type->LookupInDescriptors(NULL, *name, lookup); type->LookupInDescriptors(NULL, *name, lookup);
if (!lookup->IsPropertyOrTransition()) return false; if (!lookup->IsFound()) return false;
if (lookup->type() == FIELD) return true; if (lookup->type() == FIELD) return true;
return (lookup->type() == MAP_TRANSITION) && return (lookup->type() == MAP_TRANSITION) &&
(type->unused_property_fields() > 0); (type->unused_property_fields() > 0);
@ -3597,7 +3601,7 @@ HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object,
instr->set_transition(transition); instr->set_transition(transition);
// TODO(fschneider): Record the new map type of the object in the IR to // TODO(fschneider): Record the new map type of the object in the IR to
// enable elimination of redundant checks after the transition store. // enable elimination of redundant checks after the transition store.
instr->SetFlag(HValue::kChangesMaps); instr->SetGVNFlag(kChangesMaps);
} }
return instr; return instr;
} }
@ -4155,13 +4159,13 @@ HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj,
Handle<String> name) { Handle<String> name) {
LookupResult lookup(isolate()); LookupResult lookup(isolate());
map->LookupInDescriptors(NULL, *name, &lookup); map->LookupInDescriptors(NULL, *name, &lookup);
if (lookup.IsProperty() && lookup.type() == FIELD) { if (lookup.IsFound() && lookup.type() == FIELD) {
return BuildLoadNamedField(obj, return BuildLoadNamedField(obj,
expr, expr,
map, map,
&lookup, &lookup,
true); true);
} else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) { } else if (lookup.IsFound() && lookup.type() == CONSTANT_FUNCTION) {
AddInstruction(new(zone()) HCheckNonSmi(obj)); AddInstruction(new(zone()) HCheckNonSmi(obj));
AddInstruction(new(zone()) HCheckMap(obj, map, NULL, AddInstruction(new(zone()) HCheckMap(obj, map, NULL,
ALLOW_ELEMENT_TRANSITION_MAPS)); ALLOW_ELEMENT_TRANSITION_MAPS));
@ -4266,14 +4270,6 @@ HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map)); HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map));
bool fast_smi_only_elements = map->has_fast_smi_only_elements(); bool fast_smi_only_elements = map->has_fast_smi_only_elements();
bool fast_elements = map->has_fast_elements(); bool fast_elements = map->has_fast_elements();
bool fast_double_elements = map->has_fast_double_elements();
if (!fast_smi_only_elements &&
!fast_elements &&
!fast_double_elements &&
!map->has_external_array_elements()) {
return is_store ? BuildStoreKeyedGeneric(object, key, val)
: BuildLoadKeyedGeneric(object, key);
}
HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
if (is_store && (fast_elements || fast_smi_only_elements)) { if (is_store && (fast_elements || fast_smi_only_elements)) {
AddInstruction(new(zone()) HCheckMap( AddInstruction(new(zone()) HCheckMap(
@ -4290,7 +4286,9 @@ HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
return BuildExternalArrayElementAccess(external_elements, checked_key, return BuildExternalArrayElementAccess(external_elements, checked_key,
val, map->elements_kind(), is_store); val, map->elements_kind(), is_store);
} }
ASSERT(fast_smi_only_elements || fast_elements || fast_double_elements); ASSERT(fast_smi_only_elements ||
fast_elements ||
map->has_fast_double_elements());
if (map->instance_type() == JS_ARRAY_TYPE) { if (map->instance_type() == JS_ARRAY_TYPE) {
length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck)); length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck));
} else { } else {
@ -4362,8 +4360,14 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
// If only one map is left after transitioning, handle this case // If only one map is left after transitioning, handle this case
// monomorphically. // monomorphically.
if (num_untransitionable_maps == 1) { if (num_untransitionable_maps == 1) {
HInstruction* instr = AddInstruction(BuildMonomorphicElementAccess( HInstruction* instr = NULL;
object, key, val, untransitionable_map, is_store)); if (untransitionable_map->has_slow_elements_kind()) {
instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val)
: BuildLoadKeyedGeneric(object, key));
} else {
instr = AddInstruction(BuildMonomorphicElementAccess(
object, key, val, untransitionable_map, is_store));
}
*has_side_effects |= instr->HasObservableSideEffects(); *has_side_effects |= instr->HasObservableSideEffects();
instr->set_position(position); instr->set_position(position);
return is_store ? NULL : instr; return is_store ? NULL : instr;
@ -4499,8 +4503,13 @@ HValue* HGraphBuilder::HandleKeyedElementAccess(HValue* obj,
HInstruction* instr = NULL; HInstruction* instr = NULL;
if (expr->IsMonomorphic()) { if (expr->IsMonomorphic()) {
Handle<Map> map = expr->GetMonomorphicReceiverType(); Handle<Map> map = expr->GetMonomorphicReceiverType();
AddInstruction(new(zone()) HCheckNonSmi(obj)); if (map->has_slow_elements_kind()) {
instr = BuildMonomorphicElementAccess(obj, key, val, map, is_store); instr = is_store ? BuildStoreKeyedGeneric(obj, key, val)
: BuildLoadKeyedGeneric(obj, key);
} else {
AddInstruction(new(zone()) HCheckNonSmi(obj));
instr = BuildMonomorphicElementAccess(obj, key, val, map, is_store);
}
} else if (expr->GetReceiverTypes() != NULL && } else if (expr->GetReceiverTypes() != NULL &&
!expr->GetReceiverTypes()->is_empty()) { !expr->GetReceiverTypes()->is_empty()) {
return HandlePolymorphicElementAccess( return HandlePolymorphicElementAccess(
@ -6167,6 +6176,15 @@ static bool IsLiteralCompareNil(HValue* left,
} }
static bool IsLiteralCompareBool(HValue* left,
Token::Value op,
HValue* right) {
return op == Token::EQ_STRICT &&
((left->IsConstant() && HConstant::cast(left)->handle()->IsBoolean()) ||
(right->IsConstant() && HConstant::cast(right)->handle()->IsBoolean()));
}
void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
ASSERT(!HasStackOverflow()); ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL); ASSERT(current_block() != NULL);
@ -6214,6 +6232,12 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
if (IsLiteralCompareNil(left, op, right, f->null_value(), &sub_expr)) { if (IsLiteralCompareNil(left, op, right, f->null_value(), &sub_expr)) {
return HandleLiteralCompareNil(expr, sub_expr, kNullValue); return HandleLiteralCompareNil(expr, sub_expr, kNullValue);
} }
if (IsLiteralCompareBool(left, op, right)) {
HCompareObjectEqAndBranch* result =
new(zone()) HCompareObjectEqAndBranch(left, right);
result->set_position(expr->position());
return ast_context()->ReturnControl(result, expr->id());
}
if (op == Token::INSTANCEOF) { if (op == Token::INSTANCEOF) {
// Check to see if the rhs of the instanceof is a global function not // Check to see if the rhs of the instanceof is a global function not
@ -6229,7 +6253,7 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
Handle<GlobalObject> global(info()->global_object()); Handle<GlobalObject> global(info()->global_object());
LookupResult lookup(isolate()); LookupResult lookup(isolate());
global->Lookup(*name, &lookup); global->Lookup(*name, &lookup);
if (lookup.IsProperty() && if (lookup.IsFound() &&
lookup.type() == NORMAL && lookup.type() == NORMAL &&
lookup.GetValue()->IsJSFunction()) { lookup.GetValue()->IsJSFunction()) {
Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue())); Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue()));

9
deps/v8/src/hydrogen.h

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -1056,10 +1056,10 @@ class HValueMap: public ZoneObject {
Resize(kInitialSize); Resize(kInitialSize);
} }
void Kill(int flags); void Kill(GVNFlagSet flags);
void Add(HValue* value) { void Add(HValue* value) {
present_flags_ |= value->flags(); present_flags_.Add(value->gvn_flags());
Insert(value); Insert(value);
} }
@ -1092,7 +1092,8 @@ class HValueMap: public ZoneObject {
int array_size_; int array_size_;
int lists_size_; int lists_size_;
int count_; // The number of values stored in the HValueMap. int count_; // The number of values stored in the HValueMap.
int present_flags_; // All flags that are in any value in the HValueMap. GVNFlagSet present_flags_; // All flags that are in any value in the
// HValueMap.
HValueMapListElement* array_; // Primary store - contains the first value HValueMapListElement* array_; // Primary store - contains the first value
// with a given hash. Colliding elements are stored in linked lists. // with a given hash. Colliding elements are stored in linked lists.
HValueMapListElement* lists_; // The linked lists containing hash collisions. HValueMapListElement* lists_; // The linked lists containing hash collisions.

43
deps/v8/src/ia32/code-stubs-ia32.cc

@ -749,7 +749,7 @@ static void IntegerConvert(MacroAssembler* masm,
// Exponent word in scratch, exponent part of exponent word in scratch2. // Exponent word in scratch, exponent part of exponent word in scratch2.
// Zero in ecx. // Zero in ecx.
// We know the exponent is smaller than 30 (biased). If it is less than // We know the exponent is smaller than 30 (biased). If it is less than
// 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, ie // 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, i.e.
// it rounds to zero. // it rounds to zero.
const uint32_t zero_exponent = const uint32_t zero_exponent =
(HeapNumber::kExponentBias + 0) << HeapNumber::kExponentShift; (HeapNumber::kExponentBias + 0) << HeapNumber::kExponentShift;
@ -3723,7 +3723,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
kShortExternalStringMask); kShortExternalStringMask);
STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0); STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
__ j(zero, &seq_two_byte_string, Label::kNear); __ j(zero, &seq_two_byte_string, Label::kNear);
// Any other flat string must be a flat ascii string. None of the following // Any other flat string must be a flat ASCII string. None of the following
// string type tests will succeed if subject is not a string or a short // string type tests will succeed if subject is not a string or a short
// external string. // external string.
__ and_(ebx, Immediate(kIsNotStringMask | __ and_(ebx, Immediate(kIsNotStringMask |
@ -3772,16 +3772,16 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
kStringRepresentationMask | kStringEncodingMask); kStringRepresentationMask | kStringEncodingMask);
STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
__ j(zero, &seq_two_byte_string, Label::kNear); __ j(zero, &seq_two_byte_string, Label::kNear);
// Any other flat string must be sequential ascii or external. // Any other flat string must be sequential ASCII or external.
__ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset), __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset),
kStringRepresentationMask); kStringRepresentationMask);
__ j(not_zero, &external_string); __ j(not_zero, &external_string);
__ bind(&seq_ascii_string); __ bind(&seq_ascii_string);
// eax: subject string (flat ascii) // eax: subject string (flat ASCII)
// ecx: RegExp data (FixedArray) // ecx: RegExp data (FixedArray)
__ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset)); __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset));
__ Set(ecx, Immediate(1)); // Type is ascii. __ Set(ecx, Immediate(1)); // Type is ASCII.
__ jmp(&check_code, Label::kNear); __ jmp(&check_code, Label::kNear);
__ bind(&seq_two_byte_string); __ bind(&seq_two_byte_string);
@ -3798,7 +3798,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// eax: subject string // eax: subject string
// edx: code // edx: code
// ecx: encoding of subject string (1 if ascii, 0 if two_byte); // ecx: encoding of subject string (1 if ASCII, 0 if two_byte);
// Load used arguments before starting to push arguments for call to native // Load used arguments before starting to push arguments for call to native
// RegExp code to avoid handling changing stack height. // RegExp code to avoid handling changing stack height.
__ mov(ebx, Operand(esp, kPreviousIndexOffset)); __ mov(ebx, Operand(esp, kPreviousIndexOffset));
@ -3807,7 +3807,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// eax: subject string // eax: subject string
// ebx: previous index // ebx: previous index
// edx: code // edx: code
// ecx: encoding of subject string (1 if ascii 0 if two_byte); // ecx: encoding of subject string (1 if ASCII 0 if two_byte);
// All checks done. Now push arguments for native regexp code. // All checks done. Now push arguments for native regexp code.
Counters* counters = masm->isolate()->counters(); Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->regexp_entry_native(), 1); __ IncrementCounter(counters->regexp_entry_native(), 1);
@ -3847,7 +3847,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// esi: original subject string // esi: original subject string
// eax: underlying subject string // eax: underlying subject string
// ebx: previous index // ebx: previous index
// ecx: encoding of subject string (1 if ascii 0 if two_byte); // ecx: encoding of subject string (1 if ASCII 0 if two_byte);
// edx: code // edx: code
// Argument 4: End of string data // Argument 4: End of string data
// Argument 3: Start of string data // Argument 3: Start of string data
@ -4475,7 +4475,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
__ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx,
&check_unequal_objects); &check_unequal_objects);
// Inline comparison of ascii strings. // Inline comparison of ASCII strings.
if (cc_ == equal) { if (cc_ == equal) {
StringCompareStub::GenerateFlatAsciiStringEquals(masm, StringCompareStub::GenerateFlatAsciiStringEquals(masm,
edx, edx,
@ -5428,7 +5428,7 @@ void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
STATIC_ASSERT(kSmiTag == 0); STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1); STATIC_ASSERT(kSmiTagSize == 1);
STATIC_ASSERT(kSmiShiftSize == 0); STATIC_ASSERT(kSmiShiftSize == 0);
// At this point code register contains smi tagged ascii char code. // At this point code register contains smi tagged ASCII char code.
__ mov(result_, FieldOperand(result_, __ mov(result_, FieldOperand(result_,
code_, times_half_pointer_size, code_, times_half_pointer_size,
FixedArray::kHeaderSize)); FixedArray::kHeaderSize));
@ -5548,7 +5548,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
__ cmp(ebx, Immediate(Smi::FromInt(2))); __ cmp(ebx, Immediate(Smi::FromInt(2)));
__ j(not_equal, &longer_than_two); __ j(not_equal, &longer_than_two);
// Check that both strings are non-external ascii strings. // Check that both strings are non-external ASCII strings.
__ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, &call_runtime); __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, &call_runtime);
// Get the two characters forming the new string. // Get the two characters forming the new string.
@ -5585,11 +5585,11 @@ void StringAddStub::Generate(MacroAssembler* masm) {
__ bind(&longer_than_two); __ bind(&longer_than_two);
// Check if resulting string will be flat. // Check if resulting string will be flat.
__ cmp(ebx, Immediate(Smi::FromInt(String::kMinNonFlatLength))); __ cmp(ebx, Immediate(Smi::FromInt(ConsString::kMinLength)));
__ j(below, &string_add_flat_result); __ j(below, &string_add_flat_result);
// If result is not supposed to be flat allocate a cons string object. If both // If result is not supposed to be flat allocate a cons string object. If both
// strings are ascii the result is an ascii cons string. // strings are ASCII the result is an ASCII cons string.
Label non_ascii, allocated, ascii_data; Label non_ascii, allocated, ascii_data;
__ mov(edi, FieldOperand(eax, HeapObject::kMapOffset)); __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset));
__ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset)); __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset));
@ -5601,7 +5601,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
__ test(ecx, Immediate(kStringEncodingMask)); __ test(ecx, Immediate(kStringEncodingMask));
__ j(zero, &non_ascii); __ j(zero, &non_ascii);
__ bind(&ascii_data); __ bind(&ascii_data);
// Allocate an acsii cons string. // Allocate an ASCII cons string.
__ AllocateAsciiConsString(ecx, edi, no_reg, &call_runtime); __ AllocateAsciiConsString(ecx, edi, no_reg, &call_runtime);
__ bind(&allocated); __ bind(&allocated);
// Fill the fields of the cons string. // Fill the fields of the cons string.
@ -5616,7 +5616,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
__ ret(2 * kPointerSize); __ ret(2 * kPointerSize);
__ bind(&non_ascii); __ bind(&non_ascii);
// At least one of the strings is two-byte. Check whether it happens // At least one of the strings is two-byte. Check whether it happens
// to contain only ascii characters. // to contain only ASCII characters.
// ecx: first instance type AND second instance type. // ecx: first instance type AND second instance type.
// edi: second instance type. // edi: second instance type.
__ test(ecx, Immediate(kAsciiDataHintMask)); __ test(ecx, Immediate(kAsciiDataHintMask));
@ -5633,7 +5633,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
__ jmp(&allocated); __ jmp(&allocated);
// We cannot encounter sliced strings or cons strings here since: // We cannot encounter sliced strings or cons strings here since:
STATIC_ASSERT(SlicedString::kMinLength >= String::kMinNonFlatLength); STATIC_ASSERT(SlicedString::kMinLength >= ConsString::kMinLength);
// Handle creating a flat result from either external or sequential strings. // Handle creating a flat result from either external or sequential strings.
// Locate the first characters' locations. // Locate the first characters' locations.
// eax: first string // eax: first string
@ -5691,7 +5691,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
__ test_b(edi, kStringEncodingMask); __ test_b(edi, kStringEncodingMask);
__ j(zero, &non_ascii_string_add_flat_result); __ j(zero, &non_ascii_string_add_flat_result);
// Both strings are ascii strings. // Both strings are ASCII strings.
// ebx: length of resulting flat string as a smi // ebx: length of resulting flat string as a smi
__ SmiUntag(ebx); __ SmiUntag(ebx);
__ AllocateAsciiString(eax, ebx, ecx, edx, edi, &call_runtime_drop_two); __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &call_runtime_drop_two);
@ -6001,7 +6001,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
__ push(mask); __ push(mask);
Register temp = mask; Register temp = mask;
// Check that the candidate is a non-external ascii string. // Check that the candidate is a non-external ASCII string.
__ mov(temp, FieldOperand(candidate, HeapObject::kMapOffset)); __ mov(temp, FieldOperand(candidate, HeapObject::kMapOffset));
__ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
__ JumpIfInstanceTypeIsNotSequentialAscii( __ JumpIfInstanceTypeIsNotSequentialAscii(
@ -6042,6 +6042,7 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm,
__ mov(scratch, Operand::StaticArray(scratch, __ mov(scratch, Operand::StaticArray(scratch,
times_pointer_size, times_pointer_size,
roots_array_start)); roots_array_start));
__ SmiUntag(scratch);
__ add(scratch, character); __ add(scratch, character);
__ mov(hash, scratch); __ mov(hash, scratch);
__ shl(scratch, 10); __ shl(scratch, 10);
@ -6280,7 +6281,7 @@ void SubStringStub::Generate(MacroAssembler* masm) {
__ test_b(ebx, kStringEncodingMask); __ test_b(ebx, kStringEncodingMask);
__ j(zero, &two_byte_sequential); __ j(zero, &two_byte_sequential);
// Sequential ascii string. Allocate the result. // Sequential ASCII string. Allocate the result.
__ AllocateAsciiString(eax, ecx, ebx, edx, edi, &runtime_drop_two); __ AllocateAsciiString(eax, ecx, ebx, edx, edi, &runtime_drop_two);
// eax: result string // eax: result string
@ -6493,10 +6494,10 @@ void StringCompareStub::Generate(MacroAssembler* masm) {
__ bind(&not_same); __ bind(&not_same);
// Check that both objects are sequential ascii strings. // Check that both objects are sequential ASCII strings.
__ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime); __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime);
// Compare flat ascii strings. // Compare flat ASCII strings.
// Drop arguments from the stack. // Drop arguments from the stack.
__ pop(ecx); __ pop(ecx);
__ add(esp, Immediate(2 * kPointerSize)); __ add(esp, Immediate(2 * kPointerSize));

6
deps/v8/src/ia32/full-codegen-ia32.cc

@ -106,7 +106,7 @@ class JumpPatchSite BASE_EMBEDDED {
// formal parameter count expected by the function. // formal parameter count expected by the function.
// //
// The live registers are: // The live registers are:
// o edi: the JS function object being called (ie, ourselves) // o edi: the JS function object being called (i.e. ourselves)
// o esi: our context // o esi: our context
// o ebp: our caller's frame pointer // o ebp: our caller's frame pointer
// o esp: stack pointer (pointing to return address) // o esp: stack pointer (pointing to return address)
@ -227,7 +227,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset)); Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
__ push(edx); __ push(edx);
__ SafePush(Immediate(Smi::FromInt(num_parameters))); __ SafePush(Immediate(Smi::FromInt(num_parameters)));
// Arguments to ArgumentsAccessStub and/or New...: // Arguments to ArgumentsAccessStub:
// function, receiver address, parameter count. // function, receiver address, parameter count.
// The stub will rewrite receiver and parameter count if the previous // The stub will rewrite receiver and parameter count if the previous
// stack frame was an arguments adapter frame. // stack frame was an arguments adapter frame.
@ -3571,7 +3571,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
// One-character separator case // One-character separator case
__ bind(&one_char_separator); __ bind(&one_char_separator);
// Replace separator with its ascii character value. // Replace separator with its ASCII character value.
__ mov_b(scratch, FieldOperand(string, SeqAsciiString::kHeaderSize)); __ mov_b(scratch, FieldOperand(string, SeqAsciiString::kHeaderSize));
__ mov_b(separator_operand, scratch); __ mov_b(separator_operand, scratch);

26
deps/v8/src/ia32/ic-ia32.cc

@ -473,7 +473,6 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
Counters* counters = isolate->counters(); Counters* counters = isolate->counters();
__ IncrementCounter(counters->keyed_load_generic_smi(), 1); __ IncrementCounter(counters->keyed_load_generic_smi(), 1);
__ ret(0); __ ret(0);
__ bind(&check_number_dictionary); __ bind(&check_number_dictionary);
__ mov(ebx, eax); __ mov(ebx, eax);
__ SmiUntag(ebx); __ SmiUntag(ebx);
@ -535,15 +534,25 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ mov(edi, FieldOperand(eax, String::kHashFieldOffset)); __ mov(edi, FieldOperand(eax, String::kHashFieldOffset));
__ shr(edi, String::kHashShift); __ shr(edi, String::kHashShift);
__ xor_(ecx, edi); __ xor_(ecx, edi);
__ and_(ecx, KeyedLookupCache::kCapacityMask); __ and_(ecx, KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
// Load the key (consisting of map and symbol) from the cache and // Load the key (consisting of map and symbol) from the cache and
// check for match. // check for match.
Label try_second_entry, hit_on_first_entry, load_in_object_property;
ExternalReference cache_keys = ExternalReference cache_keys =
ExternalReference::keyed_lookup_cache_keys(masm->isolate()); ExternalReference::keyed_lookup_cache_keys(masm->isolate());
__ mov(edi, ecx); __ mov(edi, ecx);
__ shl(edi, kPointerSizeLog2 + 1); __ shl(edi, kPointerSizeLog2 + 1);
__ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys)); __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
__ j(not_equal, &try_second_entry);
__ add(edi, Immediate(kPointerSize));
__ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys));
__ j(equal, &hit_on_first_entry);
__ bind(&try_second_entry);
__ lea(edi, Operand(ecx, 1));
__ shl(edi, kPointerSizeLog2 + 1);
__ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
__ j(not_equal, &slow); __ j(not_equal, &slow);
__ add(edi, Immediate(kPointerSize)); __ add(edi, Immediate(kPointerSize));
__ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys)); __ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys));
@ -556,6 +565,18 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
// ecx : lookup cache index // ecx : lookup cache index
ExternalReference cache_field_offsets = ExternalReference cache_field_offsets =
ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate()); ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate());
// Hit on second entry.
__ add(ecx, Immediate(1));
__ mov(edi,
Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets));
__ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset));
__ sub(edi, ecx);
__ j(above_equal, &property_array_property);
__ jmp(&load_in_object_property);
// Hit on first entry.
__ bind(&hit_on_first_entry);
__ mov(edi, __ mov(edi,
Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets)); Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets));
__ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset)); __ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset));
@ -563,6 +584,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ j(above_equal, &property_array_property); __ j(above_equal, &property_array_property);
// Load in-object property. // Load in-object property.
__ bind(&load_in_object_property);
__ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset)); __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset));
__ add(ecx, edi); __ add(ecx, edi);
__ mov(eax, FieldOperand(edx, ecx, times_pointer_size, 0)); __ mov(eax, FieldOperand(edx, ecx, times_pointer_size, 0));

63
deps/v8/src/ia32/lithium-codegen-ia32.cc

@ -2216,7 +2216,7 @@ void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
Handle<String> name) { Handle<String> name) {
LookupResult lookup(isolate()); LookupResult lookup(isolate());
type->LookupInDescriptors(NULL, *name, &lookup); type->LookupInDescriptors(NULL, *name, &lookup);
ASSERT(lookup.IsProperty() && ASSERT(lookup.IsFound() &&
(lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION)); (lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION));
if (lookup.type() == FIELD) { if (lookup.type() == FIELD) {
int index = lookup.GetLocalFieldIndexFromMap(*type); int index = lookup.GetLocalFieldIndexFromMap(*type);
@ -2701,41 +2701,53 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
int arity, int arity,
LInstruction* instr, LInstruction* instr,
CallKind call_kind) { CallKind call_kind) {
// Change context if needed. bool can_invoke_directly = !function->NeedsArgumentsAdaption() ||
bool change_context = function->shared()->formal_parameter_count() == arity;
(info()->closure()->context() != function->context()) ||
scope()->contains_with() ||
(scope()->num_heap_slots() > 0);
if (change_context) {
__ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
} else {
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
}
// Set eax to arguments count if adaption is not needed. Assumes that eax
// is available to write to at this point.
if (!function->NeedsArgumentsAdaption()) {
__ mov(eax, arity);
}
LPointerMap* pointers = instr->pointer_map(); LPointerMap* pointers = instr->pointer_map();
RecordPosition(pointers->position()); RecordPosition(pointers->position());
// Invoke function. if (can_invoke_directly) {
__ SetCallKind(ecx, call_kind); __ LoadHeapObject(edi, function);
if (*function == *info()->closure()) {
__ CallSelf(); // Change context if needed.
bool change_context =
(info()->closure()->context() != function->context()) ||
scope()->contains_with() ||
(scope()->num_heap_slots() > 0);
if (change_context) {
__ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
} else {
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
}
// Set eax to arguments count if adaption is not needed. Assumes that eax
// is available to write to at this point.
if (!function->NeedsArgumentsAdaption()) {
__ mov(eax, arity);
}
// Invoke function directly.
__ SetCallKind(ecx, call_kind);
if (*function == *info()->closure()) {
__ CallSelf();
} else {
__ call(FieldOperand(edi, JSFunction::kCodeEntryOffset));
}
RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
} else { } else {
__ call(FieldOperand(edi, JSFunction::kCodeEntryOffset)); // We need to adapt arguments.
SafepointGenerator generator(
this, pointers, Safepoint::kLazyDeopt);
ParameterCount count(arity);
__ InvokeFunction(function, count, CALL_FUNCTION, generator, call_kind);
} }
RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
} }
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
ASSERT(ToRegister(instr->result()).is(eax)); ASSERT(ToRegister(instr->result()).is(eax));
__ LoadHeapObject(edi, instr->function());
CallKnownFunction(instr->function(), CallKnownFunction(instr->function(),
instr->arity(), instr->arity(),
instr, instr,
@ -3190,7 +3202,6 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
ASSERT(ToRegister(instr->result()).is(eax)); ASSERT(ToRegister(instr->result()).is(eax));
__ LoadHeapObject(edi, instr->target());
CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION); CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
} }

67
deps/v8/src/ia32/macro-assembler-ia32.cc

@ -1387,7 +1387,7 @@ void MacroAssembler::AllocateAsciiString(Register result,
add(scratch1, Immediate(kObjectAlignmentMask)); add(scratch1, Immediate(kObjectAlignmentMask));
and_(scratch1, Immediate(~kObjectAlignmentMask)); and_(scratch1, Immediate(~kObjectAlignmentMask));
// Allocate ascii string in new space. // Allocate ASCII string in new space.
AllocateInNewSpace(SeqAsciiString::kHeaderSize, AllocateInNewSpace(SeqAsciiString::kHeaderSize,
times_1, times_1,
scratch1, scratch1,
@ -1415,7 +1415,7 @@ void MacroAssembler::AllocateAsciiString(Register result,
Label* gc_required) { Label* gc_required) {
ASSERT(length > 0); ASSERT(length > 0);
// Allocate ascii string in new space. // Allocate ASCII string in new space.
AllocateInNewSpace(SeqAsciiString::SizeFor(length), AllocateInNewSpace(SeqAsciiString::SizeFor(length),
result, result,
scratch1, scratch1,
@ -1933,11 +1933,13 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
Handle<Code> code_constant, Handle<Code> code_constant,
const Operand& code_operand, const Operand& code_operand,
Label* done, Label* done,
bool* definitely_mismatches,
InvokeFlag flag, InvokeFlag flag,
Label::Distance done_near, Label::Distance done_near,
const CallWrapper& call_wrapper, const CallWrapper& call_wrapper,
CallKind call_kind) { CallKind call_kind) {
bool definitely_matches = false; bool definitely_matches = false;
*definitely_mismatches = false;
Label invoke; Label invoke;
if (expected.is_immediate()) { if (expected.is_immediate()) {
ASSERT(actual.is_immediate()); ASSERT(actual.is_immediate());
@ -1953,6 +1955,7 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
// arguments. // arguments.
definitely_matches = true; definitely_matches = true;
} else { } else {
*definitely_mismatches = true;
mov(ebx, expected.immediate()); mov(ebx, expected.immediate());
} }
} }
@ -1990,7 +1993,9 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
SetCallKind(ecx, call_kind); SetCallKind(ecx, call_kind);
call(adaptor, RelocInfo::CODE_TARGET); call(adaptor, RelocInfo::CODE_TARGET);
call_wrapper.AfterCall(); call_wrapper.AfterCall();
jmp(done, done_near); if (!*definitely_mismatches) {
jmp(done, done_near);
}
} else { } else {
SetCallKind(ecx, call_kind); SetCallKind(ecx, call_kind);
jmp(adaptor, RelocInfo::CODE_TARGET); jmp(adaptor, RelocInfo::CODE_TARGET);
@ -2010,20 +2015,23 @@ void MacroAssembler::InvokeCode(const Operand& code,
ASSERT(flag == JUMP_FUNCTION || has_frame()); ASSERT(flag == JUMP_FUNCTION || has_frame());
Label done; Label done;
bool definitely_mismatches = false;
InvokePrologue(expected, actual, Handle<Code>::null(), code, InvokePrologue(expected, actual, Handle<Code>::null(), code,
&done, flag, Label::kNear, call_wrapper, &done, &definitely_mismatches, flag, Label::kNear,
call_kind); call_wrapper, call_kind);
if (flag == CALL_FUNCTION) { if (!definitely_mismatches) {
call_wrapper.BeforeCall(CallSize(code)); if (flag == CALL_FUNCTION) {
SetCallKind(ecx, call_kind); call_wrapper.BeforeCall(CallSize(code));
call(code); SetCallKind(ecx, call_kind);
call_wrapper.AfterCall(); call(code);
} else { call_wrapper.AfterCall();
ASSERT(flag == JUMP_FUNCTION); } else {
SetCallKind(ecx, call_kind); ASSERT(flag == JUMP_FUNCTION);
jmp(code); SetCallKind(ecx, call_kind);
jmp(code);
}
bind(&done);
} }
bind(&done);
} }
@ -2039,19 +2047,22 @@ void MacroAssembler::InvokeCode(Handle<Code> code,
Label done; Label done;
Operand dummy(eax, 0); Operand dummy(eax, 0);
InvokePrologue(expected, actual, code, dummy, &done, flag, Label::kNear, bool definitely_mismatches = false;
call_wrapper, call_kind); InvokePrologue(expected, actual, code, dummy, &done, &definitely_mismatches,
if (flag == CALL_FUNCTION) { flag, Label::kNear, call_wrapper, call_kind);
call_wrapper.BeforeCall(CallSize(code, rmode)); if (!definitely_mismatches) {
SetCallKind(ecx, call_kind); if (flag == CALL_FUNCTION) {
call(code, rmode); call_wrapper.BeforeCall(CallSize(code, rmode));
call_wrapper.AfterCall(); SetCallKind(ecx, call_kind);
} else { call(code, rmode);
ASSERT(flag == JUMP_FUNCTION); call_wrapper.AfterCall();
SetCallKind(ecx, call_kind); } else {
jmp(code, rmode); ASSERT(flag == JUMP_FUNCTION);
SetCallKind(ecx, call_kind);
jmp(code, rmode);
}
bind(&done);
} }
bind(&done);
} }
@ -2464,7 +2475,7 @@ void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register object1,
movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset)); movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset)); movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
// Check that both are flat ascii strings. // Check that both are flat ASCII strings.
const int kFlatAsciiStringMask = const int kFlatAsciiStringMask =
kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
const int kFlatAsciiStringTag = ASCII_STRING_TYPE; const int kFlatAsciiStringTag = ASCII_STRING_TYPE;

5
deps/v8/src/ia32/macro-assembler-ia32.h

@ -368,7 +368,7 @@ class MacroAssembler: public Assembler {
// Check if the map of an object is equal to a specified map and branch to // Check if the map of an object is equal to a specified map and branch to
// label if not. Skip the smi check if not required (object is known to be a // label if not. Skip the smi check if not required (object is known to be a
// heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
// against maps that are ElementsKind transition maps of the specificed map. // against maps that are ElementsKind transition maps of the specified map.
void CheckMap(Register obj, void CheckMap(Register obj,
Handle<Map> map, Handle<Map> map,
Label* fail, Label* fail,
@ -791,7 +791,7 @@ class MacroAssembler: public Assembler {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// String utilities. // String utilities.
// Check whether the instance type represents a flat ascii string. Jump to the // Check whether the instance type represents a flat ASCII string. Jump to the
// label if not. If the instance type can be scratched specify same register // label if not. If the instance type can be scratched specify same register
// for both instance type and scratch. // for both instance type and scratch.
void JumpIfInstanceTypeIsNotSequentialAscii(Register instance_type, void JumpIfInstanceTypeIsNotSequentialAscii(Register instance_type,
@ -827,6 +827,7 @@ class MacroAssembler: public Assembler {
Handle<Code> code_constant, Handle<Code> code_constant,
const Operand& code_operand, const Operand& code_operand,
Label* done, Label* done,
bool* definitely_mismatches,
InvokeFlag flag, InvokeFlag flag,
Label::Distance done_distance, Label::Distance done_distance,
const CallWrapper& call_wrapper = NullCallWrapper(), const CallWrapper& call_wrapper = NullCallWrapper(),

2
deps/v8/src/ia32/regexp-macro-assembler-ia32.cc

@ -210,7 +210,7 @@ void RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str,
bool check_end_of_string) { bool check_end_of_string) {
#ifdef DEBUG #ifdef DEBUG
// If input is ASCII, don't even bother calling here if the string to // If input is ASCII, don't even bother calling here if the string to
// match contains a non-ascii character. // match contains a non-ASCII character.
if (mode_ == ASCII) { if (mode_ == ASCII) {
ASSERT(String::IsAscii(str.start(), str.length())); ASSERT(String::IsAscii(str.start(), str.length()));
} }

4
deps/v8/src/ia32/stub-cache-ia32.cc

@ -992,7 +992,7 @@ void StubCompiler::GenerateLoadCallback(Handle<JSObject> object,
__ push(scratch3); // Restore return address. __ push(scratch3); // Restore return address.
// 3 elements array for v8::Agruments::values_, handler for name and pointer // 3 elements array for v8::Arguments::values_, handler for name and pointer
// to the values (it considered as smi in GC). // to the values (it considered as smi in GC).
const int kStackSpace = 5; const int kStackSpace = 5;
const int kApiArgc = 2; const int kApiArgc = 2;
@ -1053,7 +1053,7 @@ void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object,
// and CALLBACKS, so inline only them, other cases may be added // and CALLBACKS, so inline only them, other cases may be added
// later. // later.
bool compile_followup_inline = false; bool compile_followup_inline = false;
if (lookup->IsProperty() && lookup->IsCacheable()) { if (lookup->IsFound() && lookup->IsCacheable()) {
if (lookup->type() == FIELD) { if (lookup->type() == FIELD) {
compile_followup_inline = true; compile_followup_inline = true;
} else if (lookup->type() == CALLBACKS && } else if (lookup->type() == CALLBACKS &&

14
deps/v8/src/ic.cc

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -860,7 +860,7 @@ MaybeObject* LoadIC::Load(State state,
} }
PropertyAttributes attr; PropertyAttributes attr;
if (lookup.IsProperty() && if (lookup.IsFound() &&
(lookup.type() == INTERCEPTOR || lookup.type() == HANDLER)) { (lookup.type() == INTERCEPTOR || lookup.type() == HANDLER)) {
// Get the property. // Get the property.
Handle<Object> result = Handle<Object> result =
@ -1083,7 +1083,7 @@ MaybeObject* KeyedLoadIC::Load(State state,
} }
PropertyAttributes attr; PropertyAttributes attr;
if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { if (lookup.IsFound() && lookup.type() == INTERCEPTOR) {
// Get the property. // Get the property.
Handle<Object> result = Handle<Object> result =
Object::GetProperty(object, object, &lookup, name, &attr); Object::GetProperty(object, object, &lookup, name, &attr);
@ -1206,10 +1206,12 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup,
static bool StoreICableLookup(LookupResult* lookup) { static bool StoreICableLookup(LookupResult* lookup) {
// Bail out if we didn't find a result. // Bail out if we didn't find a result.
if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false; if (!lookup->IsFound() || lookup->type() == NULL_DESCRIPTOR) return false;
// If the property is read-only, we leave the IC in its current // Bail out if inline caching is not allowed.
// state. if (!lookup->IsCacheable()) return false;
// If the property is read-only, we leave the IC in its current state.
if (lookup->IsReadOnly()) return false; if (lookup->IsReadOnly()) return false;
return true; return true;

2
deps/v8/src/incremental-marking-inl.h

@ -95,7 +95,7 @@ void IncrementalMarking::BlackToGreyAndUnshift(HeapObject* obj,
ASSERT(IsMarking()); ASSERT(IsMarking());
Marking::BlackToGrey(mark_bit); Marking::BlackToGrey(mark_bit);
int obj_size = obj->Size(); int obj_size = obj->Size();
MemoryChunk::IncrementLiveBytes(obj->address(), -obj_size); MemoryChunk::IncrementLiveBytesFromGC(obj->address(), -obj_size);
bytes_scanned_ -= obj_size; bytes_scanned_ -= obj_size;
int64_t old_bytes_rescanned = bytes_rescanned_; int64_t old_bytes_rescanned = bytes_rescanned_;
bytes_rescanned_ = old_bytes_rescanned + obj_size; bytes_rescanned_ = old_bytes_rescanned + obj_size;

22
deps/v8/src/incremental-marking.cc

@ -225,8 +225,8 @@ class IncrementalMarkingMarkingVisitor : public ObjectVisitor {
MarkBit mark_bit = Marking::MarkBitFrom(heap_object); MarkBit mark_bit = Marking::MarkBitFrom(heap_object);
if (mark_bit.data_only()) { if (mark_bit.data_only()) {
if (incremental_marking_->MarkBlackOrKeepGrey(mark_bit)) { if (incremental_marking_->MarkBlackOrKeepGrey(mark_bit)) {
MemoryChunk::IncrementLiveBytes(heap_object->address(), MemoryChunk::IncrementLiveBytesFromGC(heap_object->address(),
heap_object->Size()); heap_object->Size());
} }
} else if (Marking::IsWhite(mark_bit)) { } else if (Marking::IsWhite(mark_bit)) {
incremental_marking_->WhiteToGreyAndPush(heap_object, mark_bit); incremental_marking_->WhiteToGreyAndPush(heap_object, mark_bit);
@ -263,8 +263,8 @@ class IncrementalMarkingRootMarkingVisitor : public ObjectVisitor {
MarkBit mark_bit = Marking::MarkBitFrom(heap_object); MarkBit mark_bit = Marking::MarkBitFrom(heap_object);
if (mark_bit.data_only()) { if (mark_bit.data_only()) {
if (incremental_marking_->MarkBlackOrKeepGrey(mark_bit)) { if (incremental_marking_->MarkBlackOrKeepGrey(mark_bit)) {
MemoryChunk::IncrementLiveBytes(heap_object->address(), MemoryChunk::IncrementLiveBytesFromGC(heap_object->address(),
heap_object->Size()); heap_object->Size());
} }
} else { } else {
if (Marking::IsWhite(mark_bit)) { if (Marking::IsWhite(mark_bit)) {
@ -491,8 +491,8 @@ static void MarkObjectGreyDoNotEnqueue(Object* obj) {
HeapObject* heap_obj = HeapObject::cast(obj); HeapObject* heap_obj = HeapObject::cast(obj);
MarkBit mark_bit = Marking::MarkBitFrom(HeapObject::cast(obj)); MarkBit mark_bit = Marking::MarkBitFrom(HeapObject::cast(obj));
if (Marking::IsBlack(mark_bit)) { if (Marking::IsBlack(mark_bit)) {
MemoryChunk::IncrementLiveBytes(heap_obj->address(), MemoryChunk::IncrementLiveBytesFromGC(heap_obj->address(),
-heap_obj->Size()); -heap_obj->Size());
} }
Marking::AnyToGrey(mark_bit); Marking::AnyToGrey(mark_bit);
} }
@ -658,7 +658,7 @@ void IncrementalMarking::Hurry() {
MarkBit mark_bit = Marking::MarkBitFrom(obj); MarkBit mark_bit = Marking::MarkBitFrom(obj);
ASSERT(!Marking::IsBlack(mark_bit)); ASSERT(!Marking::IsBlack(mark_bit));
Marking::MarkBlack(mark_bit); Marking::MarkBlack(mark_bit);
MemoryChunk::IncrementLiveBytes(obj->address(), obj->Size()); MemoryChunk::IncrementLiveBytesFromGC(obj->address(), obj->Size());
} }
state_ = COMPLETE; state_ = COMPLETE;
if (FLAG_trace_incremental_marking) { if (FLAG_trace_incremental_marking) {
@ -671,8 +671,8 @@ void IncrementalMarking::Hurry() {
if (FLAG_cleanup_code_caches_at_gc) { if (FLAG_cleanup_code_caches_at_gc) {
PolymorphicCodeCache* poly_cache = heap_->polymorphic_code_cache(); PolymorphicCodeCache* poly_cache = heap_->polymorphic_code_cache();
Marking::GreyToBlack(Marking::MarkBitFrom(poly_cache)); Marking::GreyToBlack(Marking::MarkBitFrom(poly_cache));
MemoryChunk::IncrementLiveBytes(poly_cache->address(), MemoryChunk::IncrementLiveBytesFromGC(poly_cache->address(),
PolymorphicCodeCache::kSize); PolymorphicCodeCache::kSize);
} }
Object* context = heap_->global_contexts_list(); Object* context = heap_->global_contexts_list();
@ -685,7 +685,7 @@ void IncrementalMarking::Hurry() {
MarkBit mark_bit = Marking::MarkBitFrom(cache); MarkBit mark_bit = Marking::MarkBitFrom(cache);
if (Marking::IsGrey(mark_bit)) { if (Marking::IsGrey(mark_bit)) {
Marking::GreyToBlack(mark_bit); Marking::GreyToBlack(mark_bit);
MemoryChunk::IncrementLiveBytes(cache->address(), cache->Size()); MemoryChunk::IncrementLiveBytesFromGC(cache->address(), cache->Size());
} }
} }
context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
@ -819,7 +819,7 @@ void IncrementalMarking::Step(intptr_t allocated_bytes) {
SLOW_ASSERT(Marking::IsGrey(obj_mark_bit) || SLOW_ASSERT(Marking::IsGrey(obj_mark_bit) ||
(obj->IsFiller() && Marking::IsWhite(obj_mark_bit))); (obj->IsFiller() && Marking::IsWhite(obj_mark_bit)));
Marking::MarkBlack(obj_mark_bit); Marking::MarkBlack(obj_mark_bit);
MemoryChunk::IncrementLiveBytes(obj->address(), size); MemoryChunk::IncrementLiveBytesFromGC(obj->address(), size);
} }
if (marking_deque_.IsEmpty()) MarkingComplete(); if (marking_deque_.IsEmpty()) MarkingComplete();
} }

7
deps/v8/src/isolate.cc

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -1219,7 +1219,7 @@ bool Isolate::OptionalRescheduleException(bool is_bottom_call) {
ASSERT(has_pending_exception()); ASSERT(has_pending_exception());
PropagatePendingExceptionToExternalTryCatch(); PropagatePendingExceptionToExternalTryCatch();
// Allways reschedule out of memory exceptions. // Always reschedule out of memory exceptions.
if (!is_out_of_memory()) { if (!is_out_of_memory()) {
bool is_termination_exception = bool is_termination_exception =
pending_exception() == heap_.termination_exception(); pending_exception() == heap_.termination_exception();
@ -1454,7 +1454,8 @@ Isolate::Isolate()
has_installed_extensions_(false), has_installed_extensions_(false),
string_tracker_(NULL), string_tracker_(NULL),
regexp_stack_(NULL), regexp_stack_(NULL),
embedder_data_(NULL) { embedder_data_(NULL),
context_exit_happened_(false) {
TRACE_ISOLATE(constructor); TRACE_ISOLATE(constructor);
memset(isolate_addresses_, 0, memset(isolate_addresses_, 0,

18
deps/v8/src/isolate.h

@ -258,7 +258,7 @@ class ThreadLocalTop BASE_EMBEDDED {
#endif #endif
#endif // USE_SIMULATOR #endif // USE_SIMULATOR
Address js_entry_sp_; // the stack pointer of the bottom js entry frame Address js_entry_sp_; // the stack pointer of the bottom JS entry frame
Address external_callback_; // the external callback we're currently in Address external_callback_; // the external callback we're currently in
StateTag current_vm_state_; StateTag current_vm_state_;
@ -485,7 +485,7 @@ class Isolate {
bool IsDefaultIsolate() const { return this == default_isolate_; } bool IsDefaultIsolate() const { return this == default_isolate_; }
// Ensures that process-wide resources and the default isolate have been // Ensures that process-wide resources and the default isolate have been
// allocated. It is only necessary to call this method in rare casses, for // allocated. It is only necessary to call this method in rare cases, for
// example if you are using V8 from within the body of a static initializer. // example if you are using V8 from within the body of a static initializer.
// Safe to call multiple times. // Safe to call multiple times.
static void EnsureDefaultIsolate(); static void EnsureDefaultIsolate();
@ -635,7 +635,7 @@ class Isolate {
void* formal_count_address() { return &thread_local_top_.formal_count_; } void* formal_count_address() { return &thread_local_top_.formal_count_; }
// Returns the global object of the current context. It could be // Returns the global object of the current context. It could be
// a builtin object, or a js global object. // a builtin object, or a JS global object.
Handle<GlobalObject> global() { Handle<GlobalObject> global() {
return Handle<GlobalObject>(context()->global()); return Handle<GlobalObject>(context()->global());
} }
@ -1023,6 +1023,13 @@ class Isolate {
thread_local_top_.top_lookup_result_ = top; thread_local_top_.top_lookup_result_ = top;
} }
bool context_exit_happened() {
return context_exit_happened_;
}
void set_context_exit_happened(bool context_exit_happened) {
context_exit_happened_ = context_exit_happened;
}
private: private:
Isolate(); Isolate();
@ -1064,6 +1071,7 @@ class Isolate {
Isolate* previous_isolate; Isolate* previous_isolate;
EntryStackItem* previous_item; EntryStackItem* previous_item;
private:
DISALLOW_COPY_AND_ASSIGN(EntryStackItem); DISALLOW_COPY_AND_ASSIGN(EntryStackItem);
}; };
@ -1188,6 +1196,10 @@ class Isolate {
unibrow::Mapping<unibrow::Ecma262Canonicalize> interp_canonicalize_mapping_; unibrow::Mapping<unibrow::Ecma262Canonicalize> interp_canonicalize_mapping_;
void* embedder_data_; void* embedder_data_;
// The garbage collector should be a little more aggressive when it knows
// that a context was recently exited.
bool context_exit_happened_;
#if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \ #if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__) defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
bool simulator_initialized_; bool simulator_initialized_;

4
deps/v8/src/json-parser.h

@ -130,7 +130,7 @@ class JsonParser BASE_EMBEDDED {
// An object literal is a squiggly-braced and comma separated sequence // An object literal is a squiggly-braced and comma separated sequence
// (possibly empty) of key/value pairs, where the key is a JSON string // (possibly empty) of key/value pairs, where the key is a JSON string
// literal, the value is a JSON value, and the two are separated by a colon. // literal, the value is a JSON value, and the two are separated by a colon.
// A JSON array dosn't allow numbers and identifiers as keys, like a // A JSON array doesn't allow numbers and identifiers as keys, like a
// JavaScript array. // JavaScript array.
Handle<Object> ParseJsonObject(); Handle<Object> ParseJsonObject();
@ -177,7 +177,7 @@ Handle<Object> JsonParser<seq_ascii>::ParseJson(Handle<String> source) {
// Set initial position right before the string. // Set initial position right before the string.
position_ = -1; position_ = -1;
// Advance to the first character (posibly EOS) // Advance to the first character (possibly EOS)
AdvanceSkipWhitespace(); AdvanceSkipWhitespace();
Handle<Object> result = ParseJsonValue(); Handle<Object> result = ParseJsonValue();
if (result.is_null() || c0_ != kEndOfString) { if (result.is_null() || c0_ != kEndOfString) {

2
deps/v8/src/jsregexp.cc

@ -704,7 +704,7 @@ Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> jsregexp,
// the virtualized backtrack stack and some register changes. When a node is // the virtualized backtrack stack and some register changes. When a node is
// to be emitted it can flush the Trace or update it. Flushing the Trace // to be emitted it can flush the Trace or update it. Flushing the Trace
// will emit code to bring the actual state into line with the virtual state. // will emit code to bring the actual state into line with the virtual state.
// Avoiding flushing the state can postpone some work (eg updates of capture // Avoiding flushing the state can postpone some work (e.g. updates of capture
// registers). Postponing work can save time when executing the regular // registers). Postponing work can save time when executing the regular
// expression since it may be found that the work never has to be done as a // expression since it may be found that the work never has to be done as a
// failure to match can occur. In addition it is much faster to jump to a // failure to match can occur. In addition it is much faster to jump to a

2
deps/v8/src/jsregexp.h

@ -634,7 +634,7 @@ class RegExpNode: public ZoneObject {
static const int kNodeIsTooComplexForGreedyLoops = -1; static const int kNodeIsTooComplexForGreedyLoops = -1;
virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; } virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; }
Label* label() { return &label_; } Label* label() { return &label_; }
// If non-generic code is generated for a node (ie the node is not at the // If non-generic code is generated for a node (i.e. the node is not at the
// start of the trace) then it cannot be reused. This variable sets a limit // start of the trace) then it cannot be reused. This variable sets a limit
// on how often we allow that to happen before we insist on starting a new // on how often we allow that to happen before we insist on starting a new
// trace and generating generic code for a node that can be reused by flushing // trace and generating generic code for a node that can be reused by flushing

2
deps/v8/src/list.h

@ -67,7 +67,7 @@ class List {
// Returns a reference to the element at index i. This reference is // Returns a reference to the element at index i. This reference is
// not safe to use after operations that can change the list's // not safe to use after operations that can change the list's
// backing store (eg, Add). // backing store (e.g. Add).
inline T& operator[](int i) const { inline T& operator[](int i) const {
ASSERT(0 <= i); ASSERT(0 <= i);
ASSERT(i < length_); ASSERT(i < length_);

2
deps/v8/src/liveedit-debugger.js

@ -581,7 +581,7 @@ Debug.LiveEdit = new function() {
// children of unchanged functions are ignored. // children of unchanged functions are ignored.
function MarkChangedFunctions(code_info_tree, chunks) { function MarkChangedFunctions(code_info_tree, chunks) {
// A convenient interator over diff chunks that also translates // A convenient iterator over diff chunks that also translates
// positions from old to new in a current non-changed part of script. // positions from old to new in a current non-changed part of script.
var chunk_it = new function() { var chunk_it = new function() {
var chunk_index = 0; var chunk_index = 0;

2
deps/v8/src/liveobjectlist.cc

@ -462,7 +462,7 @@ static int CompactString(char* str) {
char prev_ch = 0; char prev_ch = 0;
while (*dst != '\0') { while (*dst != '\0') {
char ch = *src++; char ch = *src++;
// We will treat non-ascii chars as '?'. // We will treat non-ASCII chars as '?'.
if ((ch & 0x80) != 0) { if ((ch & 0x80) != 0) {
ch = '?'; ch = '?';
} }

2
deps/v8/src/macros.py

@ -26,7 +26,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Dictionary that is passed as defines for js2c.py. # Dictionary that is passed as defines for js2c.py.
# Used for defines that must be defined for all native js files. # Used for defines that must be defined for all native JS files.
const NONE = 0; const NONE = 0;
const READ_ONLY = 1; const READ_ONLY = 1;

14
deps/v8/src/mark-compact-inl.h

@ -49,11 +49,18 @@ void MarkCompactCollector::SetFlags(int flags) {
} }
void MarkCompactCollector::ClearCacheOnMap(Map* map) {
if (FLAG_cleanup_code_caches_at_gc) {
map->ClearCodeCache(heap());
}
}
void MarkCompactCollector::MarkObject(HeapObject* obj, MarkBit mark_bit) { void MarkCompactCollector::MarkObject(HeapObject* obj, MarkBit mark_bit) {
ASSERT(Marking::MarkBitFrom(obj) == mark_bit); ASSERT(Marking::MarkBitFrom(obj) == mark_bit);
if (!mark_bit.Get()) { if (!mark_bit.Get()) {
mark_bit.Set(); mark_bit.Set();
MemoryChunk::IncrementLiveBytes(obj->address(), obj->Size()); MemoryChunk::IncrementLiveBytesFromGC(obj->address(), obj->Size());
ProcessNewlyMarkedObject(obj); ProcessNewlyMarkedObject(obj);
} }
} }
@ -63,7 +70,10 @@ void MarkCompactCollector::SetMark(HeapObject* obj, MarkBit mark_bit) {
ASSERT(!mark_bit.Get()); ASSERT(!mark_bit.Get());
ASSERT(Marking::MarkBitFrom(obj) == mark_bit); ASSERT(Marking::MarkBitFrom(obj) == mark_bit);
mark_bit.Set(); mark_bit.Set();
MemoryChunk::IncrementLiveBytes(obj->address(), obj->Size()); MemoryChunk::IncrementLiveBytesFromGC(obj->address(), obj->Size());
if (obj->IsMap()) {
ClearCacheOnMap(Map::cast(obj));
}
} }

71
deps/v8/src/mark-compact.cc

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -63,6 +63,7 @@ MarkCompactCollector::MarkCompactCollector() : // NOLINT
compacting_(false), compacting_(false),
was_marked_incrementally_(false), was_marked_incrementally_(false),
collect_maps_(FLAG_collect_maps), collect_maps_(FLAG_collect_maps),
flush_monomorphic_ics_(false),
tracer_(NULL), tracer_(NULL),
migration_slots_buffer_(NULL), migration_slots_buffer_(NULL),
heap_(NULL), heap_(NULL),
@ -515,6 +516,12 @@ void MarkCompactCollector::Prepare(GCTracer* tracer) {
// order which is not implemented for incremental marking. // order which is not implemented for incremental marking.
collect_maps_ = FLAG_collect_maps && !was_marked_incrementally_; collect_maps_ = FLAG_collect_maps && !was_marked_incrementally_;
// Monomorphic ICs are preserved when possible, but need to be flushed
// when they might be keeping a Context alive, or when the heap is about
// to be serialized.
flush_monomorphic_ics_ =
heap()->isolate()->context_exit_happened() || Serializer::enabled();
// Rather than passing the tracer around we stash it in a static member // Rather than passing the tracer around we stash it in a static member
// variable. // variable.
tracer_ = tracer; tracer_ = tracer;
@ -737,7 +744,7 @@ static inline HeapObject* ShortCircuitConsString(Object** p) {
// it in place to its left substring. Return the updated value. // it in place to its left substring. Return the updated value.
// //
// Here we assume that if we change *p, we replace it with a heap object // Here we assume that if we change *p, we replace it with a heap object
// (ie, the left substring of a cons string is always a heap object). // (i.e., the left substring of a cons string is always a heap object).
// //
// The check performed is: // The check performed is:
// object->IsConsString() && !object->IsSymbol() && // object->IsConsString() && !object->IsSymbol() &&
@ -881,7 +888,9 @@ class StaticMarkingVisitor : public StaticVisitorBase {
static inline void VisitCodeTarget(Heap* heap, RelocInfo* rinfo) { static inline void VisitCodeTarget(Heap* heap, RelocInfo* rinfo) {
ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
if (FLAG_cleanup_code_caches_at_gc && target->is_inline_cache_stub()) { if (FLAG_cleanup_code_caches_at_gc && target->is_inline_cache_stub()
&& (target->ic_state() == MEGAMORPHIC ||
heap->mark_compact_collector()->flush_monomorphic_ics_)) {
IC::Clear(rinfo->pc()); IC::Clear(rinfo->pc());
target = Code::GetCodeFromTargetAddress(rinfo->target_address()); target = Code::GetCodeFromTargetAddress(rinfo->target_address());
} else { } else {
@ -1196,7 +1205,7 @@ class StaticMarkingVisitor : public StaticVisitorBase {
return; return;
} }
JSRegExp* re = reinterpret_cast<JSRegExp*>(object); JSRegExp* re = reinterpret_cast<JSRegExp*>(object);
// Flush code or set age on both ascii and two byte code. // Flush code or set age on both ASCII and two byte code.
UpdateRegExpCodeAgeAndFlush(heap, re, true); UpdateRegExpCodeAgeAndFlush(heap, re, true);
UpdateRegExpCodeAgeAndFlush(heap, re, false); UpdateRegExpCodeAgeAndFlush(heap, re, false);
// Visit the fields of the RegExp, including the updated FixedArray. // Visit the fields of the RegExp, including the updated FixedArray.
@ -1614,9 +1623,7 @@ void MarkCompactCollector::ProcessNewlyMarkedObject(HeapObject* object) {
ASSERT(HEAP->Contains(object)); ASSERT(HEAP->Contains(object));
if (object->IsMap()) { if (object->IsMap()) {
Map* map = Map::cast(object); Map* map = Map::cast(object);
if (FLAG_cleanup_code_caches_at_gc) { ClearCacheOnMap(map);
map->ClearCodeCache(heap());
}
// When map collection is enabled we have to mark through map's transitions // When map collection is enabled we have to mark through map's transitions
// in a special way to make transition links weak. // in a special way to make transition links weak.
@ -1641,8 +1648,8 @@ void MarkCompactCollector::MarkMapContents(Map* map) {
MarkBit mark = Marking::MarkBitFrom(prototype_transitions); MarkBit mark = Marking::MarkBitFrom(prototype_transitions);
if (!mark.Get()) { if (!mark.Get()) {
mark.Set(); mark.Set();
MemoryChunk::IncrementLiveBytes(prototype_transitions->address(), MemoryChunk::IncrementLiveBytesFromGC(prototype_transitions->address(),
prototype_transitions->Size()); prototype_transitions->Size());
} }
Object** raw_descriptor_array_slot = Object** raw_descriptor_array_slot =
@ -1756,7 +1763,7 @@ static void DiscoverGreyObjectsWithIterator(Heap* heap,
MarkBit markbit = Marking::MarkBitFrom(object); MarkBit markbit = Marking::MarkBitFrom(object);
if ((object->map() != filler_map) && Marking::IsGrey(markbit)) { if ((object->map() != filler_map) && Marking::IsGrey(markbit)) {
Marking::GreyToBlack(markbit); Marking::GreyToBlack(markbit);
MemoryChunk::IncrementLiveBytes(object->address(), object->Size()); MemoryChunk::IncrementLiveBytesFromGC(object->address(), object->Size());
marking_deque->PushBlack(object); marking_deque->PushBlack(object);
if (marking_deque->IsFull()) return; if (marking_deque->IsFull()) return;
} }
@ -1808,7 +1815,7 @@ static void DiscoverGreyObjectsOnPage(MarkingDeque* marking_deque, Page* p) {
Marking::GreyToBlack(markbit); Marking::GreyToBlack(markbit);
Address addr = cell_base + offset * kPointerSize; Address addr = cell_base + offset * kPointerSize;
HeapObject* object = HeapObject::FromAddress(addr); HeapObject* object = HeapObject::FromAddress(addr);
MemoryChunk::IncrementLiveBytes(object->address(), object->Size()); MemoryChunk::IncrementLiveBytesFromGC(object->address(), object->Size());
marking_deque->PushBlack(object); marking_deque->PushBlack(object);
if (marking_deque->IsFull()) return; if (marking_deque->IsFull()) return;
offset += 2; offset += 2;
@ -2297,40 +2304,39 @@ void MarkCompactCollector::ClearNonLiveTransitions() {
Object* prototype = prototype_transitions->get(proto_offset + i * step); Object* prototype = prototype_transitions->get(proto_offset + i * step);
Object* cached_map = prototype_transitions->get(map_offset + i * step); Object* cached_map = prototype_transitions->get(map_offset + i * step);
if (IsMarked(prototype) && IsMarked(cached_map)) { if (IsMarked(prototype) && IsMarked(cached_map)) {
int proto_index = proto_offset + new_number_of_transitions * step;
int map_index = map_offset + new_number_of_transitions * step;
if (new_number_of_transitions != i) { if (new_number_of_transitions != i) {
prototype_transitions->set_unchecked( prototype_transitions->set_unchecked(
heap_, heap_,
proto_offset + new_number_of_transitions * step, proto_index,
prototype, prototype,
UPDATE_WRITE_BARRIER); UPDATE_WRITE_BARRIER);
prototype_transitions->set_unchecked( prototype_transitions->set_unchecked(
heap_, heap_,
map_offset + new_number_of_transitions * step, map_index,
cached_map, cached_map,
SKIP_WRITE_BARRIER); SKIP_WRITE_BARRIER);
} }
Object** slot =
HeapObject::RawField(prototype_transitions,
FixedArray::OffsetOfElementAt(proto_index));
RecordSlot(slot, slot, prototype);
new_number_of_transitions++;
} }
}
// Fill slots that became free with undefined value. if (new_number_of_transitions != number_of_transitions) {
Object* undefined = heap()->undefined_value();
for (int i = new_number_of_transitions * step;
i < number_of_transitions * step;
i++) {
// The undefined object is on a page that is never compacted and never
// in new space so it is OK to skip the write barrier. Also it's a
// root.
prototype_transitions->set_unchecked(heap_,
header + i,
undefined,
SKIP_WRITE_BARRIER);
Object** undefined_slot =
prototype_transitions->data_start() + i;
RecordSlot(undefined_slot, undefined_slot, undefined);
}
map->SetNumberOfProtoTransitions(new_number_of_transitions); map->SetNumberOfProtoTransitions(new_number_of_transitions);
} }
// Fill slots that became free with undefined value.
for (int i = new_number_of_transitions * step;
i < number_of_transitions * step;
i++) {
prototype_transitions->set_undefined(heap_, header + i);
}
// Follow the chain of back pointers to find the prototype. // Follow the chain of back pointers to find the prototype.
Map* current = map; Map* current = map;
while (current->IsMap()) { while (current->IsMap()) {
@ -3630,6 +3636,9 @@ void MarkCompactCollector::SweepSpace(PagedSpace* space, SweeperType sweeper) {
PrintF("Sweeping 0x%" V8PRIxPTR " released page.\n", PrintF("Sweeping 0x%" V8PRIxPTR " released page.\n",
reinterpret_cast<intptr_t>(p)); reinterpret_cast<intptr_t>(p));
} }
// Adjust unswept free bytes because releasing a page expects said
// counter to be accurate for unswept pages.
space->IncreaseUnsweptFreeBytes(p);
space->ReleasePage(p); space->ReleasePage(p);
continue; continue;
} }
@ -3641,7 +3650,7 @@ void MarkCompactCollector::SweepSpace(PagedSpace* space, SweeperType sweeper) {
PrintF("Sweeping 0x%" V8PRIxPTR " lazily postponed.\n", PrintF("Sweeping 0x%" V8PRIxPTR " lazily postponed.\n",
reinterpret_cast<intptr_t>(p)); reinterpret_cast<intptr_t>(p));
} }
space->MarkPageForLazySweeping(p); space->IncreaseUnsweptFreeBytes(p);
continue; continue;
} }

14
deps/v8/src/mark-compact.h

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -198,7 +198,7 @@ class MarkingDeque {
ASSERT(object->IsHeapObject()); ASSERT(object->IsHeapObject());
if (IsFull()) { if (IsFull()) {
Marking::BlackToGrey(object); Marking::BlackToGrey(object);
MemoryChunk::IncrementLiveBytes(object->address(), -object->Size()); MemoryChunk::IncrementLiveBytesFromGC(object->address(), -object->Size());
SetOverflowed(); SetOverflowed();
} else { } else {
array_[top_] = object; array_[top_] = object;
@ -407,7 +407,7 @@ class MarkCompactCollector {
// object from the forwarding address of the previous live object in the // object from the forwarding address of the previous live object in the
// page as input, and is updated to contain the offset to be used for the // page as input, and is updated to contain the offset to be used for the
// next live object in the same page. For spaces using a different // next live object in the same page. For spaces using a different
// encoding (ie, contiguous spaces), the offset parameter is ignored. // encoding (i.e., contiguous spaces), the offset parameter is ignored.
typedef void (*EncodingFunction)(Heap* heap, typedef void (*EncodingFunction)(Heap* heap,
HeapObject* old_object, HeapObject* old_object,
int object_size, int object_size,
@ -580,6 +580,8 @@ class MarkCompactCollector {
bool collect_maps_; bool collect_maps_;
bool flush_monomorphic_ics_;
// A pointer to the current stack-allocated GC tracer object during a full // A pointer to the current stack-allocated GC tracer object during a full
// collection (NULL before and after). // collection (NULL before and after).
GCTracer* tracer_; GCTracer* tracer_;
@ -622,10 +624,16 @@ class MarkCompactCollector {
void AfterMarking(); void AfterMarking();
// Marks the object black and pushes it on the marking stack.
// This is for non-incremental marking.
INLINE(void MarkObject(HeapObject* obj, MarkBit mark_bit)); INLINE(void MarkObject(HeapObject* obj, MarkBit mark_bit));
// Marks the object black. This is for non-incremental marking.
INLINE(void SetMark(HeapObject* obj, MarkBit mark_bit)); INLINE(void SetMark(HeapObject* obj, MarkBit mark_bit));
// Clears the cache of ICs related to this map.
INLINE(void ClearCacheOnMap(Map* map));
void ProcessNewlyMarkedObject(HeapObject* obj); void ProcessNewlyMarkedObject(HeapObject* obj);
// Creates back pointers for all map transitions, stores them in // Creates back pointers for all map transitions, stores them in

12
deps/v8/src/mips/assembler-mips-inl.h

@ -30,7 +30,7 @@
// The original source code covered by the above license above has been // The original source code covered by the above license above has been
// modified significantly by Google Inc. // modified significantly by Google Inc.
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
#ifndef V8_MIPS_ASSEMBLER_MIPS_INL_H_ #ifndef V8_MIPS_ASSEMBLER_MIPS_INL_H_
@ -78,6 +78,16 @@ bool Operand::is_reg() const {
} }
int FPURegister::ToAllocationIndex(FPURegister reg) {
ASSERT(reg.code() % 2 == 0);
ASSERT(reg.code() / 2 < kNumAllocatableRegisters);
ASSERT(reg.is_valid());
ASSERT(!reg.is(kDoubleRegZero));
ASSERT(!reg.is(kLithiumScratchDouble));
return (reg.code() / 2);
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// RelocInfo. // RelocInfo.

19
deps/v8/src/mips/assembler-mips.h

@ -30,7 +30,7 @@
// The original source code covered by the above license above has been // The original source code covered by the above license above has been
// modified significantly by Google Inc. // modified significantly by Google Inc.
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
#ifndef V8_MIPS_ASSEMBLER_MIPS_H_ #ifndef V8_MIPS_ASSEMBLER_MIPS_H_
@ -182,12 +182,7 @@ struct FPURegister {
kNumReservedRegisters; kNumReservedRegisters;
static int ToAllocationIndex(FPURegister reg) { inline static int ToAllocationIndex(FPURegister reg);
ASSERT(reg.code() % 2 == 0);
ASSERT(reg.code() / 2 < kNumAllocatableRegisters);
ASSERT(reg.is_valid());
return (reg.code() / 2);
}
static FPURegister FromAllocationIndex(int index) { static FPURegister FromAllocationIndex(int index) {
ASSERT(index >= 0 && index < kNumAllocatableRegisters); ASSERT(index >= 0 && index < kNumAllocatableRegisters);
@ -302,6 +297,14 @@ const FPURegister f29 = { 29 };
const FPURegister f30 = { 30 }; const FPURegister f30 = { 30 };
const FPURegister f31 = { 31 }; const FPURegister f31 = { 31 };
// Register aliases.
// cp is assumed to be a callee saved register.
static const Register& kLithiumScratchReg = s3; // Scratch register.
static const Register& kLithiumScratchReg2 = s4; // Scratch register.
static const Register& kRootRegister = s6; // Roots array pointer.
static const Register& cp = s7; // JavaScript context pointer.
static const Register& fp = s8_fp; // Alias for fp.
static const DoubleRegister& kLithiumScratchDouble = f30;
static const FPURegister& kDoubleRegZero = f28; static const FPURegister& kDoubleRegZero = f28;
// FPU (coprocessor 1) control registers. // FPU (coprocessor 1) control registers.
@ -667,7 +670,7 @@ class Assembler : public AssemblerBase {
// Never use the int16_t b(l)cond version with a branch offset // Never use the int16_t b(l)cond version with a branch offset
// instead of using the Label* version. // instead of using the Label* version.
// Jump targets must be in the current 256 MB-aligned region. ie 28 bits. // Jump targets must be in the current 256 MB-aligned region. i.e. 28 bits.
void j(int32_t target); void j(int32_t target);
void jal(int32_t target); void jal(int32_t target);
void jalr(Register rs, Register rd = ra); void jalr(Register rs, Register rd = ra);

6
deps/v8/src/mips/builtins-mips.cc

@ -895,7 +895,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// Initialize the FixedArray. // Initialize the FixedArray.
// a1: constructor // a1: constructor
// a3: number of elements in properties array (un-tagged) // a3: number of elements in properties array (untagged)
// t4: JSObject // t4: JSObject
// t5: start of next object // t5: start of next object
__ LoadRoot(t6, Heap::kFixedArrayMapRootIndex); __ LoadRoot(t6, Heap::kFixedArrayMapRootIndex);
@ -1099,7 +1099,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- a0: code entry // -- a0: code entry
// -- a1: function // -- a1: function
// -- a2: reveiver_pointer // -- a2: receiver_pointer
// -- a3: argc // -- a3: argc
// -- s0: argv // -- s0: argv
// ----------------------------------- // -----------------------------------
@ -1121,7 +1121,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
// Copy arguments to the stack in a loop. // Copy arguments to the stack in a loop.
// a3: argc // a3: argc
// s0: argv, ie points to first arg // s0: argv, i.e. points to first arg
Label loop, entry; Label loop, entry;
__ sll(t0, a3, kPointerSizeLog2); __ sll(t0, a3, kPointerSizeLog2);
__ addu(t2, s0, t0); __ addu(t2, s0, t0);

29
deps/v8/src/mips/code-stubs-mips.cc

@ -4061,7 +4061,7 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
// Registers: // Registers:
// a0: entry address // a0: entry address
// a1: function // a1: function
// a2: reveiver // a2: receiver
// a3: argc // a3: argc
// //
// Stack: // Stack:
@ -4103,7 +4103,7 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
// Registers: // Registers:
// a0: entry_address // a0: entry_address
// a1: function // a1: function
// a2: reveiver_pointer // a2: receiver_pointer
// a3: argc // a3: argc
// s0: argv // s0: argv
// //
@ -4170,7 +4170,7 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
// Registers: // Registers:
// a0: entry_address // a0: entry_address
// a1: function // a1: function
// a2: reveiver_pointer // a2: receiver_pointer
// a3: argc // a3: argc
// s0: argv // s0: argv
// //
@ -4252,7 +4252,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
const Register inline_site = t5; const Register inline_site = t5;
const Register scratch = a2; const Register scratch = a2;
const int32_t kDeltaToLoadBoolResult = 4 * kPointerSize; const int32_t kDeltaToLoadBoolResult = 5 * kPointerSize;
Label slow, loop, is_instance, is_not_instance, not_js_object; Label slow, loop, is_instance, is_not_instance, not_js_object;
@ -4296,11 +4296,12 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
// Patch the (relocated) inlined map check. // Patch the (relocated) inlined map check.
// The offset was stored in t0 safepoint slot. // The offset was stored in t0 safepoint slot.
// (See LCodeGen::DoDeferredLInstanceOfKnownGlobal) // (See LCodeGen::DoDeferredLInstanceOfKnownGlobal).
__ LoadFromSafepointRegisterSlot(scratch, t0); __ LoadFromSafepointRegisterSlot(scratch, t0);
__ Subu(inline_site, ra, scratch); __ Subu(inline_site, ra, scratch);
// Patch the relocated value to map. // Get the map location in scratch and patch it.
__ PatchRelocatedValue(inline_site, scratch, map); __ GetRelocatedValue(inline_site, scratch, v1); // v1 used as scratch.
__ sw(map, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
} }
// Register mapping: a3 is object map and t0 is function prototype. // Register mapping: a3 is object map and t0 is function prototype.
@ -5006,9 +5007,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
STATIC_ASSERT(kAsciiStringTag == 4); STATIC_ASSERT(kAsciiStringTag == 4);
STATIC_ASSERT(kTwoByteStringTag == 0); STATIC_ASSERT(kTwoByteStringTag == 0);
// Find the code object based on the assumptions above. // Find the code object based on the assumptions above.
__ And(a0, a0, Operand(kStringEncodingMask)); // Non-zero for ascii. __ And(a0, a0, Operand(kStringEncodingMask)); // Non-zero for ASCII.
__ lw(t9, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset)); __ lw(t9, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset));
__ sra(a3, a0, 2); // a3 is 1 for ascii, 0 for UC16 (usyed below). __ sra(a3, a0, 2); // a3 is 1 for ASCII, 0 for UC16 (used below).
__ lw(t1, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset)); __ lw(t1, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset));
__ movz(t9, t1, a0); // If UC16 (a0 is 0), replace t9 w/kDataUC16CodeOffset. __ movz(t9, t1, a0); // If UC16 (a0 is 0), replace t9 w/kDataUC16CodeOffset.
@ -6033,7 +6034,7 @@ void SubStringStub::Generate(MacroAssembler* masm) {
Label result_longer_than_two; Label result_longer_than_two;
// Check for special case of two character ascii string, in which case // Check for special case of two character ASCII string, in which case
// we do a lookup in the symbol table first. // we do a lookup in the symbol table first.
__ li(t0, 2); __ li(t0, 2);
__ Branch(&result_longer_than_two, gt, a2, Operand(t0)); __ Branch(&result_longer_than_two, gt, a2, Operand(t0));
@ -6164,7 +6165,7 @@ void SubStringStub::Generate(MacroAssembler* masm) {
__ And(t0, a1, Operand(kStringEncodingMask)); __ And(t0, a1, Operand(kStringEncodingMask));
__ Branch(&two_byte_sequential, eq, t0, Operand(zero_reg)); __ Branch(&two_byte_sequential, eq, t0, Operand(zero_reg));
// Allocate and copy the resulting ascii string. // Allocate and copy the resulting ASCII string.
__ AllocateAsciiString(v0, a2, t0, t2, t3, &runtime); __ AllocateAsciiString(v0, a2, t0, t2, t3, &runtime);
// Locate first character of substring to copy. // Locate first character of substring to copy.
@ -6491,7 +6492,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
__ bind(&longer_than_two); __ bind(&longer_than_two);
// Check if resulting string will be flat. // Check if resulting string will be flat.
__ Branch(&string_add_flat_result, lt, t2, __ Branch(&string_add_flat_result, lt, t2,
Operand(String::kMinNonFlatLength)); Operand(ConsString::kMinLength));
// Handle exceptionally long strings in the runtime system. // Handle exceptionally long strings in the runtime system.
STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0); STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0);
ASSERT(IsPowerOf2(String::kMaxLength + 1)); ASSERT(IsPowerOf2(String::kMaxLength + 1));
@ -6508,7 +6509,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
} }
Label non_ascii, allocated, ascii_data; Label non_ascii, allocated, ascii_data;
STATIC_ASSERT(kTwoByteStringTag == 0); STATIC_ASSERT(kTwoByteStringTag == 0);
// Branch to non_ascii if either string-encoding field is zero (non-ascii). // Branch to non_ascii if either string-encoding field is zero (non-ASCII).
__ And(t4, t0, Operand(t1)); __ And(t4, t0, Operand(t1));
__ And(t4, t4, Operand(kStringEncodingMask)); __ And(t4, t4, Operand(kStringEncodingMask));
__ Branch(&non_ascii, eq, t4, Operand(zero_reg)); __ Branch(&non_ascii, eq, t4, Operand(zero_reg));
@ -6543,7 +6544,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
__ Branch(&allocated); __ Branch(&allocated);
// We cannot encounter sliced strings or cons strings here since: // We cannot encounter sliced strings or cons strings here since:
STATIC_ASSERT(SlicedString::kMinLength >= String::kMinNonFlatLength); STATIC_ASSERT(SlicedString::kMinLength >= ConsString::kMinLength);
// Handle creating a flat result from either external or sequential strings. // Handle creating a flat result from either external or sequential strings.
// Locate the first characters' locations. // Locate the first characters' locations.
// a0: first string // a0: first string

4
deps/v8/src/mips/constants-mips.cc

@ -302,7 +302,7 @@ Instruction::Type Instruction::InstructionType() const {
return kRegisterType; return kRegisterType;
}; };
break; break;
// 16 bits Immediate type instructions. eg: addi dest, src, imm16. // 16 bits Immediate type instructions. e.g.: addi dest, src, imm16.
case REGIMM: case REGIMM:
case BEQ: case BEQ:
case BNE: case BNE:
@ -337,7 +337,7 @@ Instruction::Type Instruction::InstructionType() const {
case SWC1: case SWC1:
case SDC1: case SDC1:
return kImmediateType; return kImmediateType;
// 26 bits immediate type instructions. eg: j imm26. // 26 bits immediate type instructions. e.g.: j imm26.
case J: case J:
case JAL: case JAL:
return kJumpType; return kJumpType;

2
deps/v8/src/mips/constants-mips.h

@ -747,7 +747,7 @@ class Instruction {
// Say if the instruction should not be used in a branch delay slot. // Say if the instruction should not be used in a branch delay slot.
bool IsForbiddenInBranchDelay() const; bool IsForbiddenInBranchDelay() const;
// Say if the instruction 'links'. eg: jal, bal. // Say if the instruction 'links'. e.g. jal, bal.
bool IsLinkingInstruction() const; bool IsLinkingInstruction() const;
// Say if the instruction is a break or a trap. // Say if the instruction is a break or a trap.
bool IsTrap() const; bool IsTrap() const;

6
deps/v8/src/mips/full-codegen-mips.cc

@ -125,7 +125,7 @@ class JumpPatchSite BASE_EMBEDDED {
// function. // function.
// //
// The live registers are: // The live registers are:
// o a1: the JS function object being called (ie, ourselves) // o a1: the JS function object being called (i.e. ourselves)
// o cp: our context // o cp: our context
// o fp: our caller's frame pointer // o fp: our caller's frame pointer
// o sp: stack pointer // o sp: stack pointer
@ -3655,7 +3655,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
// One-character separator case. // One-character separator case.
__ bind(&one_char_separator); __ bind(&one_char_separator);
// Replace separator with its ascii character value. // Replace separator with its ASCII character value.
__ lbu(separator, FieldMemOperand(separator, SeqAsciiString::kHeaderSize)); __ lbu(separator, FieldMemOperand(separator, SeqAsciiString::kHeaderSize));
// Jump into the loop after the code that copies the separator, so the first // Jump into the loop after the code that copies the separator, so the first
// element is not preceded by a separator. // element is not preceded by a separator.
@ -3666,7 +3666,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
// result_pos: the position to which we are currently copying characters. // result_pos: the position to which we are currently copying characters.
// element: Current array element. // element: Current array element.
// elements_end: Array end. // elements_end: Array end.
// separator: Single separator ascii char (in lower byte). // separator: Single separator ASCII char (in lower byte).
// Copy the separator character to the result. // Copy the separator character to the result.
__ sb(separator, MemOperand(result_pos)); __ sb(separator, MemOperand(result_pos));

29
deps/v8/src/mips/ic-mips.cc

@ -1033,19 +1033,26 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ lw(t0, FieldMemOperand(a0, String::kHashFieldOffset)); __ lw(t0, FieldMemOperand(a0, String::kHashFieldOffset));
__ sra(at, t0, String::kHashShift); __ sra(at, t0, String::kHashShift);
__ xor_(a3, a3, at); __ xor_(a3, a3, at);
__ And(a3, a3, Operand(KeyedLookupCache::kCapacityMask)); int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask;
__ And(a3, a3, Operand(mask));
// Load the key (consisting of map and symbol) from the cache and // Load the key (consisting of map and symbol) from the cache and
// check for match. // check for match.
Label try_second_entry, hit_on_first_entry, load_in_object_property;
ExternalReference cache_keys = ExternalReference cache_keys =
ExternalReference::keyed_lookup_cache_keys(isolate); ExternalReference::keyed_lookup_cache_keys(isolate);
__ li(t0, Operand(cache_keys)); __ li(t0, Operand(cache_keys));
__ sll(at, a3, kPointerSizeLog2 + 1); __ sll(at, a3, kPointerSizeLog2 + 1);
__ addu(t0, t0, at); __ addu(t0, t0, at);
__ lw(t1, MemOperand(t0)); // Move t0 to symbol.
__ Addu(t0, t0, Operand(kPointerSize));
__ Branch(&slow, ne, a2, Operand(t1));
__ lw(t1, MemOperand(t0)); __ lw(t1, MemOperand(t0));
__ Branch(&try_second_entry, ne, a2, Operand(t1));
__ lw(t1, MemOperand(t0, kPointerSize));
__ Branch(&hit_on_first_entry, eq, a0, Operand(t1));
__ bind(&try_second_entry);
__ lw(t1, MemOperand(t0, kPointerSize * 2));
__ Branch(&slow, ne, a2, Operand(t1));
__ lw(t1, MemOperand(t0, kPointerSize * 3));
__ Branch(&slow, ne, a0, Operand(t1)); __ Branch(&slow, ne, a0, Operand(t1));
// Get field offset. // Get field offset.
@ -1055,6 +1062,19 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
// a3 : lookup cache index // a3 : lookup cache index
ExternalReference cache_field_offsets = ExternalReference cache_field_offsets =
ExternalReference::keyed_lookup_cache_field_offsets(isolate); ExternalReference::keyed_lookup_cache_field_offsets(isolate);
// Hit on second entry.
__ li(t0, Operand(cache_field_offsets));
__ sll(at, a3, kPointerSizeLog2);
__ addu(at, t0, at);
__ lw(t1, MemOperand(at, kPointerSize));
__ lbu(t2, FieldMemOperand(a2, Map::kInObjectPropertiesOffset));
__ Subu(t1, t1, t2);
__ Branch(&property_array_property, ge, t1, Operand(zero_reg));
__ Branch(&load_in_object_property);
// Hit on first entry.
__ bind(&hit_on_first_entry);
__ li(t0, Operand(cache_field_offsets)); __ li(t0, Operand(cache_field_offsets));
__ sll(at, a3, kPointerSizeLog2); __ sll(at, a3, kPointerSizeLog2);
__ addu(at, t0, at); __ addu(at, t0, at);
@ -1064,6 +1084,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ Branch(&property_array_property, ge, t1, Operand(zero_reg)); __ Branch(&property_array_property, ge, t1, Operand(zero_reg));
// Load in-object property. // Load in-object property.
__ bind(&load_in_object_property);
__ lbu(t2, FieldMemOperand(a2, Map::kInstanceSizeOffset)); __ lbu(t2, FieldMemOperand(a2, Map::kInstanceSizeOffset));
__ addu(t2, t2, t1); // Index from start of object. __ addu(t2, t2, t1); // Index from start of object.
__ Subu(a1, a1, Operand(kHeapObjectTag)); // Remove the heap tag. __ Subu(a1, a1, Operand(kHeapObjectTag)); // Remove the heap tag.

116
deps/v8/src/mips/lithium-codegen-mips.cc

@ -1862,9 +1862,8 @@ void LCodeGen::DoHasCachedArrayIndexAndBranch(
} }
// Branches to a label or falls through with this instance class-name adr // Branches to a label or falls through with the answer in flags. Trashes
// returned in temp reg, available for comparison by the caller. Trashes the // the temp registers, but not the input.
// temp registers, but not the input. Only input and temp2 may alias.
void LCodeGen::EmitClassOfTest(Label* is_true, void LCodeGen::EmitClassOfTest(Label* is_true,
Label* is_false, Label* is_false,
Handle<String>class_name, Handle<String>class_name,
@ -1872,7 +1871,9 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
Register temp, Register temp,
Register temp2) { Register temp2) {
ASSERT(!input.is(temp)); ASSERT(!input.is(temp));
ASSERT(!temp.is(temp2)); // But input and temp2 may be the same register. ASSERT(!input.is(temp2));
ASSERT(!temp.is(temp2));
__ JumpIfSmi(input, is_false); __ JumpIfSmi(input, is_false);
if (class_name->IsEqualTo(CStrVector("Function"))) { if (class_name->IsEqualTo(CStrVector("Function"))) {
@ -2018,7 +2019,10 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
// We use Factory::the_hole_value() on purpose instead of loading from the // We use Factory::the_hole_value() on purpose instead of loading from the
// root array to force relocation to be able to later patch with // root array to force relocation to be able to later patch with
// the cached map. // the cached map.
__ li(at, Operand(factory()->the_hole_value()), true); Handle<JSGlobalPropertyCell> cell =
factory()->NewJSGlobalPropertyCell(factory()->the_hole_value());
__ li(at, Operand(Handle<Object>(cell)));
__ lw(at, FieldMemOperand(at, JSGlobalPropertyCell::kValueOffset));
__ Branch(&cache_miss, ne, map, Operand(at)); __ Branch(&cache_miss, ne, map, Operand(at));
// We use Factory::the_hole_value() on purpose instead of loading from the // We use Factory::the_hole_value() on purpose instead of loading from the
// root array to force relocation to be able to later patch // root array to force relocation to be able to later patch
@ -2265,7 +2269,7 @@ void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
Handle<String> name) { Handle<String> name) {
LookupResult lookup(isolate()); LookupResult lookup(isolate());
type->LookupInDescriptors(NULL, *name, &lookup); type->LookupInDescriptors(NULL, *name, &lookup);
ASSERT(lookup.IsProperty() && ASSERT(lookup.IsFound() &&
(lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION)); (lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION));
if (lookup.type() == FIELD) { if (lookup.type() == FIELD) {
int index = lookup.GetLocalFieldIndexFromMap(*type); int index = lookup.GetLocalFieldIndexFromMap(*type);
@ -2715,7 +2719,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
this, pointers, Safepoint::kLazyDeopt); this, pointers, Safepoint::kLazyDeopt);
// The number of arguments is stored in receiver which is a0, as expected // The number of arguments is stored in receiver which is a0, as expected
// by InvokeFunction. // by InvokeFunction.
v8::internal::ParameterCount actual(receiver); ParameterCount actual(receiver);
__ InvokeFunction(function, actual, CALL_FUNCTION, __ InvokeFunction(function, actual, CALL_FUNCTION,
safepoint_generator, CALL_AS_METHOD); safepoint_generator, CALL_AS_METHOD);
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
@ -2771,31 +2775,41 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
int arity, int arity,
LInstruction* instr, LInstruction* instr,
CallKind call_kind) { CallKind call_kind) {
// Change context if needed. bool can_invoke_directly = !function->NeedsArgumentsAdaption() ||
bool change_context = function->shared()->formal_parameter_count() == arity;
(info()->closure()->context() != function->context()) ||
scope()->contains_with() ||
(scope()->num_heap_slots() > 0);
if (change_context) {
__ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
}
// Set a0 to arguments count if adaption is not needed. Assumes that a0
// is available to write to at this point.
if (!function->NeedsArgumentsAdaption()) {
__ li(a0, Operand(arity));
}
LPointerMap* pointers = instr->pointer_map(); LPointerMap* pointers = instr->pointer_map();
RecordPosition(pointers->position()); RecordPosition(pointers->position());
// Invoke function. if (can_invoke_directly) {
__ SetCallKind(t1, call_kind); __ LoadHeapObject(a1, function);
__ lw(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); // Change context if needed.
__ Call(at); bool change_context =
(info()->closure()->context() != function->context()) ||
scope()->contains_with() ||
(scope()->num_heap_slots() > 0);
if (change_context) {
__ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
}
// Set up deoptimization. // Set r0 to arguments count if adaption is not needed. Assumes that r0
RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); // is available to write to at this point.
if (!function->NeedsArgumentsAdaption()) {
__ li(a0, Operand(arity));
}
// Invoke function.
__ SetCallKind(t1, call_kind);
__ lw(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
__ Call(at);
// Set up deoptimization.
RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
} else {
SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
ParameterCount count(arity);
__ InvokeFunction(function, count, CALL_FUNCTION, generator, call_kind);
}
// Restore context. // Restore context.
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
@ -2805,7 +2819,6 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
ASSERT(ToRegister(instr->result()).is(v0)); ASSERT(ToRegister(instr->result()).is(v0));
__ mov(a0, v0); __ mov(a0, v0);
__ LoadHeapObject(a1, instr->function());
CallKnownFunction(instr->function(), instr->arity(), instr, CALL_AS_METHOD); CallKnownFunction(instr->function(), instr->arity(), instr, CALL_AS_METHOD);
} }
@ -2884,7 +2897,7 @@ void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
__ mov(result, input); __ mov(result, input);
ASSERT_EQ(2, masm()->InstructionsGeneratedSince(&done)); ASSERT_EQ(2, masm()->InstructionsGeneratedSince(&done));
__ subu(result, zero_reg, input); __ subu(result, zero_reg, input);
// Overflow if result is still negative, ie 0x80000000. // Overflow if result is still negative, i.e. 0x80000000.
DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg)); DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg));
__ bind(&done); __ bind(&done);
} }
@ -3248,7 +3261,6 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
ASSERT(ToRegister(instr->result()).is(v0)); ASSERT(ToRegister(instr->result()).is(v0));
__ LoadHeapObject(a1, instr->target());
CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION); CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
} }
@ -3816,6 +3828,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
void LCodeGen::EmitNumberUntagD(Register input_reg, void LCodeGen::EmitNumberUntagD(Register input_reg,
DoubleRegister result_reg, DoubleRegister result_reg,
bool deoptimize_on_undefined, bool deoptimize_on_undefined,
bool deoptimize_on_minus_zero,
LEnvironment* env) { LEnvironment* env) {
Register scratch = scratch0(); Register scratch = scratch0();
@ -3845,6 +3858,12 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
} }
// Heap number to double register conversion. // Heap number to double register conversion.
__ ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset)); __ ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset));
if (deoptimize_on_minus_zero) {
__ mfc1(at, result_reg.low());
__ Branch(&done, ne, at, Operand(zero_reg));
__ mfc1(scratch, result_reg.high());
DeoptimizeIf(eq, env, scratch, Operand(HeapNumber::kSignMask));
}
__ Branch(&done); __ Branch(&done);
// Smi to double register conversion // Smi to double register conversion
@ -3976,6 +3995,7 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
EmitNumberUntagD(input_reg, result_reg, EmitNumberUntagD(input_reg, result_reg,
instr->hydrogen()->deoptimize_on_undefined(), instr->hydrogen()->deoptimize_on_undefined(),
instr->hydrogen()->deoptimize_on_minus_zero(),
instr->environment()); instr->environment());
} }
@ -4086,16 +4106,26 @@ void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
} }
void LCodeGen::DoCheckMapCommon(Register reg,
Register scratch,
Handle<Map> map,
CompareMapMode mode,
LEnvironment* env) {
Label success;
__ CompareMapAndBranch(reg, scratch, map, &success, eq, &success, mode);
DeoptimizeIf(al, env);
__ bind(&success);
}
void LCodeGen::DoCheckMap(LCheckMap* instr) { void LCodeGen::DoCheckMap(LCheckMap* instr) {
Register scratch = scratch0(); Register scratch = scratch0();
LOperand* input = instr->InputAt(0); LOperand* input = instr->InputAt(0);
ASSERT(input->IsRegister()); ASSERT(input->IsRegister());
Register reg = ToRegister(input); Register reg = ToRegister(input);
__ lw(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); Handle<Map> map = instr->hydrogen()->map();
DeoptimizeIf(ne, DoCheckMapCommon(reg, scratch, map, instr->hydrogen()->mode(),
instr->environment(), instr->environment());
scratch,
Operand(instr->hydrogen()->map()));
} }
@ -4163,11 +4193,9 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
// Check prototype maps up to the holder. // Check prototype maps up to the holder.
while (!current_prototype.is_identical_to(holder)) { while (!current_prototype.is_identical_to(holder)) {
__ lw(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset)); DoCheckMapCommon(temp1, temp2,
DeoptimizeIf(ne, Handle<Map>(current_prototype->map()),
instr->environment(), ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment());
temp2,
Operand(Handle<Map>(current_prototype->map())));
current_prototype = current_prototype =
Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype()));
// Load next prototype object. // Load next prototype object.
@ -4175,11 +4203,9 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
} }
// Check the holder map. // Check the holder map.
__ lw(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset)); DoCheckMapCommon(temp1, temp2,
DeoptimizeIf(ne, Handle<Map>(current_prototype->map()),
instr->environment(), ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment());
temp2,
Operand(Handle<Map>(current_prototype->map())));
} }

10
deps/v8/src/mips/lithium-codegen-mips.h

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -115,6 +115,9 @@ class LCodeGen BASE_EMBEDDED {
void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
Label* map_check); Label* map_check);
void DoCheckMapCommon(Register reg, Register scratch, Handle<Map> map,
CompareMapMode mode, LEnvironment* env);
// Parallel move support. // Parallel move support.
void DoParallelMove(LParallelMove* move); void DoParallelMove(LParallelMove* move);
void DoGap(LGap* instr); void DoGap(LGap* instr);
@ -223,8 +226,8 @@ class LCodeGen BASE_EMBEDDED {
Safepoint::DeoptMode mode); Safepoint::DeoptMode mode);
void DeoptimizeIf(Condition cc, void DeoptimizeIf(Condition cc,
LEnvironment* environment, LEnvironment* environment,
Register src1, Register src1 = zero_reg,
const Operand& src2); const Operand& src2 = Operand(zero_reg));
void AddToTranslation(Translation* translation, void AddToTranslation(Translation* translation,
LOperand* op, LOperand* op,
@ -280,6 +283,7 @@ class LCodeGen BASE_EMBEDDED {
void EmitNumberUntagD(Register input, void EmitNumberUntagD(Register input,
DoubleRegister result, DoubleRegister result,
bool deoptimize_on_undefined, bool deoptimize_on_undefined,
bool deoptimize_on_minus_zero,
LEnvironment* env); LEnvironment* env);
// Emits optimized code for typeof x == "y". Modifies input register. // Emits optimized code for typeof x == "y". Modifies input register.

23
deps/v8/src/mips/lithium-gap-resolver-mips.cc

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -34,7 +34,6 @@ namespace v8 {
namespace internal { namespace internal {
static const Register kSavedValueRegister = kLithiumScratchReg; static const Register kSavedValueRegister = kLithiumScratchReg;
static const DoubleRegister kSavedDoubleValueRegister = kLithiumScratchDouble;
LGapResolver::LGapResolver(LCodeGen* owner) LGapResolver::LGapResolver(LCodeGen* owner)
: cgen_(owner), : cgen_(owner),
@ -175,9 +174,9 @@ void LGapResolver::BreakCycle(int index) {
} else if (source->IsStackSlot()) { } else if (source->IsStackSlot()) {
__ lw(kSavedValueRegister, cgen_->ToMemOperand(source)); __ lw(kSavedValueRegister, cgen_->ToMemOperand(source));
} else if (source->IsDoubleRegister()) { } else if (source->IsDoubleRegister()) {
__ mov_d(kSavedDoubleValueRegister, cgen_->ToDoubleRegister(source)); __ mov_d(kLithiumScratchDouble, cgen_->ToDoubleRegister(source));
} else if (source->IsDoubleStackSlot()) { } else if (source->IsDoubleStackSlot()) {
__ ldc1(kSavedDoubleValueRegister, cgen_->ToMemOperand(source)); __ ldc1(kLithiumScratchDouble, cgen_->ToMemOperand(source));
} else { } else {
UNREACHABLE(); UNREACHABLE();
} }
@ -190,16 +189,16 @@ void LGapResolver::RestoreValue() {
ASSERT(in_cycle_); ASSERT(in_cycle_);
ASSERT(saved_destination_ != NULL); ASSERT(saved_destination_ != NULL);
// Spilled value is in kSavedValueRegister or kSavedDoubleValueRegister. // Spilled value is in kSavedValueRegister or kLithiumScratchDouble.
if (saved_destination_->IsRegister()) { if (saved_destination_->IsRegister()) {
__ mov(cgen_->ToRegister(saved_destination_), kSavedValueRegister); __ mov(cgen_->ToRegister(saved_destination_), kSavedValueRegister);
} else if (saved_destination_->IsStackSlot()) { } else if (saved_destination_->IsStackSlot()) {
__ sw(kSavedValueRegister, cgen_->ToMemOperand(saved_destination_)); __ sw(kSavedValueRegister, cgen_->ToMemOperand(saved_destination_));
} else if (saved_destination_->IsDoubleRegister()) { } else if (saved_destination_->IsDoubleRegister()) {
__ mov_d(cgen_->ToDoubleRegister(saved_destination_), __ mov_d(cgen_->ToDoubleRegister(saved_destination_),
kSavedDoubleValueRegister); kLithiumScratchDouble);
} else if (saved_destination_->IsDoubleStackSlot()) { } else if (saved_destination_->IsDoubleStackSlot()) {
__ sdc1(kSavedDoubleValueRegister, __ sdc1(kLithiumScratchDouble,
cgen_->ToMemOperand(saved_destination_)); cgen_->ToMemOperand(saved_destination_));
} else { } else {
UNREACHABLE(); UNREACHABLE();
@ -239,8 +238,8 @@ void LGapResolver::EmitMove(int index) {
// Therefore we can't use 'at'. It is OK if the read from the source // Therefore we can't use 'at'. It is OK if the read from the source
// destroys 'at', since that happens before the value is read. // destroys 'at', since that happens before the value is read.
// This uses only a single reg of the double reg-pair. // This uses only a single reg of the double reg-pair.
__ lwc1(kSavedDoubleValueRegister, source_operand); __ lwc1(kLithiumScratchDouble, source_operand);
__ swc1(kSavedDoubleValueRegister, destination_operand); __ swc1(kLithiumScratchDouble, destination_operand);
} else { } else {
__ lw(at, source_operand); __ lw(at, source_operand);
__ sw(at, destination_operand); __ sw(at, destination_operand);
@ -291,7 +290,7 @@ void LGapResolver::EmitMove(int index) {
ASSERT(destination->IsDoubleStackSlot()); ASSERT(destination->IsDoubleStackSlot());
MemOperand destination_operand = cgen_->ToMemOperand(destination); MemOperand destination_operand = cgen_->ToMemOperand(destination);
if (in_cycle_) { if (in_cycle_) {
// kSavedDoubleValueRegister was used to break the cycle, // kLithiumScratchDouble was used to break the cycle,
// but kSavedValueRegister is free. // but kSavedValueRegister is free.
MemOperand source_high_operand = MemOperand source_high_operand =
cgen_->ToHighMemOperand(source); cgen_->ToHighMemOperand(source);
@ -302,8 +301,8 @@ void LGapResolver::EmitMove(int index) {
__ lw(kSavedValueRegister, source_high_operand); __ lw(kSavedValueRegister, source_high_operand);
__ sw(kSavedValueRegister, destination_high_operand); __ sw(kSavedValueRegister, destination_high_operand);
} else { } else {
__ ldc1(kSavedDoubleValueRegister, source_operand); __ ldc1(kLithiumScratchDouble, source_operand);
__ sdc1(kSavedDoubleValueRegister, destination_operand); __ sdc1(kLithiumScratchDouble, destination_operand);
} }
} }
} else { } else {

2
deps/v8/src/mips/lithium-mips.cc

@ -1554,7 +1554,7 @@ LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
LInstruction* LChunkBuilder::DoClassOfTestAndBranch( LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
HClassOfTestAndBranch* instr) { HClassOfTestAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged()); ASSERT(instr->value()->representation().IsTagged());
return new LClassOfTestAndBranch(UseTempRegister(instr->value()), return new LClassOfTestAndBranch(UseRegister(instr->value()),
TempRegister()); TempRegister());
} }

144
deps/v8/src/mips/macro-assembler-mips.cc

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -444,8 +444,10 @@ void MacroAssembler::GetNumberHash(Register reg0, Register scratch) {
xor_(reg0, reg0, at); xor_(reg0, reg0, at);
// hash = hash * 2057; // hash = hash * 2057;
li(scratch, Operand(2057)); sll(scratch, reg0, 11);
mul(reg0, reg0, scratch); sll(at, reg0, 3);
addu(reg0, reg0, at);
addu(reg0, reg0, scratch);
// hash = hash ^ (hash >> 16); // hash = hash ^ (hash >> 16);
srl(at, reg0, 16); srl(at, reg0, 16);
@ -1176,7 +1178,7 @@ void MacroAssembler::ConvertToInt32(Register source,
Branch(not_int32, gt, scratch2, Operand(non_smi_exponent)); Branch(not_int32, gt, scratch2, Operand(non_smi_exponent));
// We know the exponent is smaller than 30 (biased). If it is less than // We know the exponent is smaller than 30 (biased). If it is less than
// 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, ie // 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, i.e.
// it rounds to zero. // it rounds to zero.
const uint32_t zero_exponent = const uint32_t zero_exponent =
(HeapNumber::kExponentBias + 0) << HeapNumber::kExponentShift; (HeapNumber::kExponentBias + 0) << HeapNumber::kExponentShift;
@ -3313,17 +3315,51 @@ void MacroAssembler::StoreNumberToDoubleElements(Register value_reg,
} }
void MacroAssembler::CompareMapAndBranch(Register obj,
Register scratch,
Handle<Map> map,
Label* early_success,
Condition cond,
Label* branch_to,
CompareMapMode mode) {
lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
Operand right = Operand(map);
if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) {
Map* transitioned_fast_element_map(
map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL));
ASSERT(transitioned_fast_element_map == NULL ||
map->elements_kind() != FAST_ELEMENTS);
if (transitioned_fast_element_map != NULL) {
Branch(early_success, eq, scratch, right);
right = Operand(Handle<Map>(transitioned_fast_element_map));
}
Map* transitioned_double_map(
map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL));
ASSERT(transitioned_double_map == NULL ||
map->elements_kind() == FAST_SMI_ONLY_ELEMENTS);
if (transitioned_double_map != NULL) {
Branch(early_success, eq, scratch, right);
right = Operand(Handle<Map>(transitioned_double_map));
}
}
Branch(branch_to, cond, scratch, right);
}
void MacroAssembler::CheckMap(Register obj, void MacroAssembler::CheckMap(Register obj,
Register scratch, Register scratch,
Handle<Map> map, Handle<Map> map,
Label* fail, Label* fail,
SmiCheckType smi_check_type) { SmiCheckType smi_check_type,
CompareMapMode mode) {
if (smi_check_type == DO_SMI_CHECK) { if (smi_check_type == DO_SMI_CHECK) {
JumpIfSmi(obj, fail); JumpIfSmi(obj, fail);
} }
lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); Label success;
li(at, Operand(map)); CompareMapAndBranch(obj, scratch, map, &success, ne, fail, mode);
Branch(fail, ne, scratch, Operand(at)); bind(&success);
} }
@ -3430,10 +3466,12 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
Handle<Code> code_constant, Handle<Code> code_constant,
Register code_reg, Register code_reg,
Label* done, Label* done,
bool* definitely_mismatches,
InvokeFlag flag, InvokeFlag flag,
const CallWrapper& call_wrapper, const CallWrapper& call_wrapper,
CallKind call_kind) { CallKind call_kind) {
bool definitely_matches = false; bool definitely_matches = false;
*definitely_mismatches = false;
Label regular_invoke; Label regular_invoke;
// Check whether the expected and actual arguments count match. If not, // Check whether the expected and actual arguments count match. If not,
@ -3464,6 +3502,7 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
// arguments. // arguments.
definitely_matches = true; definitely_matches = true;
} else { } else {
*definitely_mismatches = true;
li(a2, Operand(expected.immediate())); li(a2, Operand(expected.immediate()));
} }
} }
@ -3487,7 +3526,9 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
SetCallKind(t1, call_kind); SetCallKind(t1, call_kind);
Call(adaptor); Call(adaptor);
call_wrapper.AfterCall(); call_wrapper.AfterCall();
jmp(done); if (!*definitely_mismatches) {
Branch(done);
}
} else { } else {
SetCallKind(t1, call_kind); SetCallKind(t1, call_kind);
Jump(adaptor, RelocInfo::CODE_TARGET); Jump(adaptor, RelocInfo::CODE_TARGET);
@ -3508,21 +3549,25 @@ void MacroAssembler::InvokeCode(Register code,
Label done; Label done;
InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag, bool definitely_mismatches = false;
InvokePrologue(expected, actual, Handle<Code>::null(), code,
&done, &definitely_mismatches, flag,
call_wrapper, call_kind); call_wrapper, call_kind);
if (flag == CALL_FUNCTION) { if (!definitely_mismatches) {
call_wrapper.BeforeCall(CallSize(code)); if (flag == CALL_FUNCTION) {
SetCallKind(t1, call_kind); call_wrapper.BeforeCall(CallSize(code));
Call(code); SetCallKind(t1, call_kind);
call_wrapper.AfterCall(); Call(code);
} else { call_wrapper.AfterCall();
ASSERT(flag == JUMP_FUNCTION); } else {
SetCallKind(t1, call_kind); ASSERT(flag == JUMP_FUNCTION);
Jump(code); SetCallKind(t1, call_kind);
Jump(code);
}
// Continue here if InvokePrologue does handle the invocation due to
// mismatched parameter counts.
bind(&done);
} }
// Continue here if InvokePrologue does handle the invocation due to
// mismatched parameter counts.
bind(&done);
} }
@ -3537,18 +3582,22 @@ void MacroAssembler::InvokeCode(Handle<Code> code,
Label done; Label done;
InvokePrologue(expected, actual, code, no_reg, &done, flag, bool definitely_mismatches = false;
InvokePrologue(expected, actual, code, no_reg,
&done, &definitely_mismatches, flag,
NullCallWrapper(), call_kind); NullCallWrapper(), call_kind);
if (flag == CALL_FUNCTION) { if (!definitely_mismatches) {
SetCallKind(t1, call_kind); if (flag == CALL_FUNCTION) {
Call(code, rmode); SetCallKind(t1, call_kind);
} else { Call(code, rmode);
SetCallKind(t1, call_kind); } else {
Jump(code, rmode); SetCallKind(t1, call_kind);
Jump(code, rmode);
}
// Continue here if InvokePrologue does handle the invocation due to
// mismatched parameter counts.
bind(&done);
} }
// Continue here if InvokePrologue does handle the invocation due to
// mismatched parameter counts.
bind(&done);
} }
@ -3581,6 +3630,7 @@ void MacroAssembler::InvokeFunction(Register function,
void MacroAssembler::InvokeFunction(Handle<JSFunction> function, void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
const ParameterCount& actual, const ParameterCount& actual,
InvokeFlag flag, InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind) { CallKind call_kind) {
// You can't call a function without a valid frame. // You can't call a function without a valid frame.
ASSERT(flag == JUMP_FUNCTION || has_frame()); ASSERT(flag == JUMP_FUNCTION || has_frame());
@ -3594,7 +3644,7 @@ void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
// allow recompilation to take effect without changing any of the // allow recompilation to take effect without changing any of the
// call sites. // call sites.
lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
InvokeCode(a3, expected, actual, flag, NullCallWrapper(), call_kind); InvokeCode(a3, expected, actual, flag, call_wrapper, call_kind);
} }
@ -4731,6 +4781,34 @@ void MacroAssembler::PatchRelocatedValue(Register li_location,
FlushICache(li_location, 2); FlushICache(li_location, 2);
} }
void MacroAssembler::GetRelocatedValue(Register li_location,
Register value,
Register scratch) {
lw(value, MemOperand(li_location));
if (emit_debug_code()) {
And(value, value, kOpcodeMask);
Check(eq, "The instruction should be a lui.",
value, Operand(LUI));
lw(value, MemOperand(li_location));
}
// value now holds a lui instruction. Extract the immediate.
sll(value, value, kImm16Bits);
lw(scratch, MemOperand(li_location, kInstrSize));
if (emit_debug_code()) {
And(scratch, scratch, kOpcodeMask);
Check(eq, "The instruction should be an ori.",
scratch, Operand(ORI));
lw(scratch, MemOperand(li_location, kInstrSize));
}
// "scratch" now holds an ori instruction. Extract the immediate.
andi(scratch, scratch, kImm16Mask);
// Merge the results.
or_(value, value, scratch);
}
void MacroAssembler::CheckPageFlag( void MacroAssembler::CheckPageFlag(
Register object, Register object,

48
deps/v8/src/mips/macro-assembler-mips.h

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -51,16 +51,6 @@ class JumpTarget;
// MIPS generated code calls C code, it must be via t9 register. // MIPS generated code calls C code, it must be via t9 register.
// Register aliases.
// cp is assumed to be a callee saved register.
const Register kLithiumScratchReg = s3; // Scratch register.
const Register kLithiumScratchReg2 = s4; // Scratch register.
const Register kCondReg = s5; // Simulated (partial) condition code for mips.
const Register kRootRegister = s6; // Roots array pointer.
const Register cp = s7; // JavaScript context pointer.
const Register fp = s8_fp; // Alias for fp.
const DoubleRegister kLithiumScratchDouble = f30; // Double scratch register.
// Flags used for the AllocateInNewSpace functions. // Flags used for the AllocateInNewSpace functions.
enum AllocationFlags { enum AllocationFlags {
// No special flags. // No special flags.
@ -340,7 +330,7 @@ class MacroAssembler: public Assembler {
Register scratch3, Register scratch3,
Label* object_is_white_and_not_data); Label* object_is_white_and_not_data);
// Detects conservatively whether an object is data-only, ie it does need to // Detects conservatively whether an object is data-only, i.e. it does need to
// be scanned by the garbage collector. // be scanned by the garbage collector.
void JumpIfDataObject(Register value, void JumpIfDataObject(Register value,
Register scratch, Register scratch,
@ -421,7 +411,7 @@ class MacroAssembler: public Assembler {
} }
// Check if the given instruction is a 'type' marker. // Check if the given instruction is a 'type' marker.
// ie. check if it is a sll zero_reg, zero_reg, <type> (referenced as // i.e. check if it is a sll zero_reg, zero_reg, <type> (referenced as
// nop(type)). These instructions are generated to mark special location in // nop(type)). These instructions are generated to mark special location in
// the code, like some special IC code. // the code, like some special IC code.
static inline bool IsMarkedCode(Instr instr, int type) { static inline bool IsMarkedCode(Instr instr, int type) {
@ -830,6 +820,7 @@ class MacroAssembler: public Assembler {
void InvokeFunction(Handle<JSFunction> function, void InvokeFunction(Handle<JSFunction> function,
const ParameterCount& actual, const ParameterCount& actual,
InvokeFlag flag, InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind); CallKind call_kind);
@ -940,15 +931,29 @@ class MacroAssembler: public Assembler {
Register scratch4, Register scratch4,
Label* fail); Label* fail);
// Check if the map of an object is equal to a specified map (either // Compare an object's map with the specified map and its transitioned
// given directly or as an index into the root list) and branch to // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Jumps to
// label if not. Skip the smi check if not required (object is known // "branch_to" if the result of the comparison is "cond". If multiple map
// to be a heap object). // compares are required, the compare sequences branches to early_success.
void CompareMapAndBranch(Register obj,
Register scratch,
Handle<Map> map,
Label* early_success,
Condition cond,
Label* branch_to,
CompareMapMode mode = REQUIRE_EXACT_MAP);
// Check if the map of an object is equal to a specified map and branch to
// label if not. Skip the smi check if not required (object is known to be a
// heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
// against maps that are ElementsKind transition maps of the specificed map.
void CheckMap(Register obj, void CheckMap(Register obj,
Register scratch, Register scratch,
Handle<Map> map, Handle<Map> map,
Label* fail, Label* fail,
SmiCheckType smi_check_type); SmiCheckType smi_check_type,
CompareMapMode mode = REQUIRE_EXACT_MAP);
void CheckMap(Register obj, void CheckMap(Register obj,
Register scratch, Register scratch,
@ -1132,7 +1137,7 @@ class MacroAssembler: public Assembler {
// Calls an API function. Allocates HandleScope, extracts returned value // Calls an API function. Allocates HandleScope, extracts returned value
// from handle and propagates exceptions. Restores context. stack_space // from handle and propagates exceptions. Restores context. stack_space
// - space to be unwound on exit (includes the call js arguments space and // - space to be unwound on exit (includes the call JS arguments space and
// the additional space allocated for the fast call). // the additional space allocated for the fast call).
void CallApiFunctionAndReturn(ExternalReference function, int stack_space); void CallApiFunctionAndReturn(ExternalReference function, int stack_space);
@ -1337,6 +1342,10 @@ class MacroAssembler: public Assembler {
void PatchRelocatedValue(Register li_location, void PatchRelocatedValue(Register li_location,
Register scratch, Register scratch,
Register new_value); Register new_value);
// Get the relocatad value (loaded data) from the lui/ori pair.
void GetRelocatedValue(Register li_location,
Register value,
Register scratch);
private: private:
void CallCFunctionHelper(Register function, void CallCFunctionHelper(Register function,
@ -1369,6 +1378,7 @@ class MacroAssembler: public Assembler {
Handle<Code> code_constant, Handle<Code> code_constant,
Register code_reg, Register code_reg,
Label* done, Label* done,
bool* definitely_mismatches,
InvokeFlag flag, InvokeFlag flag,
const CallWrapper& call_wrapper, const CallWrapper& call_wrapper,
CallKind call_kind); CallKind call_kind);

4
deps/v8/src/mips/simulator-mips.cc

@ -2291,7 +2291,7 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
} }
// Type 2: instructions using a 16 bytes immediate. (eg: addi, beq). // Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq).
void Simulator::DecodeTypeImmediate(Instruction* instr) { void Simulator::DecodeTypeImmediate(Instruction* instr) {
// Instruction fields. // Instruction fields.
Opcode op = instr->OpcodeFieldRaw(); Opcode op = instr->OpcodeFieldRaw();
@ -2614,7 +2614,7 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
} }
// Type 3: instructions using a 26 bytes immediate. (eg: j, jal). // Type 3: instructions using a 26 bytes immediate. (e.g. j, jal).
void Simulator::DecodeTypeJump(Instruction* instr) { void Simulator::DecodeTypeJump(Instruction* instr) {
// Get current pc. // Get current pc.
int32_t current_pc = get_pc(); int32_t current_pc = get_pc();

59
deps/v8/src/mips/stub-cache-mips.cc

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -377,13 +377,9 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
Label* miss_label) { Label* miss_label) {
// a0 : value. // a0 : value.
Label exit; Label exit;
// Check that the map of the object hasn't changed.
// Check that the receiver isn't a smi. __ CheckMap(receiver_reg, scratch, Handle<Map>(object->map()), miss_label,
__ JumpIfSmi(receiver_reg, miss_label, scratch); DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Check that the map of the receiver hasn't changed.
__ lw(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
__ Branch(miss_label, ne, scratch, Operand(Handle<Map>(object->map())));
// Perform global security token check if needed. // Perform global security token check if needed.
if (object->IsJSGlobalProxy()) { if (object->IsJSGlobalProxy()) {
@ -565,11 +561,11 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm,
int argc) { int argc) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- sp[0] : holder (set by CheckPrototypes) // -- sp[0] : holder (set by CheckPrototypes)
// -- sp[4] : callee js function // -- sp[4] : callee JS function
// -- sp[8] : call data // -- sp[8] : call data
// -- sp[12] : last js argument // -- sp[12] : last JS argument
// -- ... // -- ...
// -- sp[(argc + 3) * 4] : first js argument // -- sp[(argc + 3) * 4] : first JS argument
// -- sp[(argc + 4) * 4] : receiver // -- sp[(argc + 4) * 4] : receiver
// ----------------------------------- // -----------------------------------
// Get the function and setup the context. // Get the function and setup the context.
@ -587,7 +583,7 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm,
__ li(t2, call_data); __ li(t2, call_data);
} }
// Store js function and call data. // Store JS function and call data.
__ sw(t1, MemOperand(sp, 1 * kPointerSize)); __ sw(t1, MemOperand(sp, 1 * kPointerSize));
__ sw(t2, MemOperand(sp, 2 * kPointerSize)); __ sw(t2, MemOperand(sp, 2 * kPointerSize));
@ -747,7 +743,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
? CALL_AS_FUNCTION ? CALL_AS_FUNCTION
: CALL_AS_METHOD; : CALL_AS_METHOD;
__ InvokeFunction(optimization.constant_function(), arguments_, __ InvokeFunction(optimization.constant_function(), arguments_,
JUMP_FUNCTION, call_kind); JUMP_FUNCTION, NullCallWrapper(), call_kind);
} }
// Deferred code for fast API call case---clean preallocated space. // Deferred code for fast API call case---clean preallocated space.
@ -1037,9 +1033,8 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
__ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
} else { } else {
Handle<Map> current_map(current->map()); Handle<Map> current_map(current->map());
__ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK,
// Branch on the result of the map check. ALLOW_ELEMENT_TRANSITION_MAPS);
__ Branch(miss, ne, scratch1, Operand(current_map));
// Check access rights to the global object. This has to happen after // Check access rights to the global object. This has to happen after
// the map check so that we know that the object is actually a global // the map check so that we know that the object is actually a global
// object. // object.
@ -1070,8 +1065,8 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1)); LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1));
// Check the holder map. // Check the holder map.
__ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); __ CheckMap(reg, scratch1, Handle<Map>(current->map()), miss,
__ Branch(miss, ne, scratch1, Operand(Handle<Map>(current->map()))); DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform security check for access to the global object. // Perform security check for access to the global object.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
@ -1209,7 +1204,7 @@ void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object,
// and CALLBACKS, so inline only them, other cases may be added // and CALLBACKS, so inline only them, other cases may be added
// later. // later.
bool compile_followup_inline = false; bool compile_followup_inline = false;
if (lookup->IsProperty() && lookup->IsCacheable()) { if (lookup->IsFound() && lookup->IsCacheable()) {
if (lookup->type() == FIELD) { if (lookup->type() == FIELD) {
compile_followup_inline = true; compile_followup_inline = true;
} else if (lookup->type() == CALLBACKS && } else if (lookup->type() == CALLBACKS &&
@ -1934,7 +1929,8 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
// Tail call the full function. We do not have to patch the receiver // Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it. // because the function makes no use of it.
__ bind(&slow); __ bind(&slow);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); __ InvokeFunction(
function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss); __ bind(&miss);
// a2: function name. // a2: function name.
@ -2067,7 +2063,8 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
__ bind(&slow); __ bind(&slow);
// Tail call the full function. We do not have to patch the receiver // Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it. // because the function makes no use of it.
__ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); __ InvokeFunction(
function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss); __ bind(&miss);
// a2: function name. // a2: function name.
@ -2167,7 +2164,8 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
// Tail call the full function. We do not have to patch the receiver // Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it. // because the function makes no use of it.
__ bind(&slow); __ bind(&slow);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); __ InvokeFunction(
function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss); __ bind(&miss);
// a2: function name. // a2: function name.
@ -2346,7 +2344,8 @@ Handle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object,
CallKind call_kind = CallICBase::Contextual::decode(extra_state_) CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
? CALL_AS_FUNCTION ? CALL_AS_FUNCTION
: CALL_AS_METHOD; : CALL_AS_METHOD;
__ InvokeFunction(function, arguments(), JUMP_FUNCTION, call_kind); __ InvokeFunction(
function, arguments(), JUMP_FUNCTION, NullCallWrapper(), call_kind);
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);
@ -2493,12 +2492,9 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
// Check that the object isn't a smi.
__ JumpIfSmi(a1, &miss);
// Check that the map of the object hasn't changed. // Check that the map of the object hasn't changed.
__ lw(a3, FieldMemOperand(a1, HeapObject::kMapOffset)); __ CheckMap(a1, a3, Handle<Map>(object->map()), &miss,
__ Branch(&miss, ne, a3, Operand(Handle<Map>(object->map()))); DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform global security token check if needed. // Perform global security token check if needed.
if (object->IsJSGlobalProxy()) { if (object->IsJSGlobalProxy()) {
@ -2540,12 +2536,9 @@ Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
// Check that the object isn't a smi.
__ JumpIfSmi(a1, &miss);
// Check that the map of the object hasn't changed. // Check that the map of the object hasn't changed.
__ lw(a3, FieldMemOperand(a1, HeapObject::kMapOffset)); __ CheckMap(a1, a3, Handle<Map>(receiver->map()), &miss,
__ Branch(&miss, ne, a3, Operand(Handle<Map>(receiver->map()))); DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform global security token check if needed. // Perform global security token check if needed.
if (receiver->IsJSGlobalProxy()) { if (receiver->IsJSGlobalProxy()) {

2
deps/v8/src/objects-debug.cc

@ -388,7 +388,7 @@ void ConsString::ConsStringVerify() {
CHECK(this->first()->IsString()); CHECK(this->first()->IsString());
CHECK(this->second() == GetHeap()->empty_string() || CHECK(this->second() == GetHeap()->empty_string() ||
this->second()->IsString()); this->second()->IsString());
CHECK(this->length() >= String::kMinNonFlatLength); CHECK(this->length() >= ConsString::kMinLength);
if (this->IsFlat()) { if (this->IsFlat()) {
// A flat cons can only be created by String::SlowTryFlatten. // A flat cons can only be created by String::SlowTryFlatten.
// Afterwards, the first part may be externalized. // Afterwards, the first part may be externalized.

4
deps/v8/src/objects-inl.h

@ -1391,11 +1391,11 @@ int JSObject::GetHeaderSize() {
case JS_VALUE_TYPE: case JS_VALUE_TYPE:
return JSValue::kSize; return JSValue::kSize;
case JS_ARRAY_TYPE: case JS_ARRAY_TYPE:
return JSValue::kSize; return JSArray::kSize;
case JS_WEAK_MAP_TYPE: case JS_WEAK_MAP_TYPE:
return JSWeakMap::kSize; return JSWeakMap::kSize;
case JS_REGEXP_TYPE: case JS_REGEXP_TYPE:
return JSValue::kSize; return JSRegExp::kSize;
case JS_CONTEXT_EXTENSION_OBJECT_TYPE: case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
return JSObject::kHeaderSize; return JSObject::kHeaderSize;
case JS_MESSAGE_OBJECT_TYPE: case JS_MESSAGE_OBJECT_TYPE:

2
deps/v8/src/objects-printer.cc

@ -627,7 +627,7 @@ void String::StringPrint(FILE* out) {
// This method is only meant to be called from gdb for debugging purposes. // This method is only meant to be called from gdb for debugging purposes.
// Since the string can also be in two-byte encoding, non-ascii characters // Since the string can also be in two-byte encoding, non-ASCII characters
// will be ignored in the output. // will be ignored in the output.
char* String::ToAsciiArray() { char* String::ToAsciiArray() {
// Static so that subsequent calls frees previously allocated space. // Static so that subsequent calls frees previously allocated space.

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

Loading…
Cancel
Save