Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBert Belder <bertbelder@gmail.com>2011-01-03 00:57:32 +0300
committerBert Belder <bertbelder@gmail.com>2011-01-03 00:57:32 +0300
commit33118df8f98f7c81c36653563b2b58e44bcc4c6f (patch)
tree4e3e8c6165a40ed2abe726aaea3b0531ac873bf9
parent86518c3b1101a20fafb8d213d0d68988cb4407fe (diff)
parentb5637170b17d4ad7d47362a394e360c44af60e46 (diff)
Merge remote branch 'origin/master'
Conflicts: src/node_net.cc src/node_os.cc
-rw-r--r--Makefile6
-rw-r--r--Makefile.cmake5
-rw-r--r--README.cmake12
-rw-r--r--cmake/codesourcery-arm-toolchain.cmake22
-rw-r--r--cmake/configure.cmake10
-rw-r--r--cmake/libs.cmake7
-rw-r--r--cmake/node_build.cmake20
-rw-r--r--cmake/v8_build.cmake5
-rw-r--r--deps/v8/ChangeLog11
-rw-r--r--deps/v8/SConstruct13
-rw-r--r--deps/v8/include/v8.h15
-rwxr-xr-xdeps/v8/src/SConscript3
-rw-r--r--deps/v8/src/api.cc29
-rw-r--r--deps/v8/src/arm/code-stubs-arm.cc103
-rw-r--r--deps/v8/src/arm/lithium-arm.cc9
-rw-r--r--deps/v8/src/arm/lithium-codegen-arm.cc15
-rw-r--r--deps/v8/src/arm/macro-assembler-arm.cc38
-rw-r--r--deps/v8/src/arm/macro-assembler-arm.h13
-rw-r--r--deps/v8/src/array.js69
-rw-r--r--deps/v8/src/assembler.cc23
-rw-r--r--deps/v8/src/assembler.h2
-rw-r--r--deps/v8/src/builtins.cc61
-rw-r--r--deps/v8/src/code-stubs.h3
-rw-r--r--deps/v8/src/codegen.cc13
-rw-r--r--deps/v8/src/counters.h3
-rw-r--r--deps/v8/src/date.js33
-rw-r--r--deps/v8/src/debug.cc2
-rw-r--r--deps/v8/src/deoptimizer.cc2
-rw-r--r--deps/v8/src/deoptimizer.h2
-rw-r--r--deps/v8/src/flag-definitions.h5
-rw-r--r--deps/v8/src/full-codegen.cc9
-rw-r--r--deps/v8/src/heap-profiler.cc4
-rw-r--r--deps/v8/src/heap.cc97
-rw-r--r--deps/v8/src/heap.h16
-rw-r--r--deps/v8/src/hydrogen-instructions.cc7
-rw-r--r--deps/v8/src/hydrogen-instructions.h6
-rw-r--r--deps/v8/src/hydrogen.cc20
-rw-r--r--deps/v8/src/hydrogen.h10
-rw-r--r--deps/v8/src/ia32/code-stubs-ia32.cc304
-rw-r--r--deps/v8/src/ia32/code-stubs-ia32.h31
-rw-r--r--deps/v8/src/ia32/codegen-ia32.cc9
-rw-r--r--deps/v8/src/ia32/full-codegen-ia32.cc9
-rw-r--r--deps/v8/src/ia32/lithium-codegen-ia32.cc28
-rw-r--r--deps/v8/src/ia32/lithium-codegen-ia32.h2
-rw-r--r--deps/v8/src/ia32/lithium-ia32.cc2
-rw-r--r--deps/v8/src/objects-debug.cc822
-rw-r--r--deps/v8/src/objects.cc131
-rw-r--r--deps/v8/src/objects.h343
-rw-r--r--deps/v8/src/parser.cc6
-rw-r--r--deps/v8/src/platform-nullos.cc13
-rw-r--r--deps/v8/src/platform-posix.cc29
-rw-r--r--deps/v8/src/platform-win32.cc16
-rw-r--r--deps/v8/src/platform.h4
-rw-r--r--deps/v8/src/profile-generator.cc8
-rw-r--r--deps/v8/src/property.cc62
-rw-r--r--deps/v8/src/property.h8
-rw-r--r--deps/v8/src/regexp.js27
-rw-r--r--deps/v8/src/runtime.cc2
-rw-r--r--deps/v8/src/spaces.cc53
-rw-r--r--deps/v8/src/spaces.h15
-rw-r--r--deps/v8/src/string-stream.cc6
-rw-r--r--deps/v8/src/string-stream.h3
-rw-r--r--deps/v8/src/string.js67
-rw-r--r--deps/v8/src/utils.cc12
-rw-r--r--deps/v8/src/v8-counters.h2
-rw-r--r--deps/v8/src/v8utils.h10
-rw-r--r--deps/v8/src/version.cc4
-rw-r--r--deps/v8/src/x64/codegen-x64.cc4
-rw-r--r--deps/v8/test/cctest/test-heap.cc64
-rw-r--r--deps/v8/test/mjsunit/array-slice.js13
-rw-r--r--deps/v8/test/mjsunit/array-sort.js17
-rw-r--r--deps/v8/test/mjsunit/with-readonly.js43
-rw-r--r--deps/v8/tools/gyp/v8.gyp3
-rw-r--r--deps/v8/tools/v8.xcodeproj/project.pbxproj3
-rw-r--r--deps/v8/tools/visual_studio/debug.vsprops2
-rw-r--r--doc/api/addons.markdown4
-rw-r--r--doc/api/appendix_1.markdown2
-rw-r--r--doc/api/assert.markdown4
-rw-r--r--doc/api/os.markdown97
-rw-r--r--doc/api/process.markdown17
-rw-r--r--doc/api/repl.markdown4
-rw-r--r--doc/api/streams.markdown57
-rw-r--r--doc/index.html8
-rw-r--r--lib/assert.js11
-rw-r--r--lib/console.js16
-rw-r--r--lib/events.js2
-rw-r--r--lib/os.js9
-rw-r--r--lib/readline.js34
-rw-r--r--lib/repl.js83
-rw-r--r--lib/stream.js43
-rw-r--r--src/node.cc33
-rw-r--r--src/node.js31
-rw-r--r--src/node_crypto.cc6
-rw-r--r--src/node_net.cc111
-rw-r--r--src/node_os.cc96
-rw-r--r--src/node_script.cc283
-rw-r--r--src/node_script.h48
-rw-r--r--src/platform.h9
-rw-r--r--src/platform_cygwin.cc124
-rw-r--r--src/platform_darwin.cc131
-rw-r--r--src/platform_darwin_proctitle.cc2
-rw-r--r--src/platform_freebsd.cc139
-rw-r--r--src/platform_linux.cc128
-rw-r--r--src/platform_openbsd.cc201
-rw-r--r--src/platform_sunos.cc41
-rw-r--r--test/simple/test-assert.js18
-rw-r--r--test/simple/test-buffer.js4
-rw-r--r--test/simple/test-os-hostname.js5
-rw-r--r--test/simple/test-os.js12
-rw-r--r--test/simple/test-repl.js4
-rw-r--r--test/simple/test-tls-client-verify.js6
-rw-r--r--test/simple/test-tls-junk-closes-server.js5
-rw-r--r--test/simple/test-tls-securepair-client.js10
-rw-r--r--test/simple/test-tls-securepair-server.js6
-rw-r--r--test/simple/test-tls-server-verify.js5
-rw-r--r--wscript7
116 files changed, 3374 insertions, 1382 deletions
diff --git a/Makefile b/Makefile
index 14276b6bf84..05b19886460 100644
--- a/Makefile
+++ b/Makefile
@@ -25,9 +25,15 @@ uninstall:
test: all
python tools/test.py --mode=release simple message
+test-valgrind: all
+ python tools/test.py --mode=release --valgrind simple message
+
test-all: all
python tools/test.py --mode=debug,release
+test-all-valgrind: all
+ python tools/test.py --mode=debug,release --valgrind
+
test-release: all
python tools/test.py --mode=release
diff --git a/Makefile.cmake b/Makefile.cmake
index aaa3f6f258c..0281b413e7c 100644
--- a/Makefile.cmake
+++ b/Makefile.cmake
@@ -2,12 +2,13 @@ BUILD?=build
VERBOSE?=0
PARALLEL_JOBS?=1
CMAKE?=cmake
+TOOLCHAIN_FILE=#./cmake/codesourcery-arm-toolchain.cmake
-all: doc package
+all: package
$(BUILD)/Makefile:
mkdir $(BUILD) || exit 0
- cd $(BUILD) && $(CMAKE) -DCMAKE_VERBOSE_MAKEFILE=$(VERBOSE) ..
+ cd $(BUILD) && $(CMAKE) -DCMAKE_VERBOSE_MAKEFILE=$(VERBOSE) -DCMAKE_TOOLCHAIN_FILE=$(TOOLCHAIN_FILE) ..
build: $(BUILD)/Makefile
cd $(BUILD) && make -j $(PARALLEL_JOBS)
diff --git a/README.cmake b/README.cmake
index 88cd99c8692..925249c8ae5 100644
--- a/README.cmake
+++ b/README.cmake
@@ -38,6 +38,18 @@ To submit valgrind test results:
make -f Makefile.cmake cdash-mem
+Cross-compiling:
+ An example toolchain file for the CodeSourcery ARM toolchain is included in
+ the cmake directory: codesourcery-arm-toolchain.cmake.
+
+ Install the CodeSourcery toolchain, set the path to the toolchain in
+ cmake/codesourcery-arm-toolchain.cmake, and uncomment the TOOLCHAIN_FILE
+ variable in Makefile.cmake to use it.
+
+ If you are using cmake directly, just add the flag
+ "-DCMAKE_TOOLCHAIN_FILE=/path/to/toolchain-file" when
+ running cmake.
+
Using cmake directly:
cd ~/your-node-source-dir
mkdir name-of-build-dir (can be anything)
diff --git a/cmake/codesourcery-arm-toolchain.cmake b/cmake/codesourcery-arm-toolchain.cmake
new file mode 100644
index 00000000000..c45bce50675
--- /dev/null
+++ b/cmake/codesourcery-arm-toolchain.cmake
@@ -0,0 +1,22 @@
+set(toolchain_dir #SET THIS TO YOUR TOOLCHAIN PATH)
+set(toolchain_bin_dir ${toolchain_dir}/bin)
+set(toolchain_libc_dir ${toolchain_dir}/arm-none-linux-gnueabi/libc)
+set(toolchain_inc_dir ${toolchain_libc_dir}/include)
+set(toolchain_lib_dir ${toolchain_libc_dir}/usr/lib)
+
+set(CMAKE_SYSTEM_NAME Linux CACHE INTERNAL "system name")
+set(CMAKE_SYSTEM_PROCESSOR arm CACHE INTERNAL "processor")
+set(CMAKE_C_COMPILER ${toolchain_bin_dir}/arm-none-linux-gnueabi-gcc)
+set(CMAKE_CXX_COMPILER ${toolchain_bin_dir}/arm-none-linux-gnueabi-g++)
+set(CMAKE_C_FLAGS "-isystem ${toolchain_inc_dir}" CACHE INTERNAL "c compiler flags")
+set(CMAKE_CXX_FLAGS "-isystem ${toolchain_inc_dir}" CACHE INTERNAL "cxx compiler flags")
+
+set(link_flags -L${toolchain_lib_dir})
+
+set(CMAKE_EXE_LINKER_FLAGS ${link_flags} CACHE INTERNAL "exe link flags")
+set(CMAKE_MODULE_LINKER_FLAGS ${link_flags} CACHE INTERNAL "module link flags")
+set(CMAKE_SHARED_LINKER_FLAGS ${link_flags} CACHE INTERNAL "shared lnk flags")
+set(CMAKE_FIND_ROOT_PATH ${toolchain_libc_dir} CACHE INTERNAL "cross root directory")
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH CACHE INTERNAL "")
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY CACHE INTERNAL "")
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY CACHE INTERNAL "")
diff --git a/cmake/configure.cmake b/cmake/configure.cmake
index eef89c5fdcf..79b6369d590 100644
--- a/cmake/configure.cmake
+++ b/cmake/configure.cmake
@@ -80,13 +80,3 @@ file(GLOB js2c_files ${PROJECT_SOURCE_DIR}/lib/*.js)
set(js2c_files ${PROJECT_SOURCE_DIR}/src/node.js ${js2c_files})
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/src)
-set(PREFIX ${CMAKE_INSTALL_PREFIX})
-if(${CMAKE_BUILD_TYPE} MATCHES Debug)
- set(CCFLAGS "${CMAKE_C_FLAGS_DEBUG} ${CMAKE_C_FLAGS}")
-else()
- set(CCFLAGS "${CMAKE_C_FLAGS_RELEASE} ${CMAKE_C_FLAGS}")
-endif()
-get_directory_property(compile_defs COMPILE_DEFINITIONS)
-foreach(def ${compile_defs})
- set(CPPFLAGS "${CPPFLAGS} -D${def}")
-endforeach()
diff --git a/cmake/libs.cmake b/cmake/libs.cmake
index 2844d86ac0d..aeeb01d8115 100644
--- a/cmake/libs.cmake
+++ b/cmake/libs.cmake
@@ -13,6 +13,7 @@ find_library(RT rt)
find_library(DL dl)
check_library_exists(socket socket "" HAVE_SOCKET_LIB)
check_library_exists(nsl gethostbyname "" HAVE_NSL_LIB)
+check_library_exists(util openpty "" HAVE_UTIL_LIB)
if(RT)
set(extra_libs ${extra_libs} ${RT})
@@ -35,7 +36,11 @@ if(${HAVE_NSL_LIB})
set(extra_libs ${extra_libs} nsl)
endif()
-if(${OPENSSL_FOUND} MATCHES True)
+if(HAVE_UTIL_LIB)
+ set(extra_libs ${extra_libs} util)
+endif()
+
+if(OPENSSL_FOUND)
add_definitions(-DHAVE_OPENSSL=1)
set(HAVE_OPENSSL True)
set(node_extra_src ${node_extra_src} src/node_crypto.cc)
diff --git a/cmake/node_build.cmake b/cmake/node_build.cmake
index ec9010dd3f9..240bdc6f9cc 100644
--- a/cmake/node_build.cmake
+++ b/cmake/node_build.cmake
@@ -7,10 +7,12 @@ add_custom_command(
COMMAND ${PYTHON_EXECUTABLE} tools/js2c.py ${PROJECT_BINARY_DIR}/src/node_natives.h ${js2c_files}
DEPENDS ${js2c_files})
-set(node_extra_src "src/platform_${node_platform}.cc")
+set(node_platform_src "src/platform_${node_platform}.cc")
-if(NOT EXISTS ${CMAKE_SOURCE_DIR}/${node_extra_src})
- set(node_extra_src "src/platform_none.cc")
+if(NOT EXISTS ${CMAKE_SOURCE_DIR}/${node_platform_src})
+ set(node_extra_src ${node_extra_src} "src/platform_none.cc")
+else()
+ set(node_extra_src ${node_extra_src} ${node_platform_src})
endif()
set(node_sources
@@ -36,6 +38,18 @@ set(node_sources
src/node_natives.h
${node_extra_src})
+# Set up PREFIX, CCFLAGS, and CPPFLAGS for node_config.h
+set(PREFIX ${CMAKE_INSTALL_PREFIX})
+if(${CMAKE_BUILD_TYPE} MATCHES Debug)
+ set(CCFLAGS "${CMAKE_C_FLAGS_DEBUG} ${CMAKE_C_FLAGS}")
+else()
+ set(CCFLAGS "${CMAKE_C_FLAGS_RELEASE} ${CMAKE_C_FLAGS}")
+endif()
+get_directory_property(compile_defs COMPILE_DEFINITIONS)
+foreach(def ${compile_defs})
+ set(CPPFLAGS "${CPPFLAGS} -D${def}")
+endforeach()
+
configure_file(src/node_config.h.in ${PROJECT_BINARY_DIR}/src/node_config.h)
configure_file(config.h.cmake ${PROJECT_BINARY_DIR}/config.h)
diff --git a/cmake/v8_build.cmake b/cmake/v8_build.cmake
index ea27e5fd083..b35caef2e66 100644
--- a/cmake/v8_build.cmake
+++ b/cmake/v8_build.cmake
@@ -38,6 +38,7 @@ if(NOT SHARED_V8)
set_property(TARGET v8
PROPERTY IMPORTED_LOCATION ${PROJECT_BINARY_DIR}/deps/v8/${v8_fn})
+ set(compile_env_vars "CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} CFLAGS=\"${CMAKE_C_FLAGS}\" CXXFLAGS=\"${CMAKE_CXX_FLAGS}\" LDFLAGS=\"${CMAKE_EXE_LINKER_FLAGS}\"")
if(CMAKE_VERSION VERSION_GREATER 2.8 OR CMAKE_VERSION VERSION_EQUAL 2.8)
# use ExternalProject for CMake >2.8
@@ -47,7 +48,7 @@ if(NOT SHARED_V8)
URL ${PROJECT_SOURCE_DIR}/deps/v8
BUILD_IN_SOURCE True
- BUILD_COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_BINARY_DIR}/tools/scons/scons.py library=static visibility=default ${v8snapshot} mode=${v8mode} verbose=on arch=${v8arch} -j ${parallel_jobs}
+ BUILD_COMMAND sh -c "${compile_env_vars} ${PYTHON_EXECUTABLE} ${PROJECT_BINARY_DIR}/tools/scons/scons.py library=static visibility=default ${v8snapshot} mode=${v8mode} verbose=on arch=${v8arch} -j ${parallel_jobs}"
SOURCE_DIR ${PROJECT_BINARY_DIR}/deps/v8
# ignore this stuff, it's not needed for building v8 but ExternalProject
@@ -78,7 +79,7 @@ if(NOT SHARED_V8)
add_custom_command(
OUTPUT ${PROJECT_BINARY_DIR}/deps/v8/${v8_fn}
- COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_BINARY_DIR}/tools/scons/scons.py library=static visibility=default ${v8snapshot} mode=${v8mode} verbose=on arch=${v8arch} -j ${parallel_jobs}
+ COMMAND sh -c "${compile_env_vars} ${PYTHON_EXECUTABLE} ${PROJECT_BINARY_DIR}/tools/scons/scons.py library=static visibility=default ${v8snapshot} mode=${v8mode} verbose=on arch=${v8arch} -j ${parallel_jobs}"
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/deps/v8/
DEPENDS ${v8_sources_dest}
)
diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog
index f1b47b06c39..c81d7a7376e 100644
--- a/deps/v8/ChangeLog
+++ b/deps/v8/ChangeLog
@@ -1,3 +1,14 @@
+2010-12-21: Version 3.0.4
+
+ Added Date::ResetCache() to the API so that the cached values in the
+ Date object can be reset to allow live DST / timezone changes.
+
+ Extended existing support for printing (while debugging) the contents
+ of objects. Added support for printing objects from release builds.
+
+ Fixed V8 issues 989, 1006, and 1007.
+
+
2010-12-17: Version 3.0.3
Reapplied all changes for version 3.0.1.
diff --git a/deps/v8/SConstruct b/deps/v8/SConstruct
index 41c9faeb63a..5908be1525c 100644
--- a/deps/v8/SConstruct
+++ b/deps/v8/SConstruct
@@ -108,11 +108,14 @@ LIBRARY_FLAGS = {
'CPPDEFINES': ['V8_INTERPRETED_REGEXP']
},
'mode:debug': {
- 'CPPDEFINES': ['V8_ENABLE_CHECKS']
+ 'CPPDEFINES': ['V8_ENABLE_CHECKS', 'OBJECT_PRINT']
},
'vmstate:on': {
'CPPDEFINES': ['ENABLE_VMSTATE_TRACKING'],
},
+ 'objectprint:on': {
+ 'CPPDEFINES': ['OBJECT_PRINT'],
+ },
'protectheap:on': {
'CPPDEFINES': ['ENABLE_VMSTATE_TRACKING', 'ENABLE_HEAP_PROTECTION'],
},
@@ -225,8 +228,7 @@ LIBRARY_FLAGS = {
'LINKFLAGS': ['-m64'],
},
'prof:oprofile': {
- 'CPPDEFINES': ['ENABLE_OPROFILE_AGENT'],
- 'LIBS': ['opagent', 'bfd']
+ 'CPPDEFINES': ['ENABLE_OPROFILE_AGENT']
}
},
'msvc': {
@@ -711,6 +713,11 @@ SIMPLE_OPTIONS = {
'default': 'off',
'help': 'enable VM state tracking'
},
+ 'objectprint': {
+ 'values': ['on', 'off'],
+ 'default': 'off',
+ 'help': 'enable object printing'
+ },
'protectheap': {
'values': ['on', 'off'],
'default': 'off',
diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h
index 82de6b8b5e8..2c0f35080d3 100644
--- a/deps/v8/include/v8.h
+++ b/deps/v8/include/v8.h
@@ -1355,6 +1355,21 @@ class Date : public Value {
V8EXPORT double NumberValue() const;
static inline Date* Cast(v8::Value* obj);
+
+ /**
+ * Notification that the embedder has changed the time zone,
+ * daylight savings time, or other date / time configuration
+ * parameters. V8 keeps a cache of various values used for
+ * date / time computation. This notification will reset
+ * those cached values for the current context so that date /
+ * time configuration changes would be reflected in the Date
+ * object.
+ *
+ * This API should not be called more than needed as it will
+ * negatively impact the performance of date operations.
+ */
+ V8EXPORT static void DateTimeConfigurationChangeNotification();
+
private:
V8EXPORT static void CheckCast(v8::Value* obj);
};
diff --git a/deps/v8/src/SConscript b/deps/v8/src/SConscript
index 5d7907251f6..8ccc6f2d8bb 100755
--- a/deps/v8/src/SConscript
+++ b/deps/v8/src/SConscript
@@ -231,7 +231,8 @@ SOURCES = {
'mode:release': [],
'mode:debug': [
'objects-debug.cc', 'prettyprinter.cc', 'regexp-macro-assembler-tracer.cc'
- ]
+ ],
+ 'objectprint:on': ['objects-debug.cc']
}
diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc
index b85d658dc38..110468e2313 100644
--- a/deps/v8/src/api.cc
+++ b/deps/v8/src/api.cc
@@ -3802,6 +3802,35 @@ double v8::Date::NumberValue() const {
}
+void v8::Date::DateTimeConfigurationChangeNotification() {
+ ON_BAILOUT("v8::Date::DateTimeConfigurationChangeNotification()", return);
+ LOG_API("Date::DateTimeConfigurationChangeNotification");
+ ENTER_V8;
+
+ HandleScope scope;
+
+ // Get the function ResetDateCache (defined in date-delay.js).
+ i::Handle<i::String> func_name_str =
+ i::Factory::LookupAsciiSymbol("ResetDateCache");
+ i::MaybeObject* result = i::Top::builtins()->GetProperty(*func_name_str);
+ i::Object* object_func;
+ if (!result->ToObject(&object_func)) {
+ return;
+ }
+
+ if (object_func->IsJSFunction()) {
+ i::Handle<i::JSFunction> func =
+ i::Handle<i::JSFunction>(i::JSFunction::cast(object_func));
+
+ // Call ResetDateCache(0 but expect no exceptions:
+ bool caught_exception = false;
+ i::Handle<i::Object> result =
+ i::Execution::TryCall(func, i::Top::builtins(), 0, NULL,
+ &caught_exception);
+ }
+}
+
+
static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
char flags_buf[3];
int num_flags = 0;
diff --git a/deps/v8/src/arm/code-stubs-arm.cc b/deps/v8/src/arm/code-stubs-arm.cc
index 3670765a612..5ec8584f9ed 100644
--- a/deps/v8/src/arm/code-stubs-arm.cc
+++ b/deps/v8/src/arm/code-stubs-arm.cc
@@ -2893,80 +2893,97 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
}
-// This stub performs an instanceof, calling the builtin function if
-// necessary. Uses r1 for the object, r0 for the function that it may
-// be an instance of (these are fetched from the stack).
+// Uses registers r0 to r4. Expected input is
+// function in r0 (or at sp+1*ptrsz) and object in
+// r1 (or at sp), depending on whether or not
+// args_in_registers() is true.
void InstanceofStub::Generate(MacroAssembler* masm) {
- // Get the object - slow case for smis (we may need to throw an exception
- // depending on the rhs).
- Label slow, loop, is_instance, is_not_instance;
- __ ldr(r0, MemOperand(sp, 1 * kPointerSize));
- __ BranchOnSmi(r0, &slow);
+ // Fixed register usage throughout the stub:
+ const Register object = r1; // Object (lhs).
+ const Register map = r3; // Map of the object.
+ const Register function = r0; // Function (rhs).
+ const Register prototype = r4; // Prototype of the function.
+ const Register scratch = r2;
+ Label slow, loop, is_instance, is_not_instance, not_js_object;
+ if (!args_in_registers()) {
+ __ ldr(function, MemOperand(sp, 1 * kPointerSize));
+ __ ldr(object, MemOperand(sp, 0));
+ }
- // Check that the left hand is a JS object and put map in r3.
- __ CompareObjectType(r0, r3, r2, FIRST_JS_OBJECT_TYPE);
- __ b(lt, &slow);
- __ cmp(r2, Operand(LAST_JS_OBJECT_TYPE));
- __ b(gt, &slow);
-
- // Get the prototype of the function (r4 is result, r2 is scratch).
- __ ldr(r1, MemOperand(sp, 0));
- // r1 is function, r3 is map.
+ // Check that the left hand is a JS object and load map.
+ __ BranchOnSmi(object, &slow);
+ __ IsObjectJSObjectType(object, map, scratch, &slow);
// Look up the function and the map in the instanceof cache.
Label miss;
__ LoadRoot(ip, Heap::kInstanceofCacheFunctionRootIndex);
- __ cmp(r1, ip);
+ __ cmp(object, ip);
__ b(ne, &miss);
__ LoadRoot(ip, Heap::kInstanceofCacheMapRootIndex);
- __ cmp(r3, ip);
+ __ cmp(map, ip);
__ b(ne, &miss);
- __ LoadRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
- __ pop();
- __ pop();
- __ mov(pc, Operand(lr));
+ __ LoadRoot(function, Heap::kInstanceofCacheAnswerRootIndex);
+ __ Ret(args_in_registers() ? 0 : 2);
__ bind(&miss);
- __ TryGetFunctionPrototype(r1, r4, r2, &slow);
+ __ TryGetFunctionPrototype(object, prototype, scratch, &slow);
// Check that the function prototype is a JS object.
- __ BranchOnSmi(r4, &slow);
- __ CompareObjectType(r4, r5, r5, FIRST_JS_OBJECT_TYPE);
- __ b(lt, &slow);
- __ cmp(r5, Operand(LAST_JS_OBJECT_TYPE));
- __ b(gt, &slow);
+ __ BranchOnSmi(prototype, &slow);
+ __ IsObjectJSObjectType(prototype, scratch, scratch, &slow);
- __ StoreRoot(r1, Heap::kInstanceofCacheFunctionRootIndex);
- __ StoreRoot(r3, Heap::kInstanceofCacheMapRootIndex);
+ __ StoreRoot(object, Heap::kInstanceofCacheFunctionRootIndex);
+ __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex);
// Register mapping: r3 is object map and r4 is function prototype.
// Get prototype of object into r2.
- __ ldr(r2, FieldMemOperand(r3, Map::kPrototypeOffset));
+ __ ldr(scratch, FieldMemOperand(map, Map::kPrototypeOffset));
// Loop through the prototype chain looking for the function prototype.
__ bind(&loop);
- __ cmp(r2, Operand(r4));
+ __ cmp(scratch, Operand(prototype));
__ b(eq, &is_instance);
__ LoadRoot(ip, Heap::kNullValueRootIndex);
- __ cmp(r2, ip);
+ __ cmp(scratch, ip);
__ b(eq, &is_not_instance);
- __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset));
- __ ldr(r2, FieldMemOperand(r2, Map::kPrototypeOffset));
+ __ ldr(scratch, FieldMemOperand(scratch, HeapObject::kMapOffset));
+ __ ldr(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset));
__ jmp(&loop);
__ bind(&is_instance);
__ mov(r0, Operand(Smi::FromInt(0)));
__ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
- __ pop();
- __ pop();
- __ mov(pc, Operand(lr)); // Return.
+ __ Ret(args_in_registers() ? 0 : 2);
__ bind(&is_not_instance);
__ mov(r0, Operand(Smi::FromInt(1)));
- __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
- __ pop();
- __ pop();
- __ mov(pc, Operand(lr)); // Return.
+ __ Ret(args_in_registers() ? 0 : 2);
+
+ Label object_not_null, object_not_null_or_smi;
+ __ bind(&not_js_object);
+ // Before null, smi and string value checks, check that the rhs is a function
+ // as for a non-function rhs an exception needs to be thrown.
+ __ BranchOnSmi(function, &slow);
+ __ CompareObjectType(function, map, scratch, JS_FUNCTION_TYPE);
+ __ b(ne, &slow);
+
+ // Null is not instance of anything.
+ __ cmp(scratch, Operand(Factory::null_value()));
+ __ b(ne, &object_not_null);
+ __ mov(r0, Operand(Smi::FromInt(1)));
+ __ Ret(args_in_registers() ? 0 : 2);
+
+ __ bind(&object_not_null);
+ // Smi values are not instances of anything.
+ __ BranchOnNotSmi(object, &object_not_null_or_smi);
+ __ mov(r0, Operand(Smi::FromInt(1)));
+ __ Ret(args_in_registers() ? 0 : 2);
+
+ __ bind(&object_not_null_or_smi);
+ // String values are not instances of anything.
+ __ IsObjectJSStringType(object, scratch, &slow);
+ __ mov(r0, Operand(Smi::FromInt(1)));
+ __ Ret(args_in_registers() ? 0 : 2);
// Slow-case. Tail call builtin.
__ bind(&slow);
diff --git a/deps/v8/src/arm/lithium-arm.cc b/deps/v8/src/arm/lithium-arm.cc
index 9c792316f5e..e31d2e1d8a8 100644
--- a/deps/v8/src/arm/lithium-arm.cc
+++ b/deps/v8/src/arm/lithium-arm.cc
@@ -1316,7 +1316,8 @@ LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
LInstruction* result =
- new LInstanceOf(Use(instr->left()), Use(instr->right()));
+ new LInstanceOf(UseFixed(instr->left(), r1),
+ UseFixed(instr->right(), r0));
return MarkAsCall(DefineFixed(result, r0), instr);
}
@@ -1375,6 +1376,12 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
case kMathLog:
Abort("MathLog LUnaryMathOperation not implemented");
return NULL;
+ case kMathCos:
+ Abort("MathCos LUnaryMathOperation not implemented");
+ return NULL;
+ case kMathSin:
+ Abort("MathSin LUnaryMathOperation not implemented");
+ return NULL;
default:
UNREACHABLE();
return NULL;
diff --git a/deps/v8/src/arm/lithium-codegen-arm.cc b/deps/v8/src/arm/lithium-codegen-arm.cc
index 533d32c7474..dfc48917da6 100644
--- a/deps/v8/src/arm/lithium-codegen-arm.cc
+++ b/deps/v8/src/arm/lithium-codegen-arm.cc
@@ -1337,7 +1337,14 @@ void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
- Abort("DoInstanceOf unimplemented.");
+ // We expect object and function in registers r1 and r0.
+ InstanceofStub stub(InstanceofStub::kArgsInRegisters);
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+
+ Label true_value, done;
+ __ tst(r0, r0);
+ __ mov(r0, Operand(Factory::false_value()), LeaveCC, eq);
+ __ mov(r0, Operand(Factory::true_value()), LeaveCC, ne);
}
@@ -1547,7 +1554,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
- Abort("LUnaryMathOperation unimplemented.");
+ Abort("DoMathAbs unimplemented.");
}
@@ -1562,9 +1569,6 @@ void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
- ASSERT(instr->op() == kMathFloor ||
- instr->op() == kMathAbs);
-
switch (instr->op()) {
case kMathAbs:
DoMathAbs(instr);
@@ -1576,6 +1580,7 @@ void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
DoMathSqrt(instr);
break;
default:
+ Abort("Unimplemented type of LUnaryMathOperation.");
UNREACHABLE();
}
}
diff --git a/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc
index 6effec1e319..4a131465902 100644
--- a/deps/v8/src/arm/macro-assembler-arm.cc
+++ b/deps/v8/src/arm/macro-assembler-arm.cc
@@ -178,6 +178,12 @@ void MacroAssembler::Drop(int count, Condition cond) {
}
+void MacroAssembler::Ret(int drop, Condition cond) {
+ Drop(drop, cond);
+ Ret(cond);
+}
+
+
void MacroAssembler::Swap(Register reg1,
Register reg2,
Register scratch,
@@ -821,6 +827,38 @@ void MacroAssembler::InvokeFunction(JSFunction* function,
}
+void MacroAssembler::IsObjectJSObjectType(Register heap_object,
+ Register map,
+ Register scratch,
+ Label* fail) {
+ ldr(map, FieldMemOperand(heap_object, HeapObject::kMapOffset));
+ IsInstanceJSObjectType(map, scratch, fail);
+}
+
+
+void MacroAssembler::IsInstanceJSObjectType(Register map,
+ Register scratch,
+ Label* fail) {
+ ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
+ cmp(scratch, Operand(FIRST_JS_OBJECT_TYPE));
+ b(lt, fail);
+ cmp(scratch, Operand(LAST_JS_OBJECT_TYPE));
+ b(gt, fail);
+}
+
+
+void MacroAssembler::IsObjectJSStringType(Register object,
+ Register scratch,
+ Label* fail) {
+ ASSERT(kNotStringTag != 0);
+
+ ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
+ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
+ tst(scratch, Operand(kIsNotStringMask));
+ b(nz, fail);
+}
+
+
#ifdef ENABLE_DEBUGGER_SUPPORT
void MacroAssembler::DebugBreak() {
ASSERT(allow_stub_calls());
diff --git a/deps/v8/src/arm/macro-assembler-arm.h b/deps/v8/src/arm/macro-assembler-arm.h
index 3da8726777b..97bbb2fb678 100644
--- a/deps/v8/src/arm/macro-assembler-arm.h
+++ b/deps/v8/src/arm/macro-assembler-arm.h
@@ -96,6 +96,7 @@ class MacroAssembler: public Assembler {
// from the stack, clobbering only the sp register.
void Drop(int count, Condition cond = al);
+ void Ret(int drop, Condition cond = al);
// Swap two registers. If the scratch register is omitted then a slightly
// less efficient form using xor instead of mov is emitted.
@@ -298,6 +299,18 @@ class MacroAssembler: public Assembler {
const ParameterCount& actual,
InvokeFlag flag);
+ void IsObjectJSObjectType(Register heap_object,
+ Register map,
+ Register scratch,
+ Label* fail);
+
+ void IsInstanceJSObjectType(Register map,
+ Register scratch,
+ Label* fail);
+
+ void IsObjectJSStringType(Register object,
+ Register scratch,
+ Label* fail);
#ifdef ENABLE_DEBUGGER_SUPPORT
// ---------------------------------------------------------------------------
diff --git a/deps/v8/src/array.js b/deps/v8/src/array.js
index a805157b13b..0f1e969f987 100644
--- a/deps/v8/src/array.js
+++ b/deps/v8/src/array.js
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -677,39 +677,76 @@ function ArraySort(comparefn) {
function QuickSort(a, from, to) {
// Insertion sort is faster for short arrays.
- if (to - from <= 22) {
+ if (to - from <= 10) {
InsertionSort(a, from, to);
return;
}
- var pivot_index = $floor($random() * (to - from)) + from;
- var pivot = a[pivot_index];
- // Issue 95: Keep the pivot element out of the comparisons to avoid
- // infinite recursion if comparefn(pivot, pivot) != 0.
- %_SwapElements(a, from, pivot_index);
- var low_end = from; // Upper bound of the elements lower than pivot.
- var high_start = to; // Lower bound of the elements greater than pivot.
+ // Find a pivot as the median of first, last and middle element.
+ var v0 = a[from];
+ var v1 = a[to - 1];
+ var middle_index = from + ((to - from) >> 1);
+ var v2 = a[middle_index];
+ var c01 = %_CallFunction(global_receiver, v0, v1, comparefn);
+ if (c01 > 0) {
+ // v1 < v0, so swap them.
+ var tmp = v0;
+ v0 = v1;
+ v1 = tmp;
+ } // v0 <= v1.
+ var c02 = %_CallFunction(global_receiver, v0, v2, comparefn);
+ if (c02 >= 0) {
+ // v2 <= v0 <= v1.
+ var tmp = v0;
+ v0 = v2;
+ v2 = v1;
+ v1 = tmp;
+ } else {
+ // v0 <= v1 && v0 < v2
+ var c12 = %_CallFunction(global_receiver, v1, v2, comparefn);
+ if (c12 > 0) {
+ // v0 <= v2 < v1
+ var tmp = v1;
+ v1 = v2;
+ v2 = tmp;
+ }
+ }
+ // v0 <= v1 <= v2
+ a[from] = v0;
+ a[to - 1] = v2;
+ var pivot = v1;
+ var low_end = from + 1; // Upper bound of elements lower than pivot.
+ var high_start = to - 1; // Lower bound of elements greater than pivot.
+ a[middle_index] = a[low_end];
+ a[low_end] = pivot;
+
// From low_end to i are elements equal to pivot.
// From i to high_start are elements that haven't been compared yet.
- for (var i = from + 1; i < high_start; ) {
+ partition: for (var i = low_end + 1; i < high_start; i++) {
var element = a[i];
var order = %_CallFunction(global_receiver, element, pivot, comparefn);
if (order < 0) {
%_SwapElements(a, i, low_end);
- i++;
low_end++;
} else if (order > 0) {
- high_start--;
+ do {
+ high_start--;
+ if (high_start == i) break partition;
+ var top_elem = a[high_start];
+ order = %_CallFunction(global_receiver, top_elem, pivot, comparefn);
+ } while (order > 0);
%_SwapElements(a, i, high_start);
- } else { // order == 0
- i++;
+ if (order < 0) {
+ %_SwapElements(a, i, low_end);
+ low_end++;
+ }
}
}
QuickSort(a, from, low_end);
QuickSort(a, high_start, to);
}
- // Copies elements in the range 0..length from obj's prototype chain
- // to obj itself, if obj has holes. Returns one more than the maximal index
+ // Copy elements in the range 0..length from obj's prototype chain
+ // to obj itself, if obj has holes. Return one more than the maximal index
// of a prototype property.
function CopyFromPrototype(obj, length) {
var max = 0;
diff --git a/deps/v8/src/assembler.cc b/deps/v8/src/assembler.cc
index 3b44efa9c02..eeb84128d76 100644
--- a/deps/v8/src/assembler.cc
+++ b/deps/v8/src/assembler.cc
@@ -467,34 +467,35 @@ const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
}
-void RelocInfo::Print() {
- PrintF("%p %s", pc_, RelocModeName(rmode_));
+void RelocInfo::Print(FILE* out) {
+ PrintF(out, "%p %s", pc_, RelocModeName(rmode_));
if (IsComment(rmode_)) {
- PrintF(" (%s)", reinterpret_cast<char*>(data_));
+ PrintF(out, " (%s)", reinterpret_cast<char*>(data_));
} else if (rmode_ == EMBEDDED_OBJECT) {
- PrintF(" (");
- target_object()->ShortPrint();
- PrintF(")");
+ PrintF(out, " (");
+ target_object()->ShortPrint(out);
+ PrintF(out, ")");
} else if (rmode_ == EXTERNAL_REFERENCE) {
ExternalReferenceEncoder ref_encoder;
- PrintF(" (%s) (%p)",
+ PrintF(out, " (%s) (%p)",
ref_encoder.NameOfAddress(*target_reference_address()),
*target_reference_address());
} else if (IsCodeTarget(rmode_)) {
Code* code = Code::GetCodeFromTargetAddress(target_address());
- PrintF(" (%s) (%p)", Code::Kind2String(code->kind()), target_address());
+ PrintF(out, " (%s) (%p)", Code::Kind2String(code->kind()),
+ target_address());
} else if (IsPosition(rmode_)) {
- PrintF(" (%" V8_PTR_PREFIX "d)", data());
+ PrintF(out, " (%" V8_PTR_PREFIX "d)", data());
} else if (rmode_ == RelocInfo::RUNTIME_ENTRY) {
// Depotimization bailouts are stored as runtime entries.
int id = Deoptimizer::GetDeoptimizationId(
target_address(), Deoptimizer::EAGER);
if (id != Deoptimizer::kNotDeoptimizationEntry) {
- PrintF(" (deoptimization bailout %d)", id);
+ PrintF(out, " (deoptimization bailout %d)", id);
}
}
- PrintF("\n");
+ PrintF(out, "\n");
}
#endif // ENABLE_DISASSEMBLER
diff --git a/deps/v8/src/assembler.h b/deps/v8/src/assembler.h
index 72a9b15380b..b68ad389708 100644
--- a/deps/v8/src/assembler.h
+++ b/deps/v8/src/assembler.h
@@ -322,7 +322,7 @@ class RelocInfo BASE_EMBEDDED {
#ifdef ENABLE_DISASSEMBLER
// Printing
static const char* RelocModeName(Mode rmode);
- void Print();
+ void Print(FILE* out);
#endif // ENABLE_DISASSEMBLER
#ifdef DEBUG
// Debugging
diff --git a/deps/v8/src/builtins.cc b/deps/v8/src/builtins.cc
index a833119e853..21381f15d5c 100644
--- a/deps/v8/src/builtins.cc
+++ b/deps/v8/src/builtins.cc
@@ -515,10 +515,10 @@ BUILTIN(ArrayShift) {
Object* elms_obj;
{ MaybeObject* maybe_elms_obj =
EnsureJSArrayWithWritableFastElements(receiver);
+ if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayShift", args);
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
}
- if (elms_obj == NULL ||
- !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
+ if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
return CallJsBuiltin("ArrayShift", args);
}
FixedArray* elms = FixedArray::cast(elms_obj);
@@ -557,10 +557,10 @@ BUILTIN(ArrayUnshift) {
Object* elms_obj;
{ MaybeObject* maybe_elms_obj =
EnsureJSArrayWithWritableFastElements(receiver);
+ if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayUnshift", args);
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
}
- if (elms_obj == NULL ||
- !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
+ if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
return CallJsBuiltin("ArrayUnshift", args);
}
FixedArray* elms = FixedArray::cast(elms_obj);
@@ -611,21 +611,46 @@ BUILTIN(ArrayUnshift) {
BUILTIN(ArraySlice) {
Object* receiver = *args.receiver();
- Object* elms_obj;
+ FixedArray* elms;
+ int len = -1;
{ MaybeObject* maybe_elms_obj =
EnsureJSArrayWithWritableFastElements(receiver);
- if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
- }
- if (elms_obj == NULL ||
- !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
- return CallJsBuiltin("ArraySlice", args);
- }
- FixedArray* elms = FixedArray::cast(elms_obj);
- JSArray* array = JSArray::cast(receiver);
- ASSERT(array->HasFastElements());
-
- int len = Smi::cast(array->length())->value();
+ Object* elms_obj;
+ if (maybe_elms_obj != NULL && maybe_elms_obj->ToObject(&elms_obj)) {
+ if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
+ return CallJsBuiltin("ArraySlice", args);
+ }
+ elms = FixedArray::cast(elms_obj);
+ JSArray* array = JSArray::cast(receiver);
+ ASSERT(array->HasFastElements());
+ len = Smi::cast(array->length())->value();
+ } else {
+ // Array.slice(arguments, ...) is quite a common idiom (notably more
+ // than 50% of invocations in Web apps). Treat it in C++ as well.
+ Map* arguments_map =
+ Top::context()->global_context()->arguments_boilerplate()->map();
+
+ bool is_arguments_object_with_fast_elements =
+ receiver->IsJSObject()
+ && JSObject::cast(receiver)->map() == arguments_map
+ && JSObject::cast(receiver)->HasFastElements();
+ if (!is_arguments_object_with_fast_elements) {
+ return CallJsBuiltin("ArraySlice", args);
+ }
+ elms = FixedArray::cast(JSObject::cast(receiver)->elements());
+ len = elms->length();
+#ifdef DEBUG
+ // Arguments object by construction should have no holes, check it.
+ if (FLAG_enable_slow_asserts) {
+ for (int i = 0; i < len; i++) {
+ ASSERT(elms->get(i) != Heap::the_hole_value());
+ }
+ }
+#endif
+ }
+ }
+ ASSERT(len >= 0);
int n_arguments = args.length() - 1;
// Note carefully choosen defaults---if argument is missing,
@@ -693,10 +718,10 @@ BUILTIN(ArraySplice) {
Object* elms_obj;
{ MaybeObject* maybe_elms_obj =
EnsureJSArrayWithWritableFastElements(receiver);
+ if (maybe_elms_obj == NULL) return CallJsBuiltin("ArraySplice", args);
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
}
- if (elms_obj == NULL ||
- !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
+ if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
return CallJsBuiltin("ArraySplice", args);
}
FixedArray* elms = FixedArray::cast(elms_obj);
diff --git a/deps/v8/src/code-stubs.h b/deps/v8/src/code-stubs.h
index 8ba9971751b..b7804b77f28 100644
--- a/deps/v8/src/code-stubs.h
+++ b/deps/v8/src/code-stubs.h
@@ -47,7 +47,7 @@ namespace internal {
V(Compare) \
V(CompareIC) \
V(MathPow) \
- V(TranscendentalCacheSSE2) \
+ V(TranscendentalCache) \
V(RecordWrite) \
V(ConvertToDouble) \
V(WriteInt32ToHeapNumber) \
@@ -56,7 +56,6 @@ namespace internal {
V(FastNewClosure) \
V(FastNewContext) \
V(FastCloneShallowArray) \
- V(TranscendentalCache) \
V(GenericUnaryOp) \
V(RevertToNumber) \
V(ToBoolean) \
diff --git a/deps/v8/src/codegen.cc b/deps/v8/src/codegen.cc
index 8a64d77b709..da479e8fc1e 100644
--- a/deps/v8/src/codegen.cc
+++ b/deps/v8/src/codegen.cc
@@ -215,8 +215,17 @@ void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) {
}
PrintF("\n\n");
}
- PrintF("--- Code ---\n");
- code->Disassemble(*function->name()->ToCString());
+ if (info->IsOptimizing()) {
+ if (FLAG_print_unopt_code) {
+ PrintF("--- Unoptimized code ---\n");
+ info->closure()->shared()->code()->Disassemble(
+ *function->debug_name()->ToCString());
+ }
+ PrintF("--- Optimized code ---\n");
+ } else {
+ PrintF("--- Code ---\n");
+ }
+ code->Disassemble(*function->debug_name()->ToCString());
}
#endif // ENABLE_DISASSEMBLER
}
diff --git a/deps/v8/src/counters.h b/deps/v8/src/counters.h
index aed46cfb36e..048fdaabf29 100644
--- a/deps/v8/src/counters.h
+++ b/deps/v8/src/counters.h
@@ -28,6 +28,9 @@
#ifndef V8_COUNTERS_H_
#define V8_COUNTERS_H_
+#include "../include/v8.h"
+#include "allocation.h"
+
namespace v8 {
namespace internal {
diff --git a/deps/v8/src/date.js b/deps/v8/src/date.js
index 38bb8eb2544..bc70327c41c 100644
--- a/deps/v8/src/date.js
+++ b/deps/v8/src/date.js
@@ -1007,6 +1007,39 @@ function DateToJSON(key) {
}
+function ResetDateCache() {
+
+ // Reset the local_time_offset:
+ local_time_offset = %DateLocalTimeOffset();
+
+ // Reset the DST offset cache:
+ var cache = DST_offset_cache;
+ cache.offset = 0;
+ cache.start = 0;
+ cache.end = -1;
+ cache.increment = 0;
+ cache.initial_increment = 19 * msPerDay;
+
+ // Reset the timezone cache:
+ timezone_cache_time = $NaN;
+ timezone_cache_timezone = undefined;
+
+ // Reset the ltcache:
+ ltcache.key = null;
+ ltcache.val = null;
+
+ // Reset the ymd_from_time_cache:
+ ymd_from_time_cache = [$NaN, $NaN, $NaN];
+ ymd_from_time_cached_time = $NaN;
+
+ // Reset the date cache:
+ cache = Date_cache;
+ cache.time = $NaN;
+ cache.year = $NaN;
+ cache.string = null;
+}
+
+
// -------------------------------------------------------------------
function SetupDate() {
diff --git a/deps/v8/src/debug.cc b/deps/v8/src/debug.cc
index 7709eb0e93d..ca3c1db790b 100644
--- a/deps/v8/src/debug.cc
+++ b/deps/v8/src/debug.cc
@@ -858,7 +858,7 @@ bool Debug::Load() {
if (caught_exception) return false;
// Debugger loaded.
- debug_context_ = Handle<Context>::cast(GlobalHandles::Create(*context));
+ debug_context_ = context;
return true;
}
diff --git a/deps/v8/src/deoptimizer.cc b/deps/v8/src/deoptimizer.cc
index 93839a49a80..dd70baaa165 100644
--- a/deps/v8/src/deoptimizer.cc
+++ b/deps/v8/src/deoptimizer.cc
@@ -1096,7 +1096,7 @@ int Translation::NumberOfOperandsFor(Opcode opcode) {
}
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
const char* Translation::StringFor(Opcode opcode) {
switch (opcode) {
diff --git a/deps/v8/src/deoptimizer.h b/deps/v8/src/deoptimizer.h
index 32edd1009f5..2d7dfc895c3 100644
--- a/deps/v8/src/deoptimizer.h
+++ b/deps/v8/src/deoptimizer.h
@@ -476,7 +476,7 @@ class Translation BASE_EMBEDDED {
static int NumberOfOperandsFor(Opcode opcode);
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
static const char* StringFor(Opcode opcode);
#endif
diff --git a/deps/v8/src/flag-definitions.h b/deps/v8/src/flag-definitions.h
index facbec273b1..f160a85afc7 100644
--- a/deps/v8/src/flag-definitions.h
+++ b/deps/v8/src/flag-definitions.h
@@ -296,6 +296,9 @@ DEFINE_int(max_map_space_pages, MapSpace::kMaxMapPageIndex - 1,
DEFINE_bool(h, false, "print this message")
DEFINE_bool(new_snapshot, true, "use new snapshot implementation")
+// objects.cc
+DEFINE_bool(use_verbose_printer, true, "allows verbose printing")
+
// parser.cc
DEFINE_bool(allow_natives_syntax, false, "allow natives syntax")
@@ -503,6 +506,8 @@ DEFINE_bool(print_code_stubs, false, "print code stubs")
// codegen-ia32.cc / codegen-arm.cc
DEFINE_bool(print_code, false, "print generated code")
DEFINE_bool(print_opt_code, false, "print optimized code")
+DEFINE_bool(print_unopt_code, false, "print unoptimized code before "
+ "printing optimized code based on it")
DEFINE_bool(print_code_verbose, false, "print more information for code")
DEFINE_bool(print_builtin_code, false, "print generated code for builtins")
diff --git a/deps/v8/src/full-codegen.cc b/deps/v8/src/full-codegen.cc
index 96307a302d5..58540f07bc6 100644
--- a/deps/v8/src/full-codegen.cc
+++ b/deps/v8/src/full-codegen.cc
@@ -671,8 +671,12 @@ const FullCodeGenerator::InlineFunctionGenerator
FullCodeGenerator::InlineFunctionGenerator
FullCodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) {
- return kInlineFunctionGenerators[
- static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction)];
+ int lookup_index =
+ static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction);
+ ASSERT(lookup_index >= 0);
+ ASSERT(static_cast<size_t>(lookup_index) <
+ ARRAY_SIZE(kInlineFunctionGenerators));
+ return kInlineFunctionGenerators[lookup_index];
}
@@ -684,7 +688,6 @@ void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* node) {
ASSERT(function->intrinsic_type == Runtime::INLINE);
InlineFunctionGenerator generator =
FindInlineFunctionGenerator(function->function_id);
- ASSERT(generator != NULL);
((*this).*(generator))(args);
}
diff --git a/deps/v8/src/heap-profiler.cc b/deps/v8/src/heap-profiler.cc
index 002950031bd..dfda7c6fec5 100644
--- a/deps/v8/src/heap-profiler.cc
+++ b/deps/v8/src/heap-profiler.cc
@@ -367,7 +367,6 @@ HeapSnapshot* HeapProfiler::TakeSnapshot(String* name,
HeapSnapshot* HeapProfiler::TakeSnapshotImpl(const char* name,
int type,
v8::ActivityControl* control) {
- Heap::CollectAllGarbage(true);
HeapSnapshot::Type s_type = static_cast<HeapSnapshot::Type>(type);
HeapSnapshot* result =
snapshots_->NewSnapshot(s_type, name, next_snapshot_uid_++);
@@ -379,6 +378,7 @@ HeapSnapshot* HeapProfiler::TakeSnapshotImpl(const char* name,
break;
}
case HeapSnapshot::kAggregated: {
+ Heap::CollectAllGarbage(true);
AggregatedHeapSnapshot agg_snapshot;
AggregatedHeapSnapshotGenerator generator(&agg_snapshot);
generator.GenerateSnapshot();
@@ -808,7 +808,7 @@ void AggregatedHeapSnapshotGenerator::CollectStats(HeapObject* obj) {
void AggregatedHeapSnapshotGenerator::GenerateSnapshot() {
- HeapIterator iterator(HeapIterator::kPreciseFiltering);
+ HeapIterator iterator(HeapIterator::kFilterFreeListNodes);
for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
CollectStats(obj);
agg_snapshot_->js_cons_profile()->CollectStats(obj);
diff --git a/deps/v8/src/heap.cc b/deps/v8/src/heap.cc
index ccf9b47a35c..1e9999164cc 100644
--- a/deps/v8/src/heap.cc
+++ b/deps/v8/src/heap.cc
@@ -4483,7 +4483,7 @@ void Heap::RecordStats(HeapStats* stats, bool take_snapshot) {
MemoryAllocator::Size() + MemoryAllocator::Available();
*stats->os_error = OS::GetLastError();
if (take_snapshot) {
- HeapIterator iterator(HeapIterator::kPreciseFiltering);
+ HeapIterator iterator(HeapIterator::kFilterFreeListNodes);
for (HeapObject* obj = iterator.next();
obj != NULL;
obj = iterator.next()) {
@@ -4917,13 +4917,20 @@ ObjectIterator* SpaceIterator::CreateIterator() {
}
-class FreeListNodesFilter {
+class HeapObjectsFilter {
+ public:
+ virtual ~HeapObjectsFilter() {}
+ virtual bool SkipObject(HeapObject* object) = 0;
+};
+
+
+class FreeListNodesFilter : public HeapObjectsFilter {
public:
FreeListNodesFilter() {
MarkFreeListNodes();
}
- inline bool IsFreeListNode(HeapObject* object) {
+ bool SkipObject(HeapObject* object) {
if (object->IsMarked()) {
object->ClearMark();
return true;
@@ -4955,6 +4962,65 @@ class FreeListNodesFilter {
};
+class UnreachableObjectsFilter : public HeapObjectsFilter {
+ public:
+ UnreachableObjectsFilter() {
+ MarkUnreachableObjects();
+ }
+
+ bool SkipObject(HeapObject* object) {
+ if (object->IsMarked()) {
+ object->ClearMark();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private:
+ class UnmarkingVisitor : public ObjectVisitor {
+ public:
+ UnmarkingVisitor() : list_(10) {}
+
+ void VisitPointers(Object** start, Object** end) {
+ for (Object** p = start; p < end; p++) {
+ if (!(*p)->IsHeapObject()) continue;
+ HeapObject* obj = HeapObject::cast(*p);
+ if (obj->IsMarked()) {
+ obj->ClearMark();
+ list_.Add(obj);
+ }
+ }
+ }
+
+ bool can_process() { return !list_.is_empty(); }
+
+ void ProcessNext() {
+ HeapObject* obj = list_.RemoveLast();
+ obj->Iterate(this);
+ }
+
+ private:
+ List<HeapObject*> list_;
+ };
+
+ void MarkUnreachableObjects() {
+ HeapIterator iterator;
+ for (HeapObject* obj = iterator.next();
+ obj != NULL;
+ obj = iterator.next()) {
+ obj->SetMark();
+ }
+ UnmarkingVisitor visitor;
+ Heap::IterateRoots(&visitor, VISIT_ONLY_STRONG);
+ while (visitor.can_process())
+ visitor.ProcessNext();
+ }
+
+ AssertNoAllocation no_alloc;
+};
+
+
HeapIterator::HeapIterator()
: filtering_(HeapIterator::kNoFiltering),
filter_(NULL) {
@@ -4962,7 +5028,7 @@ HeapIterator::HeapIterator()
}
-HeapIterator::HeapIterator(HeapIterator::FreeListNodesFiltering filtering)
+HeapIterator::HeapIterator(HeapIterator::HeapObjectsFiltering filtering)
: filtering_(filtering),
filter_(NULL) {
Init();
@@ -4976,12 +5042,17 @@ HeapIterator::~HeapIterator() {
void HeapIterator::Init() {
// Start the iteration.
- if (filtering_ == kPreciseFiltering) {
- filter_ = new FreeListNodesFilter;
- space_iterator_ =
- new SpaceIterator(MarkCompactCollector::SizeOfMarkedObject);
- } else {
- space_iterator_ = new SpaceIterator;
+ space_iterator_ = filtering_ == kNoFiltering ? new SpaceIterator :
+ new SpaceIterator(MarkCompactCollector::SizeOfMarkedObject);
+ switch (filtering_) {
+ case kFilterFreeListNodes:
+ filter_ = new FreeListNodesFilter;
+ break;
+ case kFilterUnreachable:
+ filter_ = new UnreachableObjectsFilter;
+ break;
+ default:
+ break;
}
object_iterator_ = space_iterator_->next();
}
@@ -4989,9 +5060,9 @@ void HeapIterator::Init() {
void HeapIterator::Shutdown() {
#ifdef DEBUG
- // Assert that in precise mode we have iterated through all
+ // Assert that in filtering mode we have iterated through all
// objects. Otherwise, heap will be left in an inconsistent state.
- if (filtering_ == kPreciseFiltering) {
+ if (filtering_ != kNoFiltering) {
ASSERT(object_iterator_ == NULL);
}
#endif
@@ -5008,7 +5079,7 @@ HeapObject* HeapIterator::next() {
if (filter_ == NULL) return NextObject();
HeapObject* obj = NextObject();
- while (obj != NULL && filter_->IsFreeListNode(obj)) obj = NextObject();
+ while (obj != NULL && filter_->SkipObject(obj)) obj = NextObject();
return obj;
}
diff --git a/deps/v8/src/heap.h b/deps/v8/src/heap.h
index fbcc70df531..18a4afbe46a 100644
--- a/deps/v8/src/heap.h
+++ b/deps/v8/src/heap.h
@@ -1585,17 +1585,18 @@ class SpaceIterator : public Malloced {
// nodes filtering uses GC marks, it can't be used during MS/MC GC
// phases. Also, it is forbidden to interrupt iteration in this mode,
// as this will leave heap objects marked (and thus, unusable).
-class FreeListNodesFilter;
+class HeapObjectsFilter;
class HeapIterator BASE_EMBEDDED {
public:
- enum FreeListNodesFiltering {
+ enum HeapObjectsFiltering {
kNoFiltering,
- kPreciseFiltering
+ kFilterFreeListNodes,
+ kFilterUnreachable
};
HeapIterator();
- explicit HeapIterator(FreeListNodesFiltering filtering);
+ explicit HeapIterator(HeapObjectsFiltering filtering);
~HeapIterator();
HeapObject* next();
@@ -1608,8 +1609,8 @@ class HeapIterator BASE_EMBEDDED {
void Shutdown();
HeapObject* NextObject();
- FreeListNodesFiltering filtering_;
- FreeListNodesFilter* filter_;
+ HeapObjectsFiltering filtering_;
+ HeapObjectsFilter* filter_;
// Space iterator for iterating all the spaces.
SpaceIterator* space_iterator_;
// Object iterator for the space currently being iterated.
@@ -1968,6 +1969,8 @@ class GCTracer BASE_EMBEDDED {
class TranscendentalCache {
public:
enum Type {ACOS, ASIN, ATAN, COS, EXP, LOG, SIN, TAN, kNumberOfCaches};
+ static const int kTranscendentalTypeBits = 3;
+ STATIC_ASSERT((1 << kTranscendentalTypeBits) >= kNumberOfCaches);
explicit TranscendentalCache(Type t);
@@ -2056,7 +2059,6 @@ class TranscendentalCache {
friend class ExternalReference;
// Inline implementation of the cache.
friend class TranscendentalCacheStub;
- friend class TranscendentalCacheSSE2Stub;
static TranscendentalCache* caches_[kNumberOfCaches];
Element elements_[kCacheSize];
diff --git a/deps/v8/src/hydrogen-instructions.cc b/deps/v8/src/hydrogen-instructions.cc
index a96ee406ff5..3f39888e9bf 100644
--- a/deps/v8/src/hydrogen-instructions.cc
+++ b/deps/v8/src/hydrogen-instructions.cc
@@ -579,6 +579,13 @@ void HBranch::PrintDataTo(StringStream* stream) const {
}
+void HCompareMapAndBranch::PrintDataTo(StringStream* stream) const {
+ stream->Add("on ");
+ value()->PrintNameTo(stream);
+ stream->Add(" (%p)", *map());
+}
+
+
void HGoto::PrintDataTo(StringStream* stream) const {
stream->Add("B%d", FirstSuccessor()->block_id());
}
diff --git a/deps/v8/src/hydrogen-instructions.h b/deps/v8/src/hydrogen-instructions.h
index aafa7a8830c..cbbe8fcc88a 100644
--- a/deps/v8/src/hydrogen-instructions.h
+++ b/deps/v8/src/hydrogen-instructions.h
@@ -905,6 +905,8 @@ class HCompareMapAndBranch: public HUnaryControlInstruction {
virtual HBasicBlock* FirstSuccessor() const { return true_destination_; }
virtual HBasicBlock* SecondSuccessor() const { return false_destination_; }
+ virtual void PrintDataTo(StringStream* stream) const;
+
Handle<Map> map() const { return map_; }
DECLARE_CONCRETE_INSTRUCTION(CompareMapAndBranch, "compare_map_and_branch")
@@ -1387,6 +1389,8 @@ class HUnaryMathOperation: public HUnaryOperation {
case kMathSqrt:
case kMathPowHalf:
case kMathLog:
+ case kMathSin:
+ case kMathCos:
set_representation(Representation::Double());
break;
default:
@@ -1409,6 +1413,8 @@ class HUnaryMathOperation: public HUnaryOperation {
case kMathSqrt:
case kMathPowHalf:
case kMathLog:
+ case kMathSin:
+ case kMathCos:
return Representation::Double();
break;
case kMathAbs:
diff --git a/deps/v8/src/hydrogen.cc b/deps/v8/src/hydrogen.cc
index 32108dc1cde..e34acd67d44 100644
--- a/deps/v8/src/hydrogen.cc
+++ b/deps/v8/src/hydrogen.cc
@@ -3165,6 +3165,9 @@ HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object,
if (lookup->type() == MAP_TRANSITION) {
Handle<Map> transition(lookup->GetTransitionMapFromMap(*type));
instr->set_transition(transition);
+ // TODO(fschneider): Record the new map type of the object in the IR to
+ // enable elimination of redundant checks after the transition store.
+ instr->SetFlag(HValue::kChangesMaps);
}
return instr;
}
@@ -3529,9 +3532,10 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
maps.Add(map);
HSubgraph* subgraph = CreateBranchSubgraph(environment());
SubgraphScope scope(this, subgraph);
- HInstruction* instr =
+ HLoadNamedField* instr =
BuildLoadNamedField(object, expr, map, &lookup, false);
instr->set_position(expr->position());
+ instr->ClearFlag(HValue::kUseGVN); // Don't do GVN on polymorphic loads.
PushAndAdd(instr);
subgraphs.Add(subgraph);
} else {
@@ -3570,11 +3574,11 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
}
-HInstruction* HGraphBuilder::BuildLoadNamedField(HValue* object,
- Property* expr,
- Handle<Map> type,
- LookupResult* lookup,
- bool smi_and_map_check) {
+HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
+ Property* expr,
+ Handle<Map> type,
+ LookupResult* lookup,
+ bool smi_and_map_check) {
if (smi_and_map_check) {
AddInstruction(new HCheckNonSmi(object));
AddInstruction(new HCheckMap(object, type));
@@ -4093,6 +4097,8 @@ bool HGraphBuilder::TryMathFunctionInline(Call* expr) {
case kMathAbs:
case kMathSqrt:
case kMathLog:
+ case kMathSin:
+ case kMathCos:
if (argument_count == 2) {
HValue* argument = Pop();
Drop(1); // Receiver.
@@ -4169,7 +4175,7 @@ bool HGraphBuilder::TryCallApply(Call* expr) {
if (args->length() != 2) return false;
VariableProxy* arg_two = args->at(1)->AsVariableProxy();
- if (arg_two == NULL) return false;
+ if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
HValue* arg_two_value = environment()->Lookup(arg_two->var());
if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
diff --git a/deps/v8/src/hydrogen.h b/deps/v8/src/hydrogen.h
index 2c9aeac75c2..ebabf3d2923 100644
--- a/deps/v8/src/hydrogen.h
+++ b/deps/v8/src/hydrogen.h
@@ -786,11 +786,11 @@ class HGraphBuilder: public AstVisitor {
HValue* left,
HValue* right);
HInstruction* BuildIncrement(HValue* value, bool increment);
- HInstruction* BuildLoadNamedField(HValue* object,
- Property* expr,
- Handle<Map> type,
- LookupResult* result,
- bool smi_and_map_check);
+ HLoadNamedField* BuildLoadNamedField(HValue* object,
+ Property* expr,
+ Handle<Map> type,
+ LookupResult* result,
+ bool smi_and_map_check);
HInstruction* BuildLoadNamedGeneric(HValue* object, Property* expr);
HInstruction* BuildLoadKeyedFastElement(HValue* object,
HValue* key,
diff --git a/deps/v8/src/ia32/code-stubs-ia32.cc b/deps/v8/src/ia32/code-stubs-ia32.cc
index d75acab0826..a371c963931 100644
--- a/deps/v8/src/ia32/code-stubs-ia32.cc
+++ b/deps/v8/src/ia32/code-stubs-ia32.cc
@@ -2472,41 +2472,65 @@ void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
- // Input on stack:
- // esp[4]: argument (should be number).
- // esp[0]: return address.
- // Test that eax is a number.
+ // TAGGED case:
+ // Input:
+ // esp[4]: tagged number input argument (should be number).
+ // esp[0]: return address.
+ // Output:
+ // eax: tagged double result.
+ // UNTAGGED case:
+ // Input::
+ // esp[0]: return address.
+ // xmm1: untagged double input argument
+ // Output:
+ // xmm1: untagged double result.
+
Label runtime_call;
Label runtime_call_clear_stack;
- NearLabel input_not_smi;
- NearLabel loaded;
- __ mov(eax, Operand(esp, kPointerSize));
- __ test(eax, Immediate(kSmiTagMask));
- __ j(not_zero, &input_not_smi);
- // Input is a smi. Untag and load it onto the FPU stack.
- // Then load the low and high words of the double into ebx, edx.
- STATIC_ASSERT(kSmiTagSize == 1);
- __ sar(eax, 1);
- __ sub(Operand(esp), Immediate(2 * kPointerSize));
- __ mov(Operand(esp, 0), eax);
- __ fild_s(Operand(esp, 0));
- __ fst_d(Operand(esp, 0));
- __ pop(edx);
- __ pop(ebx);
- __ jmp(&loaded);
- __ bind(&input_not_smi);
- // Check if input is a HeapNumber.
- __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
- __ cmp(Operand(ebx), Immediate(Factory::heap_number_map()));
- __ j(not_equal, &runtime_call);
- // Input is a HeapNumber. Push it on the FPU stack and load its
- // low and high words into ebx, edx.
- __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
- __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset));
- __ mov(ebx, FieldOperand(eax, HeapNumber::kMantissaOffset));
+ Label skip_cache;
+ const bool tagged = (argument_type_ == TAGGED);
+ if (tagged) {
+ // Test that eax is a number.
+ NearLabel input_not_smi;
+ NearLabel loaded;
+ __ mov(eax, Operand(esp, kPointerSize));
+ __ test(eax, Immediate(kSmiTagMask));
+ __ j(not_zero, &input_not_smi);
+ // Input is a smi. Untag and load it onto the FPU stack.
+ // Then load the low and high words of the double into ebx, edx.
+ STATIC_ASSERT(kSmiTagSize == 1);
+ __ sar(eax, 1);
+ __ sub(Operand(esp), Immediate(2 * kPointerSize));
+ __ mov(Operand(esp, 0), eax);
+ __ fild_s(Operand(esp, 0));
+ __ fst_d(Operand(esp, 0));
+ __ pop(edx);
+ __ pop(ebx);
+ __ jmp(&loaded);
+ __ bind(&input_not_smi);
+ // Check if input is a HeapNumber.
+ __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
+ __ cmp(Operand(ebx), Immediate(Factory::heap_number_map()));
+ __ j(not_equal, &runtime_call);
+ // Input is a HeapNumber. Push it on the FPU stack and load its
+ // low and high words into ebx, edx.
+ __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
+ __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset));
+ __ mov(ebx, FieldOperand(eax, HeapNumber::kMantissaOffset));
+
+ __ bind(&loaded);
+ } else { // UNTAGGED.
+ if (CpuFeatures::IsSupported(SSE4_1)) {
+ CpuFeatures::Scope sse4_scope(SSE4_1);
+ __ pextrd(Operand(edx), xmm1, 0x1); // copy xmm1[63..32] to edx.
+ } else {
+ __ pshufd(xmm0, xmm1, 0x1);
+ __ movd(Operand(edx), xmm0);
+ }
+ __ movd(Operand(ebx), xmm1);
+ }
- __ bind(&loaded);
- // ST[0] == double value
+ // ST[0] or xmm1 == double value
// ebx = low 32 bits of double value
// edx = high 32 bits of double value
// Compute hash (the shifts are arithmetic):
@@ -2522,7 +2546,7 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize));
__ and_(Operand(ecx), Immediate(TranscendentalCache::kCacheSize - 1));
- // ST[0] == double value.
+ // ST[0] or xmm1 == double value.
// ebx = low 32 bits of double value.
// edx = high 32 bits of double value.
// ecx = TranscendentalCache::hash(double value).
@@ -2559,31 +2583,80 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
__ j(not_equal, &cache_miss);
// Cache hit!
__ mov(eax, Operand(ecx, 2 * kIntSize));
- __ fstp(0);
- __ ret(kPointerSize);
+ if (tagged) {
+ __ fstp(0);
+ __ ret(kPointerSize);
+ } else { // UNTAGGED.
+ __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
+ __ Ret();
+ }
__ bind(&cache_miss);
// Update cache with new value.
// We are short on registers, so use no_reg as scratch.
// This gives slightly larger code.
- __ AllocateHeapNumber(eax, edi, no_reg, &runtime_call_clear_stack);
+ if (tagged) {
+ __ AllocateHeapNumber(eax, edi, no_reg, &runtime_call_clear_stack);
+ } else { // UNTAGGED.
+ __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
+ __ sub(Operand(esp), Immediate(kDoubleSize));
+ __ movdbl(Operand(esp, 0), xmm1);
+ __ fld_d(Operand(esp, 0));
+ __ add(Operand(esp), Immediate(kDoubleSize));
+ }
GenerateOperation(masm);
__ mov(Operand(ecx, 0), ebx);
__ mov(Operand(ecx, kIntSize), edx);
__ mov(Operand(ecx, 2 * kIntSize), eax);
__ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
- __ ret(kPointerSize);
+ if (tagged) {
+ __ ret(kPointerSize);
+ } else { // UNTAGGED.
+ __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
+ __ Ret();
+
+ // Skip cache and return answer directly, only in untagged case.
+ __ bind(&skip_cache);
+ __ sub(Operand(esp), Immediate(kDoubleSize));
+ __ movdbl(Operand(esp, 0), xmm1);
+ __ fld_d(Operand(esp, 0));
+ GenerateOperation(masm);
+ __ fstp_d(Operand(esp, 0));
+ __ movdbl(xmm1, Operand(esp, 0));
+ __ add(Operand(esp), Immediate(kDoubleSize));
+ // We return the value in xmm1 without adding it to the cache, but
+ // we cause a scavenging GC so that future allocations will succeed.
+ __ EnterInternalFrame();
+ // Allocate an unused object bigger than a HeapNumber.
+ __ push(Immediate(Smi::FromInt(2 * kDoubleSize)));
+ __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace);
+ __ LeaveInternalFrame();
+ __ Ret();
+ }
- __ bind(&runtime_call_clear_stack);
- __ fstp(0);
- __ bind(&runtime_call);
- __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1);
+ // Call runtime, doing whatever allocation and cleanup is necessary.
+ if (tagged) {
+ __ bind(&runtime_call_clear_stack);
+ __ fstp(0);
+ __ bind(&runtime_call);
+ __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1);
+ } else { // UNTAGGED.
+ __ bind(&runtime_call_clear_stack);
+ __ bind(&runtime_call);
+ __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
+ __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm1);
+ __ EnterInternalFrame();
+ __ push(eax);
+ __ CallRuntime(RuntimeFunction(), 1);
+ __ LeaveInternalFrame();
+ __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
+ __ Ret();
+ }
}
Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
switch (type_) {
- // Add more cases when necessary.
case TranscendentalCache::SIN: return Runtime::kMath_sin;
case TranscendentalCache::COS: return Runtime::kMath_cos;
case TranscendentalCache::LOG: return Runtime::kMath_log;
@@ -2596,14 +2669,14 @@ Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) {
// Only free register is edi.
- // Input value is on FP stack, and also in ebx/edx. Address of result
- // (a newly allocated HeapNumber) is in eax.
- NearLabel done;
+ // Input value is on FP stack, and also in ebx/edx.
+ // Input value is possibly in xmm1.
+ // Address of result (a newly allocated HeapNumber) may be in eax.
if (type_ == TranscendentalCache::SIN || type_ == TranscendentalCache::COS) {
// Both fsin and fcos require arguments in the range +/-2^63 and
// return NaN for infinities and NaN. They can share all code except
// the actual fsin/fcos operation.
- NearLabel in_range;
+ NearLabel in_range, done;
// If argument is outside the range -2^63..2^63, fsin/cos doesn't
// work. We must reduce it to the appropriate range.
__ mov(edi, edx);
@@ -2683,145 +2756,6 @@ void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) {
}
-void TranscendentalCacheSSE2Stub::Generate(MacroAssembler* masm) {
- // Input on stack:
- // esp[0]: return address.
- // Input in registers:
- // xmm1: untagged double input argument.
- // Output:
- // xmm1: untagged double result.
- Label skip_cache;
- Label call_runtime;
-
- // Input is an untagged double in xmm1.
- // Compute hash (the shifts are arithmetic):
- // h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
- if (CpuFeatures::IsSupported(SSE4_1)) {
- CpuFeatures::Scope sse4_scope(SSE4_1);
- __ pextrd(Operand(edx), xmm1, 0x1); // copy xmm1[63..32] to edx.
- } else {
- __ pshufd(xmm0, xmm1, 0x1);
- __ movd(Operand(edx), xmm0);
- }
- __ movd(Operand(ebx), xmm1);
-
- // xmm1 = double value
- // ebx = low 32 bits of double value
- // edx = high 32 bits of double value
- // Compute hash (the shifts are arithmetic):
- // h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
- __ mov(ecx, ebx);
- __ xor_(ecx, Operand(edx));
- __ mov(eax, ecx);
- __ sar(eax, 16);
- __ xor_(ecx, Operand(eax));
- __ mov(eax, ecx);
- __ sar(eax, 8);
- __ xor_(ecx, Operand(eax));
- ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize));
- __ and_(Operand(ecx), Immediate(TranscendentalCache::kCacheSize - 1));
-
- // xmm1 = double value.
- // ebx = low 32 bits of double value.
- // edx = high 32 bits of double value.
- // ecx = TranscendentalCache::hash(double value).
- __ mov(eax,
- Immediate(ExternalReference::transcendental_cache_array_address()));
- // Eax points to cache array.
- __ mov(eax, Operand(eax, type_ * sizeof(TranscendentalCache::caches_[0])));
- // Eax points to the cache for the type type_.
- // If NULL, the cache hasn't been initialized yet, so go through runtime.
- __ test(eax, Operand(eax));
- __ j(zero, &call_runtime);
-#ifdef DEBUG
- // Check that the layout of cache elements match expectations.
- { TranscendentalCache::Element test_elem[2];
- char* elem_start = reinterpret_cast<char*>(&test_elem[0]);
- char* elem2_start = reinterpret_cast<char*>(&test_elem[1]);
- char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0]));
- char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1]));
- char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output));
- CHECK_EQ(12, elem2_start - elem_start); // Two uint_32's and a pointer.
- CHECK_EQ(0, elem_in0 - elem_start);
- CHECK_EQ(kIntSize, elem_in1 - elem_start);
- CHECK_EQ(2 * kIntSize, elem_out - elem_start);
- }
-#endif
- // Find the address of the ecx'th entry in the cache, i.e., &eax[ecx*12].
- __ lea(ecx, Operand(ecx, ecx, times_2, 0));
- __ lea(ecx, Operand(eax, ecx, times_4, 0));
- // Check if cache matches: Double value is stored in uint32_t[2] array.
- NearLabel cache_miss;
- __ cmp(ebx, Operand(ecx, 0));
- __ j(not_equal, &cache_miss);
- __ cmp(edx, Operand(ecx, kIntSize));
- __ j(not_equal, &cache_miss);
- // Cache hit!
- __ mov(eax, Operand(ecx, 2 * kIntSize));
- __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
- __ Ret();
-
- __ bind(&cache_miss);
- // Update cache with new value.
- // We are short on registers, so use no_reg as scratch.
- // This gives slightly larger code.
- __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
- __ sub(Operand(esp), Immediate(kDoubleSize));
- __ movdbl(Operand(esp, 0), xmm1);
- __ fld_d(Operand(esp, 0));
- __ add(Operand(esp), Immediate(kDoubleSize));
- GenerateOperation(masm);
- __ mov(Operand(ecx, 0), ebx);
- __ mov(Operand(ecx, kIntSize), edx);
- __ mov(Operand(ecx, 2 * kIntSize), eax);
- __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
- __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
- __ Ret();
-
- __ bind(&skip_cache);
- __ sub(Operand(esp), Immediate(kDoubleSize));
- __ movdbl(Operand(esp, 0), xmm1);
- __ fld_d(Operand(esp, 0));
- GenerateOperation(masm);
- __ fstp_d(Operand(esp, 0));
- __ movdbl(xmm1, Operand(esp, 0));
- __ add(Operand(esp), Immediate(kDoubleSize));
- __ Ret();
-
- __ bind(&call_runtime);
- __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
- __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm1);
- __ EnterInternalFrame();
- __ push(eax);
- __ CallRuntime(RuntimeFunction(), 1);
- __ LeaveInternalFrame();
- __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
- __ Ret();
-}
-
-
-Runtime::FunctionId TranscendentalCacheSSE2Stub::RuntimeFunction() {
- switch (type_) {
- // Add more cases when necessary.
- case TranscendentalCache::LOG: return Runtime::kMath_log;
- default:
- UNIMPLEMENTED();
- return Runtime::kAbort;
- }
-}
-
-
-void TranscendentalCacheSSE2Stub::GenerateOperation(MacroAssembler* masm) {
- // Only free register is edi.
- // Input value is on FP stack and in xmm1.
-
- ASSERT(type_ == TranscendentalCache::LOG);
- __ fldln2();
- __ fxch();
- __ fyl2x();
-}
-
-
// Get the integer part of a heap number. Surprisingly, all this bit twiddling
// is faster than using the built-in instructions on floating point registers.
// Trashes edi and ebx. Dest is ecx. Source cannot be ecx or one of the
diff --git a/deps/v8/src/ia32/code-stubs-ia32.h b/deps/v8/src/ia32/code-stubs-ia32.h
index 04f23ace9b4..f66a8c7e45a 100644
--- a/deps/v8/src/ia32/code-stubs-ia32.h
+++ b/deps/v8/src/ia32/code-stubs-ia32.h
@@ -40,32 +40,21 @@ namespace internal {
// TranscendentalCache runtime function.
class TranscendentalCacheStub: public CodeStub {
public:
- explicit TranscendentalCacheStub(TranscendentalCache::Type type)
- : type_(type) {}
- void Generate(MacroAssembler* masm);
- private:
- TranscendentalCache::Type type_;
-
- Major MajorKey() { return TranscendentalCache; }
- int MinorKey() { return type_; }
- Runtime::FunctionId RuntimeFunction();
- void GenerateOperation(MacroAssembler* masm);
-};
-
+ enum ArgumentType {
+ TAGGED = 0,
+ UNTAGGED = 1 << TranscendentalCache::kTranscendentalTypeBits
+ };
-// Check the transcendental cache, or generate the result, using SSE2.
-// The argument and result will be in xmm1.
-// Only supports TranscendentalCache::LOG at this point.
-class TranscendentalCacheSSE2Stub: public CodeStub {
- public:
- explicit TranscendentalCacheSSE2Stub(TranscendentalCache::Type type)
- : type_(type) {}
+ explicit TranscendentalCacheStub(TranscendentalCache::Type type,
+ ArgumentType argument_type)
+ : type_(type), argument_type_(argument_type) {}
void Generate(MacroAssembler* masm);
private:
TranscendentalCache::Type type_;
+ ArgumentType argument_type_;
- Major MajorKey() { return TranscendentalCacheSSE2; }
- int MinorKey() { return type_; }
+ Major MajorKey() { return TranscendentalCache; }
+ int MinorKey() { return type_ | argument_type_; }
Runtime::FunctionId RuntimeFunction();
void GenerateOperation(MacroAssembler* masm);
};
diff --git a/deps/v8/src/ia32/codegen-ia32.cc b/deps/v8/src/ia32/codegen-ia32.cc
index 4c9d05558bd..2f14e82e14a 100644
--- a/deps/v8/src/ia32/codegen-ia32.cc
+++ b/deps/v8/src/ia32/codegen-ia32.cc
@@ -7912,7 +7912,8 @@ void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) {
ASSERT_EQ(args->length(), 1);
Load(args->at(0));
- TranscendentalCacheStub stub(TranscendentalCache::SIN);
+ TranscendentalCacheStub stub(TranscendentalCache::SIN,
+ TranscendentalCacheStub::TAGGED);
Result result = frame_->CallStub(&stub, 1);
frame_->Push(&result);
}
@@ -7921,7 +7922,8 @@ void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
ASSERT_EQ(args->length(), 1);
Load(args->at(0));
- TranscendentalCacheStub stub(TranscendentalCache::COS);
+ TranscendentalCacheStub stub(TranscendentalCache::COS,
+ TranscendentalCacheStub::TAGGED);
Result result = frame_->CallStub(&stub, 1);
frame_->Push(&result);
}
@@ -7930,7 +7932,8 @@ void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) {
ASSERT_EQ(args->length(), 1);
Load(args->at(0));
- TranscendentalCacheStub stub(TranscendentalCache::LOG);
+ TranscendentalCacheStub stub(TranscendentalCache::LOG,
+ TranscendentalCacheStub::TAGGED);
Result result = frame_->CallStub(&stub, 1);
frame_->Push(&result);
}
diff --git a/deps/v8/src/ia32/full-codegen-ia32.cc b/deps/v8/src/ia32/full-codegen-ia32.cc
index be059cdfe3a..13a11777ab6 100644
--- a/deps/v8/src/ia32/full-codegen-ia32.cc
+++ b/deps/v8/src/ia32/full-codegen-ia32.cc
@@ -3067,7 +3067,8 @@ void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
// Load the argument on the stack and call the stub.
- TranscendentalCacheStub stub(TranscendentalCache::SIN);
+ TranscendentalCacheStub stub(TranscendentalCache::SIN,
+ TranscendentalCacheStub::TAGGED);
ASSERT(args->length() == 1);
VisitForStackValue(args->at(0));
__ CallStub(&stub);
@@ -3077,7 +3078,8 @@ void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
// Load the argument on the stack and call the stub.
- TranscendentalCacheStub stub(TranscendentalCache::COS);
+ TranscendentalCacheStub stub(TranscendentalCache::COS,
+ TranscendentalCacheStub::TAGGED);
ASSERT(args->length() == 1);
VisitForStackValue(args->at(0));
__ CallStub(&stub);
@@ -3087,7 +3089,8 @@ void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
// Load the argument on the stack and call the stub.
- TranscendentalCacheStub stub(TranscendentalCache::LOG);
+ TranscendentalCacheStub stub(TranscendentalCache::LOG,
+ TranscendentalCacheStub::TAGGED);
ASSERT(args->length() == 1);
VisitForStackValue(args->at(0));
__ CallStub(&stub);
diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.cc b/deps/v8/src/ia32/lithium-codegen-ia32.cc
index 0e9773748e0..d64f528e71c 100644
--- a/deps/v8/src/ia32/lithium-codegen-ia32.cc
+++ b/deps/v8/src/ia32/lithium-codegen-ia32.cc
@@ -686,7 +686,8 @@ void LCodeGen::DoCallStub(LCallStub* instr) {
break;
}
case CodeStub::TranscendentalCache: {
- TranscendentalCacheStub stub(instr->transcendental_type());
+ TranscendentalCacheStub stub(instr->transcendental_type(),
+ TranscendentalCacheStub::TAGGED);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
break;
}
@@ -2314,7 +2315,24 @@ void LCodeGen::DoPower(LPower* instr) {
void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
- TranscendentalCacheSSE2Stub stub(TranscendentalCache::LOG);
+ TranscendentalCacheStub stub(TranscendentalCache::LOG,
+ TranscendentalCacheStub::UNTAGGED);
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+}
+
+
+void LCodeGen::DoMathCos(LUnaryMathOperation* instr) {
+ ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
+ TranscendentalCacheStub stub(TranscendentalCache::COS,
+ TranscendentalCacheStub::UNTAGGED);
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+}
+
+
+void LCodeGen::DoMathSin(LUnaryMathOperation* instr) {
+ ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
+ TranscendentalCacheStub stub(TranscendentalCache::SIN,
+ TranscendentalCacheStub::UNTAGGED);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
}
@@ -2336,6 +2354,12 @@ void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
case kMathPowHalf:
DoMathPowHalf(instr);
break;
+ case kMathCos:
+ DoMathCos(instr);
+ break;
+ case kMathSin:
+ DoMathSin(instr);
+ break;
case kMathLog:
DoMathLog(instr);
break;
diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.h b/deps/v8/src/ia32/lithium-codegen-ia32.h
index 5ac7b1edb24..6d8173a1cf2 100644
--- a/deps/v8/src/ia32/lithium-codegen-ia32.h
+++ b/deps/v8/src/ia32/lithium-codegen-ia32.h
@@ -177,6 +177,8 @@ class LCodeGen BASE_EMBEDDED {
void DoMathSqrt(LUnaryMathOperation* instr);
void DoMathPowHalf(LUnaryMathOperation* instr);
void DoMathLog(LUnaryMathOperation* instr);
+ void DoMathCos(LUnaryMathOperation* instr);
+ void DoMathSin(LUnaryMathOperation* instr);
// Support for recording safepoint and position information.
void RecordSafepoint(LPointerMap* pointers, int deoptimization_index);
diff --git a/deps/v8/src/ia32/lithium-ia32.cc b/deps/v8/src/ia32/lithium-ia32.cc
index e1148fc186f..3b272d0b022 100644
--- a/deps/v8/src/ia32/lithium-ia32.cc
+++ b/deps/v8/src/ia32/lithium-ia32.cc
@@ -1361,7 +1361,7 @@ LInstruction* LChunkBuilder::DoCallConstantFunction(
LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
BuiltinFunctionId op = instr->op();
- if (op == kMathLog) {
+ if (op == kMathLog || op == kMathSin || op == kMathCos) {
LOperand* input = UseFixedDouble(instr->value(), xmm1);
LInstruction* result = new LUnaryMathOperation(input);
return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
diff --git a/deps/v8/src/objects-debug.cc b/deps/v8/src/objects-debug.cc
index cb7b35ec433..53296d9272f 100644
--- a/deps/v8/src/objects-debug.cc
+++ b/deps/v8/src/objects-debug.cc
@@ -35,32 +35,34 @@
namespace v8 {
namespace internal {
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
static const char* TypeToString(InstanceType type);
-void MaybeObject::Print() {
+void MaybeObject::Print(FILE* out) {
Object* this_as_object;
if (ToObject(&this_as_object)) {
if (this_as_object->IsSmi()) {
- Smi::cast(this_as_object)->SmiPrint();
+ Smi::cast(this_as_object)->SmiPrint(out);
} else {
- HeapObject::cast(this_as_object)->HeapObjectPrint();
+ HeapObject::cast(this_as_object)->HeapObjectPrint(out);
}
} else {
- Failure::cast(this)->FailurePrint();
+ Failure::cast(this)->FailurePrint(out);
}
- Flush();
+ Flush(out);
}
-void MaybeObject::PrintLn() {
- Print();
- PrintF("\n");
+void MaybeObject::PrintLn(FILE* out) {
+ Print(out);
+ PrintF(out, "\n");
}
+#endif // OBJECT_PRINT
+#ifdef DEBUG
void MaybeObject::Verify() {
Object* this_as_object;
if (ToObject(&this_as_object)) {
@@ -92,114 +94,120 @@ void Smi::SmiVerify() {
void Failure::FailureVerify() {
ASSERT(IsFailure());
}
+#endif // DEBUG
-void HeapObject::PrintHeader(const char* id) {
- PrintF("%p: [%s]\n", reinterpret_cast<void*>(this), id);
+#ifdef OBJECT_PRINT
+void HeapObject::PrintHeader(FILE* out, const char* id) {
+ PrintF(out, "%p: [%s]\n", reinterpret_cast<void*>(this), id);
}
-void HeapObject::HeapObjectPrint() {
+void HeapObject::HeapObjectPrint(FILE* out) {
InstanceType instance_type = map()->instance_type();
HandleScope scope;
if (instance_type < FIRST_NONSTRING_TYPE) {
- String::cast(this)->StringPrint();
+ String::cast(this)->StringPrint(out);
return;
}
switch (instance_type) {
case MAP_TYPE:
- Map::cast(this)->MapPrint();
+ Map::cast(this)->MapPrint(out);
break;
case HEAP_NUMBER_TYPE:
- HeapNumber::cast(this)->HeapNumberPrint();
+ HeapNumber::cast(this)->HeapNumberPrint(out);
break;
case FIXED_ARRAY_TYPE:
- FixedArray::cast(this)->FixedArrayPrint();
+ FixedArray::cast(this)->FixedArrayPrint(out);
break;
case BYTE_ARRAY_TYPE:
- ByteArray::cast(this)->ByteArrayPrint();
+ ByteArray::cast(this)->ByteArrayPrint(out);
break;
case PIXEL_ARRAY_TYPE:
- PixelArray::cast(this)->PixelArrayPrint();
+ PixelArray::cast(this)->PixelArrayPrint(out);
break;
case EXTERNAL_BYTE_ARRAY_TYPE:
- ExternalByteArray::cast(this)->ExternalByteArrayPrint();
+ ExternalByteArray::cast(this)->ExternalByteArrayPrint(out);
break;
case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
- ExternalUnsignedByteArray::cast(this)->ExternalUnsignedByteArrayPrint();
+ ExternalUnsignedByteArray::cast(this)
+ ->ExternalUnsignedByteArrayPrint(out);
break;
case EXTERNAL_SHORT_ARRAY_TYPE:
- ExternalShortArray::cast(this)->ExternalShortArrayPrint();
+ ExternalShortArray::cast(this)->ExternalShortArrayPrint(out);
break;
case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
- ExternalUnsignedShortArray::cast(this)->ExternalUnsignedShortArrayPrint();
+ ExternalUnsignedShortArray::cast(this)
+ ->ExternalUnsignedShortArrayPrint(out);
break;
case EXTERNAL_INT_ARRAY_TYPE:
- ExternalIntArray::cast(this)->ExternalIntArrayPrint();
+ ExternalIntArray::cast(this)->ExternalIntArrayPrint(out);
break;
case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
- ExternalUnsignedIntArray::cast(this)->ExternalUnsignedIntArrayPrint();
+ ExternalUnsignedIntArray::cast(this)->ExternalUnsignedIntArrayPrint(out);
break;
case EXTERNAL_FLOAT_ARRAY_TYPE:
- ExternalFloatArray::cast(this)->ExternalFloatArrayPrint();
+ ExternalFloatArray::cast(this)->ExternalFloatArrayPrint(out);
break;
case FILLER_TYPE:
- PrintF("filler");
+ PrintF(out, "filler");
break;
case JS_OBJECT_TYPE: // fall through
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
case JS_ARRAY_TYPE:
case JS_REGEXP_TYPE:
- JSObject::cast(this)->JSObjectPrint();
+ JSObject::cast(this)->JSObjectPrint(out);
break;
case ODDBALL_TYPE:
- Oddball::cast(this)->to_string()->Print();
+ Oddball::cast(this)->to_string()->Print(out);
break;
case JS_FUNCTION_TYPE:
- JSFunction::cast(this)->JSFunctionPrint();
+ JSFunction::cast(this)->JSFunctionPrint(out);
break;
case JS_GLOBAL_PROXY_TYPE:
- JSGlobalProxy::cast(this)->JSGlobalProxyPrint();
+ JSGlobalProxy::cast(this)->JSGlobalProxyPrint(out);
break;
case JS_GLOBAL_OBJECT_TYPE:
- JSGlobalObject::cast(this)->JSGlobalObjectPrint();
+ JSGlobalObject::cast(this)->JSGlobalObjectPrint(out);
break;
case JS_BUILTINS_OBJECT_TYPE:
- JSBuiltinsObject::cast(this)->JSBuiltinsObjectPrint();
+ JSBuiltinsObject::cast(this)->JSBuiltinsObjectPrint(out);
break;
case JS_VALUE_TYPE:
- PrintF("Value wrapper around:");
- JSValue::cast(this)->value()->Print();
+ PrintF(out, "Value wrapper around:");
+ JSValue::cast(this)->value()->Print(out);
break;
case CODE_TYPE:
- Code::cast(this)->CodePrint();
+ Code::cast(this)->CodePrint(out);
break;
case PROXY_TYPE:
- Proxy::cast(this)->ProxyPrint();
+ Proxy::cast(this)->ProxyPrint(out);
break;
case SHARED_FUNCTION_INFO_TYPE:
- SharedFunctionInfo::cast(this)->SharedFunctionInfoPrint();
+ SharedFunctionInfo::cast(this)->SharedFunctionInfoPrint(out);
break;
case JS_GLOBAL_PROPERTY_CELL_TYPE:
- JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellPrint();
+ JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellPrint(out);
break;
#define MAKE_STRUCT_CASE(NAME, Name, name) \
case NAME##_TYPE: \
- Name::cast(this)->Name##Print(); \
+ Name::cast(this)->Name##Print(out); \
break;
STRUCT_LIST(MAKE_STRUCT_CASE)
#undef MAKE_STRUCT_CASE
default:
- PrintF("UNKNOWN TYPE %d", map()->instance_type());
+ PrintF(out, "UNKNOWN TYPE %d", map()->instance_type());
UNREACHABLE();
break;
}
}
+#endif // OBJECT_PRINT
+#ifdef DEBUG
void HeapObject::HeapObjectVerify() {
InstanceType instance_type = map()->instance_type();
@@ -312,53 +320,57 @@ void HeapObject::VerifyHeapPointer(Object* p) {
void HeapNumber::HeapNumberVerify() {
ASSERT(IsHeapNumber());
}
+#endif // DEBUG
-void ByteArray::ByteArrayPrint() {
- PrintF("byte array, data starts at %p", GetDataStartAddress());
+#ifdef OBJECT_PRINT
+void ByteArray::ByteArrayPrint(FILE* out) {
+ PrintF(out, "byte array, data starts at %p", GetDataStartAddress());
}
-void PixelArray::PixelArrayPrint() {
- PrintF("pixel array");
+void PixelArray::PixelArrayPrint(FILE* out) {
+ PrintF(out, "pixel array");
}
-void ExternalByteArray::ExternalByteArrayPrint() {
- PrintF("external byte array");
+void ExternalByteArray::ExternalByteArrayPrint(FILE* out) {
+ PrintF(out, "external byte array");
}
-void ExternalUnsignedByteArray::ExternalUnsignedByteArrayPrint() {
- PrintF("external unsigned byte array");
+void ExternalUnsignedByteArray::ExternalUnsignedByteArrayPrint(FILE* out) {
+ PrintF(out, "external unsigned byte array");
}
-void ExternalShortArray::ExternalShortArrayPrint() {
- PrintF("external short array");
+void ExternalShortArray::ExternalShortArrayPrint(FILE* out) {
+ PrintF(out, "external short array");
}
-void ExternalUnsignedShortArray::ExternalUnsignedShortArrayPrint() {
- PrintF("external unsigned short array");
+void ExternalUnsignedShortArray::ExternalUnsignedShortArrayPrint(FILE* out) {
+ PrintF(out, "external unsigned short array");
}
-void ExternalIntArray::ExternalIntArrayPrint() {
- PrintF("external int array");
+void ExternalIntArray::ExternalIntArrayPrint(FILE* out) {
+ PrintF(out, "external int array");
}
-void ExternalUnsignedIntArray::ExternalUnsignedIntArrayPrint() {
- PrintF("external unsigned int array");
+void ExternalUnsignedIntArray::ExternalUnsignedIntArrayPrint(FILE* out) {
+ PrintF(out, "external unsigned int array");
}
-void ExternalFloatArray::ExternalFloatArrayPrint() {
- PrintF("external float array");
+void ExternalFloatArray::ExternalFloatArrayPrint(FILE* out) {
+ PrintF(out, "external float array");
}
+#endif // OBJECT_PRINT
+#ifdef DEBUG
void ByteArray::ByteArrayVerify() {
ASSERT(IsByteArray());
}
@@ -402,38 +414,40 @@ void ExternalUnsignedIntArray::ExternalUnsignedIntArrayVerify() {
void ExternalFloatArray::ExternalFloatArrayVerify() {
ASSERT(IsExternalFloatArray());
}
+#endif // DEBUG
-void JSObject::PrintProperties() {
+#ifdef OBJECT_PRINT
+void JSObject::PrintProperties(FILE* out) {
if (HasFastProperties()) {
DescriptorArray* descs = map()->instance_descriptors();
for (int i = 0; i < descs->number_of_descriptors(); i++) {
- PrintF(" ");
- descs->GetKey(i)->StringPrint();
- PrintF(": ");
+ PrintF(out, " ");
+ descs->GetKey(i)->StringPrint(out);
+ PrintF(out, ": ");
switch (descs->GetType(i)) {
case FIELD: {
int index = descs->GetFieldIndex(i);
- FastPropertyAt(index)->ShortPrint();
- PrintF(" (field at offset %d)\n", index);
+ FastPropertyAt(index)->ShortPrint(out);
+ PrintF(out, " (field at offset %d)\n", index);
break;
}
case CONSTANT_FUNCTION:
- descs->GetConstantFunction(i)->ShortPrint();
- PrintF(" (constant function)\n");
+ descs->GetConstantFunction(i)->ShortPrint(out);
+ PrintF(out, " (constant function)\n");
break;
case CALLBACKS:
- descs->GetCallbacksObject(i)->ShortPrint();
- PrintF(" (callback)\n");
+ descs->GetCallbacksObject(i)->ShortPrint(out);
+ PrintF(out, " (callback)\n");
break;
case MAP_TRANSITION:
- PrintF(" (map transition)\n");
+ PrintF(out, " (map transition)\n");
break;
case CONSTANT_TRANSITION:
- PrintF(" (constant transition)\n");
+ PrintF(out, " (constant transition)\n");
break;
case NULL_DESCRIPTOR:
- PrintF(" (null descriptor)\n");
+ PrintF(out, " (null descriptor)\n");
break;
default:
UNREACHABLE();
@@ -441,34 +455,34 @@ void JSObject::PrintProperties() {
}
}
} else {
- property_dictionary()->Print();
+ property_dictionary()->Print(out);
}
}
-void JSObject::PrintElements() {
+void JSObject::PrintElements(FILE* out) {
switch (GetElementsKind()) {
case FAST_ELEMENTS: {
// Print in array notation for non-sparse arrays.
FixedArray* p = FixedArray::cast(elements());
for (int i = 0; i < p->length(); i++) {
- PrintF(" %d: ", i);
- p->get(i)->ShortPrint();
- PrintF("\n");
+ PrintF(out, " %d: ", i);
+ p->get(i)->ShortPrint(out);
+ PrintF(out, "\n");
}
break;
}
case PIXEL_ELEMENTS: {
PixelArray* p = PixelArray::cast(elements());
for (int i = 0; i < p->length(); i++) {
- PrintF(" %d: %d\n", i, p->get(i));
+ PrintF(out, " %d: %d\n", i, p->get(i));
}
break;
}
case EXTERNAL_BYTE_ELEMENTS: {
ExternalByteArray* p = ExternalByteArray::cast(elements());
for (int i = 0; i < p->length(); i++) {
- PrintF(" %d: %d\n", i, static_cast<int>(p->get(i)));
+ PrintF(out, " %d: %d\n", i, static_cast<int>(p->get(i)));
}
break;
}
@@ -476,14 +490,14 @@ void JSObject::PrintElements() {
ExternalUnsignedByteArray* p =
ExternalUnsignedByteArray::cast(elements());
for (int i = 0; i < p->length(); i++) {
- PrintF(" %d: %d\n", i, static_cast<int>(p->get(i)));
+ PrintF(out, " %d: %d\n", i, static_cast<int>(p->get(i)));
}
break;
}
case EXTERNAL_SHORT_ELEMENTS: {
ExternalShortArray* p = ExternalShortArray::cast(elements());
for (int i = 0; i < p->length(); i++) {
- PrintF(" %d: %d\n", i, static_cast<int>(p->get(i)));
+ PrintF(out, " %d: %d\n", i, static_cast<int>(p->get(i)));
}
break;
}
@@ -491,14 +505,14 @@ void JSObject::PrintElements() {
ExternalUnsignedShortArray* p =
ExternalUnsignedShortArray::cast(elements());
for (int i = 0; i < p->length(); i++) {
- PrintF(" %d: %d\n", i, static_cast<int>(p->get(i)));
+ PrintF(out, " %d: %d\n", i, static_cast<int>(p->get(i)));
}
break;
}
case EXTERNAL_INT_ELEMENTS: {
ExternalIntArray* p = ExternalIntArray::cast(elements());
for (int i = 0; i < p->length(); i++) {
- PrintF(" %d: %d\n", i, static_cast<int>(p->get(i)));
+ PrintF(out, " %d: %d\n", i, static_cast<int>(p->get(i)));
}
break;
}
@@ -506,19 +520,19 @@ void JSObject::PrintElements() {
ExternalUnsignedIntArray* p =
ExternalUnsignedIntArray::cast(elements());
for (int i = 0; i < p->length(); i++) {
- PrintF(" %d: %d\n", i, static_cast<int>(p->get(i)));
+ PrintF(out, " %d: %d\n", i, static_cast<int>(p->get(i)));
}
break;
}
case EXTERNAL_FLOAT_ELEMENTS: {
ExternalFloatArray* p = ExternalFloatArray::cast(elements());
for (int i = 0; i < p->length(); i++) {
- PrintF(" %d: %f\n", i, p->get(i));
+ PrintF(out, " %d: %f\n", i, p->get(i));
}
break;
}
case DICTIONARY_ELEMENTS:
- elements()->Print();
+ elements()->Print(out);
break;
default:
UNREACHABLE();
@@ -527,17 +541,19 @@ void JSObject::PrintElements() {
}
-void JSObject::JSObjectPrint() {
- PrintF("%p: [JSObject]\n", reinterpret_cast<void*>(this));
- PrintF(" - map = %p\n", reinterpret_cast<void*>(map()));
- PrintF(" - prototype = %p\n", reinterpret_cast<void*>(GetPrototype()));
- PrintF(" {\n");
- PrintProperties();
- PrintElements();
- PrintF(" }\n");
+void JSObject::JSObjectPrint(FILE* out) {
+ PrintF(out, "%p: [JSObject]\n", reinterpret_cast<void*>(this));
+ PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
+ PrintF(out, " - prototype = %p\n", reinterpret_cast<void*>(GetPrototype()));
+ PrintF(out, " {\n");
+ PrintProperties(out);
+ PrintElements(out);
+ PrintF(out, " }\n");
}
+#endif // OBJECT_PRINT
+#ifdef DEBUG
void JSObject::JSObjectVerify() {
VerifyHeapPointer(properties());
VerifyHeapPointer(elements());
@@ -551,8 +567,10 @@ void JSObject::JSObjectVerify() {
elements()->map() == Heap::fixed_cow_array_map()));
ASSERT(map()->has_fast_elements() == HasFastElements());
}
+#endif // DEBUG
+#ifdef OBJECT_PRINT
static const char* TypeToString(InstanceType type) {
switch (type) {
case INVALID_TYPE: return "INVALID";
@@ -608,42 +626,44 @@ static const char* TypeToString(InstanceType type) {
}
-void Map::MapPrint() {
- HeapObject::PrintHeader("Map");
- PrintF(" - type: %s\n", TypeToString(instance_type()));
- PrintF(" - instance size: %d\n", instance_size());
- PrintF(" - inobject properties: %d\n", inobject_properties());
- PrintF(" - pre-allocated property fields: %d\n",
+void Map::MapPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "Map");
+ PrintF(out, " - type: %s\n", TypeToString(instance_type()));
+ PrintF(out, " - instance size: %d\n", instance_size());
+ PrintF(out, " - inobject properties: %d\n", inobject_properties());
+ PrintF(out, " - pre-allocated property fields: %d\n",
pre_allocated_property_fields());
- PrintF(" - unused property fields: %d\n", unused_property_fields());
+ PrintF(out, " - unused property fields: %d\n", unused_property_fields());
if (is_hidden_prototype()) {
- PrintF(" - hidden_prototype\n");
+ PrintF(out, " - hidden_prototype\n");
}
if (has_named_interceptor()) {
- PrintF(" - named_interceptor\n");
+ PrintF(out, " - named_interceptor\n");
}
if (has_indexed_interceptor()) {
- PrintF(" - indexed_interceptor\n");
+ PrintF(out, " - indexed_interceptor\n");
}
if (is_undetectable()) {
- PrintF(" - undetectable\n");
+ PrintF(out, " - undetectable\n");
}
if (has_instance_call_handler()) {
- PrintF(" - instance_call_handler\n");
+ PrintF(out, " - instance_call_handler\n");
}
if (is_access_check_needed()) {
- PrintF(" - access_check_needed\n");
+ PrintF(out, " - access_check_needed\n");
}
- PrintF(" - instance descriptors: ");
- instance_descriptors()->ShortPrint();
- PrintF("\n - prototype: ");
- prototype()->ShortPrint();
- PrintF("\n - constructor: ");
- constructor()->ShortPrint();
- PrintF("\n");
+ PrintF(out, " - instance descriptors: ");
+ instance_descriptors()->ShortPrint(out);
+ PrintF(out, "\n - prototype: ");
+ prototype()->ShortPrint(out);
+ PrintF(out, "\n - constructor: ");
+ constructor()->ShortPrint(out);
+ PrintF(out, "\n");
}
+#endif // OBJECT_PRINT
+#ifdef DEBUG
void Map::MapVerify() {
ASSERT(!Heap::InNewSpace(this));
ASSERT(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE);
@@ -665,17 +685,21 @@ void Map::SharedMapVerify() {
ASSERT_EQ(StaticVisitorBase::GetVisitorId(instance_type(), instance_size()),
visitor_id());
}
+#endif // DEBUG
-void CodeCache::CodeCachePrint() {
- HeapObject::PrintHeader("CodeCache");
- PrintF("\n - default_cache: ");
- default_cache()->ShortPrint();
- PrintF("\n - normal_type_cache: ");
- normal_type_cache()->ShortPrint();
+#ifdef OBJECT_PRINT
+void CodeCache::CodeCachePrint(FILE* out) {
+ HeapObject::PrintHeader(out, "CodeCache");
+ PrintF(out, "\n - default_cache: ");
+ default_cache()->ShortPrint(out);
+ PrintF(out, "\n - normal_type_cache: ");
+ normal_type_cache()->ShortPrint(out);
}
+#endif // OBJECT_PRINT
+#ifdef DEBUG
void CodeCache::CodeCacheVerify() {
VerifyHeapPointer(default_cache());
VerifyHeapPointer(normal_type_cache());
@@ -683,19 +707,23 @@ void CodeCache::CodeCacheVerify() {
ASSERT(normal_type_cache()->IsUndefined()
|| normal_type_cache()->IsCodeCacheHashTable());
}
+#endif // DEBUG
-void FixedArray::FixedArrayPrint() {
- HeapObject::PrintHeader("FixedArray");
- PrintF(" - length: %d", length());
+#ifdef OBJECT_PRINT
+void FixedArray::FixedArrayPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "FixedArray");
+ PrintF(out, " - length: %d", length());
for (int i = 0; i < length(); i++) {
- PrintF("\n [%d]: ", i);
- get(i)->ShortPrint();
+ PrintF(out, "\n [%d]: ", i);
+ get(i)->ShortPrint(out);
}
- PrintF("\n");
+ PrintF(out, "\n");
}
+#endif // OBJECT_PRINT
+#ifdef DEBUG
void FixedArray::FixedArrayVerify() {
for (int i = 0; i < length(); i++) {
Object* e = get(i);
@@ -706,39 +734,57 @@ void FixedArray::FixedArrayVerify() {
}
}
}
+#endif // DEBUG
-void JSValue::JSValuePrint() {
- HeapObject::PrintHeader("ValueObject");
- value()->Print();
+#ifdef OBJECT_PRINT
+void JSValue::JSValuePrint(FILE* out) {
+ HeapObject::PrintHeader(out, "ValueObject");
+ value()->Print(out);
}
+#endif // OBJECT_PRINT
+#ifdef DEBUG
void JSValue::JSValueVerify() {
Object* v = value();
if (v->IsHeapObject()) {
VerifyHeapPointer(v);
}
}
+#endif // DEBUG
-void String::StringPrint() {
+#ifdef OBJECT_PRINT
+void String::StringPrint(FILE* out) {
if (StringShape(this).IsSymbol()) {
- PrintF("#");
+ PrintF(out, "#");
} else if (StringShape(this).IsCons()) {
- PrintF("c\"");
+ PrintF(out, "c\"");
} else {
- PrintF("\"");
+ PrintF(out, "\"");
}
- for (int i = 0; i < length(); i++) {
- PrintF("%c", Get(i));
+ const char truncated_epilogue[] = "...<truncated>";
+ int len = length();
+ if (!FLAG_use_verbose_printer) {
+ if (len > 100) {
+ len = 100 - sizeof(truncated_epilogue);
+ }
+ }
+ for (int i = 0; i < len; i++) {
+ PrintF(out, "%c", Get(i));
+ }
+ if (len != length()) {
+ PrintF(out, "%s", truncated_epilogue);
}
- if (!StringShape(this).IsSymbol()) PrintF("\"");
+ if (!StringShape(this).IsSymbol()) PrintF(out, "\"");
}
+#endif // OBJECT_PRINT
+#ifdef DEBUG
void String::StringVerify() {
CHECK(IsString());
CHECK(length() >= 0 && length() <= Smi::kMaxValue);
@@ -746,32 +792,36 @@ void String::StringVerify() {
CHECK(!Heap::InNewSpace(this));
}
}
+#endif // DEBUG
-void JSFunction::JSFunctionPrint() {
- HeapObject::PrintHeader("Function");
- PrintF(" - map = 0x%p\n", reinterpret_cast<void*>(map()));
- PrintF(" - initial_map = ");
+#ifdef OBJECT_PRINT
+void JSFunction::JSFunctionPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "Function");
+ PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
+ PrintF(out, " - initial_map = ");
if (has_initial_map()) {
- initial_map()->ShortPrint();
+ initial_map()->ShortPrint(out);
}
- PrintF("\n - shared_info = ");
- shared()->ShortPrint();
- PrintF("\n - name = ");
- shared()->name()->Print();
- PrintF("\n - context = ");
- unchecked_context()->ShortPrint();
- PrintF("\n - code = ");
- code()->ShortPrint();
- PrintF("\n");
+ PrintF(out, "\n - shared_info = ");
+ shared()->ShortPrint(out);
+ PrintF(out, "\n - name = ");
+ shared()->name()->Print(out);
+ PrintF(out, "\n - context = ");
+ unchecked_context()->ShortPrint(out);
+ PrintF(out, "\n - code = ");
+ code()->ShortPrint(out);
+ PrintF(out, "\n");
- PrintProperties();
- PrintElements();
+ PrintProperties(out);
+ PrintElements(out);
- PrintF("\n");
+ PrintF(out, "\n");
}
+#endif // OBJECT_PRINT
+#ifdef DEBUG
void JSFunction::JSFunctionVerify() {
CHECK(IsJSFunction());
VerifyObjectField(kPrototypeOrInitialMapOffset);
@@ -779,36 +829,41 @@ void JSFunction::JSFunctionVerify() {
CHECK(next_function_link()->IsUndefined() ||
next_function_link()->IsJSFunction());
}
+#endif // DEBUG
-void SharedFunctionInfo::SharedFunctionInfoPrint() {
- HeapObject::PrintHeader("SharedFunctionInfo");
- PrintF(" - name: ");
- name()->ShortPrint();
- PrintF("\n - expected_nof_properties: %d", expected_nof_properties());
- PrintF("\n - instance class name = ");
- instance_class_name()->Print();
- PrintF("\n - code = ");
- code()->ShortPrint();
- PrintF("\n - source code = ");
- GetSourceCode()->ShortPrint();
+#ifdef OBJECT_PRINT
+void SharedFunctionInfo::SharedFunctionInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "SharedFunctionInfo");
+ PrintF(out, " - name: ");
+ name()->ShortPrint(out);
+ PrintF(out, "\n - expected_nof_properties: %d", expected_nof_properties());
+ PrintF(out, "\n - instance class name = ");
+ instance_class_name()->Print(out);
+ PrintF(out, "\n - code = ");
+ code()->ShortPrint(out);
+ PrintF(out, "\n - source code = ");
+ GetSourceCode()->ShortPrint(out);
// Script files are often large, hard to read.
- // PrintF("\n - script =");
- // script()->Print();
- PrintF("\n - function token position = %d", function_token_position());
- PrintF("\n - start position = %d", start_position());
- PrintF("\n - end position = %d", end_position());
- PrintF("\n - is expression = %d", is_expression());
- PrintF("\n - debug info = ");
- debug_info()->ShortPrint();
- PrintF("\n - length = %d", length());
- PrintF("\n - has_only_simple_this_property_assignments = %d",
+ // PrintF(out, "\n - script =");
+ // script()->Print(out);
+ PrintF(out, "\n - function token position = %d", function_token_position());
+ PrintF(out, "\n - start position = %d", start_position());
+ PrintF(out, "\n - end position = %d", end_position());
+ PrintF(out, "\n - is expression = %d", is_expression());
+ PrintF(out, "\n - debug info = ");
+ debug_info()->ShortPrint(out);
+ PrintF(out, "\n - length = %d", length());
+ PrintF(out, "\n - has_only_simple_this_property_assignments = %d",
has_only_simple_this_property_assignments());
- PrintF("\n - this_property_assignments = ");
- this_property_assignments()->ShortPrint();
- PrintF("\n");
+ PrintF(out, "\n - this_property_assignments = ");
+ this_property_assignments()->ShortPrint(out);
+ PrintF(out, "\n");
}
+#endif // OBJECT_PRINT
+
+#ifdef DEBUG
void SharedFunctionInfo::SharedFunctionInfoVerify() {
CHECK(IsSharedFunctionInfo());
VerifyObjectField(kNameOffset);
@@ -819,17 +874,21 @@ void SharedFunctionInfo::SharedFunctionInfoVerify() {
VerifyObjectField(kScriptOffset);
VerifyObjectField(kDebugInfoOffset);
}
+#endif // DEBUG
-void JSGlobalProxy::JSGlobalProxyPrint() {
- PrintF("global_proxy");
- JSObjectPrint();
- PrintF("context : ");
- context()->ShortPrint();
- PrintF("\n");
+#ifdef OBJECT_PRINT
+void JSGlobalProxy::JSGlobalProxyPrint(FILE* out) {
+ PrintF(out, "global_proxy");
+ JSObjectPrint(out);
+ PrintF(out, "context : ");
+ context()->ShortPrint(out);
+ PrintF(out, "\n");
}
+#endif // OBJECT_PRINT
+#ifdef DEBUG
void JSGlobalProxy::JSGlobalProxyVerify() {
CHECK(IsJSGlobalProxy());
JSObjectVerify();
@@ -839,17 +898,21 @@ void JSGlobalProxy::JSGlobalProxyVerify() {
CHECK(HasFastElements());
CHECK_EQ(0, FixedArray::cast(elements())->length());
}
+#endif // DEBUG
-void JSGlobalObject::JSGlobalObjectPrint() {
- PrintF("global ");
- JSObjectPrint();
- PrintF("global context : ");
- global_context()->ShortPrint();
- PrintF("\n");
+#ifdef OBJECT_PRINT
+void JSGlobalObject::JSGlobalObjectPrint(FILE* out) {
+ PrintF(out, "global ");
+ JSObjectPrint(out);
+ PrintF(out, "global context : ");
+ global_context()->ShortPrint(out);
+ PrintF(out, "\n");
}
+#endif // OBJECT_PRINT
+#ifdef DEBUG
void JSGlobalObject::JSGlobalObjectVerify() {
CHECK(IsJSGlobalObject());
JSObjectVerify();
@@ -859,14 +922,18 @@ void JSGlobalObject::JSGlobalObjectVerify() {
VerifyObjectField(i);
}
}
+#endif // DEBUG
-void JSBuiltinsObject::JSBuiltinsObjectPrint() {
- PrintF("builtins ");
- JSObjectPrint();
+#ifdef OBJECT_PRINT
+void JSBuiltinsObject::JSBuiltinsObjectPrint(FILE* out) {
+ PrintF(out, "builtins ");
+ JSObjectPrint(out);
}
+#endif // OBJECT_PRINT
+#ifdef DEBUG
void JSBuiltinsObject::JSBuiltinsObjectVerify() {
CHECK(IsJSBuiltinsObject());
JSObjectVerify();
@@ -897,21 +964,27 @@ void JSGlobalPropertyCell::JSGlobalPropertyCellVerify() {
CHECK(IsJSGlobalPropertyCell());
VerifyObjectField(kValueOffset);
}
+#endif // DEBUG
-void JSGlobalPropertyCell::JSGlobalPropertyCellPrint() {
- HeapObject::PrintHeader("JSGlobalPropertyCell");
+#ifdef OBJECT_PRINT
+void JSGlobalPropertyCell::JSGlobalPropertyCellPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "JSGlobalPropertyCell");
}
-void Code::CodePrint() {
- HeapObject::PrintHeader("Code");
+void Code::CodePrint(FILE* out) {
+ HeapObject::PrintHeader(out, "Code");
#ifdef ENABLE_DISASSEMBLER
- Disassemble(NULL);
+ if (FLAG_use_verbose_printer) {
+ Disassemble(NULL, out);
+ }
#endif
}
+#endif // OBJECT_PRINT
+#ifdef DEBUG
void Code::CodeVerify() {
CHECK(IsAligned(reinterpret_cast<intptr_t>(instruction_start()),
kCodeAlignment));
@@ -966,13 +1039,17 @@ void JSRegExp::JSRegExpVerify() {
break;
}
}
+#endif // DEBUG
-void Proxy::ProxyPrint() {
- PrintF("proxy to %p", proxy());
+#ifdef OBJECT_PRINT
+void Proxy::ProxyPrint(FILE* out) {
+ PrintF(out, "proxy to %p", proxy());
}
+#endif // OBJECT_PRINT
+#ifdef DEBUG
void Proxy::ProxyVerify() {
ASSERT(IsProxy());
}
@@ -986,38 +1063,50 @@ void AccessorInfo::AccessorInfoVerify() {
VerifyPointer(data());
VerifyPointer(flag());
}
+#endif // DEBUG
+
-void AccessorInfo::AccessorInfoPrint() {
- HeapObject::PrintHeader("AccessorInfo");
- PrintF("\n - getter: ");
- getter()->ShortPrint();
- PrintF("\n - setter: ");
- setter()->ShortPrint();
- PrintF("\n - name: ");
- name()->ShortPrint();
- PrintF("\n - data: ");
- data()->ShortPrint();
- PrintF("\n - flag: ");
- flag()->ShortPrint();
+#ifdef OBJECT_PRINT
+void AccessorInfo::AccessorInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "AccessorInfo");
+ PrintF(out, "\n - getter: ");
+ getter()->ShortPrint(out);
+ PrintF(out, "\n - setter: ");
+ setter()->ShortPrint(out);
+ PrintF(out, "\n - name: ");
+ name()->ShortPrint(out);
+ PrintF(out, "\n - data: ");
+ data()->ShortPrint(out);
+ PrintF(out, "\n - flag: ");
+ flag()->ShortPrint(out);
}
+#endif // OBJECT_PRINT
+
+#ifdef DEBUG
void AccessCheckInfo::AccessCheckInfoVerify() {
CHECK(IsAccessCheckInfo());
VerifyPointer(named_callback());
VerifyPointer(indexed_callback());
VerifyPointer(data());
}
+#endif // DEBUG
-void AccessCheckInfo::AccessCheckInfoPrint() {
- HeapObject::PrintHeader("AccessCheckInfo");
- PrintF("\n - named_callback: ");
- named_callback()->ShortPrint();
- PrintF("\n - indexed_callback: ");
- indexed_callback()->ShortPrint();
- PrintF("\n - data: ");
- data()->ShortPrint();
+
+#ifdef OBJECT_PRINT
+void AccessCheckInfo::AccessCheckInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "AccessCheckInfo");
+ PrintF(out, "\n - named_callback: ");
+ named_callback()->ShortPrint(out);
+ PrintF(out, "\n - indexed_callback: ");
+ indexed_callback()->ShortPrint(out);
+ PrintF(out, "\n - data: ");
+ data()->ShortPrint(out);
}
+#endif // OBJECT_PRINT
+
+#ifdef DEBUG
void InterceptorInfo::InterceptorInfoVerify() {
CHECK(IsInterceptorInfo());
VerifyPointer(getter());
@@ -1027,38 +1116,50 @@ void InterceptorInfo::InterceptorInfoVerify() {
VerifyPointer(enumerator());
VerifyPointer(data());
}
+#endif // DEBUG
+
-void InterceptorInfo::InterceptorInfoPrint() {
- HeapObject::PrintHeader("InterceptorInfo");
- PrintF("\n - getter: ");
- getter()->ShortPrint();
- PrintF("\n - setter: ");
- setter()->ShortPrint();
- PrintF("\n - query: ");
- query()->ShortPrint();
- PrintF("\n - deleter: ");
- deleter()->ShortPrint();
- PrintF("\n - enumerator: ");
- enumerator()->ShortPrint();
- PrintF("\n - data: ");
- data()->ShortPrint();
+#ifdef OBJECT_PRINT
+void InterceptorInfo::InterceptorInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "InterceptorInfo");
+ PrintF(out, "\n - getter: ");
+ getter()->ShortPrint(out);
+ PrintF(out, "\n - setter: ");
+ setter()->ShortPrint(out);
+ PrintF(out, "\n - query: ");
+ query()->ShortPrint(out);
+ PrintF(out, "\n - deleter: ");
+ deleter()->ShortPrint(out);
+ PrintF(out, "\n - enumerator: ");
+ enumerator()->ShortPrint(out);
+ PrintF(out, "\n - data: ");
+ data()->ShortPrint(out);
}
+#endif // OBJECT_PRINT
+
+#ifdef DEBUG
void CallHandlerInfo::CallHandlerInfoVerify() {
CHECK(IsCallHandlerInfo());
VerifyPointer(callback());
VerifyPointer(data());
}
+#endif // DEBUG
+
-void CallHandlerInfo::CallHandlerInfoPrint() {
- HeapObject::PrintHeader("CallHandlerInfo");
- PrintF("\n - callback: ");
- callback()->ShortPrint();
- PrintF("\n - data: ");
- data()->ShortPrint();
- PrintF("\n - call_stub_cache: ");
+#ifdef OBJECT_PRINT
+void CallHandlerInfo::CallHandlerInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "CallHandlerInfo");
+ PrintF(out, "\n - callback: ");
+ callback()->ShortPrint(out);
+ PrintF(out, "\n - data: ");
+ data()->ShortPrint(out);
+ PrintF(out, "\n - call_stub_cache: ");
}
+#endif // OBJECT_PRINT
+
+#ifdef DEBUG
void TemplateInfo::TemplateInfoVerify() {
VerifyPointer(tag());
VerifyPointer(property_list());
@@ -1078,81 +1179,106 @@ void FunctionTemplateInfo::FunctionTemplateInfoVerify() {
VerifyPointer(signature());
VerifyPointer(access_check_info());
}
+#endif // DEBUG
+
+
+#ifdef OBJECT_PRINT
+void FunctionTemplateInfo::FunctionTemplateInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "FunctionTemplateInfo");
+ PrintF(out, "\n - class name: ");
+ class_name()->ShortPrint(out);
+ PrintF(out, "\n - tag: ");
+ tag()->ShortPrint(out);
+ PrintF(out, "\n - property_list: ");
+ property_list()->ShortPrint(out);
+ PrintF(out, "\n - serial_number: ");
+ serial_number()->ShortPrint(out);
+ PrintF(out, "\n - call_code: ");
+ call_code()->ShortPrint(out);
+ PrintF(out, "\n - property_accessors: ");
+ property_accessors()->ShortPrint(out);
+ PrintF(out, "\n - prototype_template: ");
+ prototype_template()->ShortPrint(out);
+ PrintF(out, "\n - parent_template: ");
+ parent_template()->ShortPrint(out);
+ PrintF(out, "\n - named_property_handler: ");
+ named_property_handler()->ShortPrint(out);
+ PrintF(out, "\n - indexed_property_handler: ");
+ indexed_property_handler()->ShortPrint(out);
+ PrintF(out, "\n - instance_template: ");
+ instance_template()->ShortPrint(out);
+ PrintF(out, "\n - signature: ");
+ signature()->ShortPrint(out);
+ PrintF(out, "\n - access_check_info: ");
+ access_check_info()->ShortPrint(out);
+ PrintF(out, "\n - hidden_prototype: %s",
+ hidden_prototype() ? "true" : "false");
+ PrintF(out, "\n - undetectable: %s", undetectable() ? "true" : "false");
+ PrintF(out, "\n - need_access_check: %s",
+ needs_access_check() ? "true" : "false");
+}
+#endif // OBJECT_PRINT
-void FunctionTemplateInfo::FunctionTemplateInfoPrint() {
- HeapObject::PrintHeader("FunctionTemplateInfo");
- PrintF("\n - class name: ");
- class_name()->ShortPrint();
- PrintF("\n - tag: ");
- tag()->ShortPrint();
- PrintF("\n - property_list: ");
- property_list()->ShortPrint();
- PrintF("\n - serial_number: ");
- serial_number()->ShortPrint();
- PrintF("\n - call_code: ");
- call_code()->ShortPrint();
- PrintF("\n - property_accessors: ");
- property_accessors()->ShortPrint();
- PrintF("\n - prototype_template: ");
- prototype_template()->ShortPrint();
- PrintF("\n - parent_template: ");
- parent_template()->ShortPrint();
- PrintF("\n - named_property_handler: ");
- named_property_handler()->ShortPrint();
- PrintF("\n - indexed_property_handler: ");
- indexed_property_handler()->ShortPrint();
- PrintF("\n - instance_template: ");
- instance_template()->ShortPrint();
- PrintF("\n - signature: ");
- signature()->ShortPrint();
- PrintF("\n - access_check_info: ");
- access_check_info()->ShortPrint();
- PrintF("\n - hidden_prototype: %s", hidden_prototype() ? "true" : "false");
- PrintF("\n - undetectable: %s", undetectable() ? "true" : "false");
- PrintF("\n - need_access_check: %s", needs_access_check() ? "true" : "false");
-}
+#ifdef DEBUG
void ObjectTemplateInfo::ObjectTemplateInfoVerify() {
CHECK(IsObjectTemplateInfo());
TemplateInfoVerify();
VerifyPointer(constructor());
VerifyPointer(internal_field_count());
}
+#endif // DEBUG
-void ObjectTemplateInfo::ObjectTemplateInfoPrint() {
- HeapObject::PrintHeader("ObjectTemplateInfo");
- PrintF("\n - constructor: ");
- constructor()->ShortPrint();
- PrintF("\n - internal_field_count: ");
- internal_field_count()->ShortPrint();
+
+#ifdef OBJECT_PRINT
+void ObjectTemplateInfo::ObjectTemplateInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "ObjectTemplateInfo");
+ PrintF(out, "\n - constructor: ");
+ constructor()->ShortPrint(out);
+ PrintF(out, "\n - internal_field_count: ");
+ internal_field_count()->ShortPrint(out);
}
+#endif // OBJECT_PRINT
+
+#ifdef DEBUG
void SignatureInfo::SignatureInfoVerify() {
CHECK(IsSignatureInfo());
VerifyPointer(receiver());
VerifyPointer(args());
}
+#endif // DEBUG
+
-void SignatureInfo::SignatureInfoPrint() {
- HeapObject::PrintHeader("SignatureInfo");
- PrintF("\n - receiver: ");
- receiver()->ShortPrint();
- PrintF("\n - args: ");
- args()->ShortPrint();
+#ifdef OBJECT_PRINT
+void SignatureInfo::SignatureInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "SignatureInfo");
+ PrintF(out, "\n - receiver: ");
+ receiver()->ShortPrint(out);
+ PrintF(out, "\n - args: ");
+ args()->ShortPrint(out);
}
+#endif // OBJECT_PRINT
+
+#ifdef DEBUG
void TypeSwitchInfo::TypeSwitchInfoVerify() {
CHECK(IsTypeSwitchInfo());
VerifyPointer(types());
}
+#endif // DEBUG
+
-void TypeSwitchInfo::TypeSwitchInfoPrint() {
- HeapObject::PrintHeader("TypeSwitchInfo");
- PrintF("\n - types: ");
- types()->ShortPrint();
+#ifdef OBJECT_PRINT
+void TypeSwitchInfo::TypeSwitchInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "TypeSwitchInfo");
+ PrintF(out, "\n - types: ");
+ types()->ShortPrint(out);
}
+#endif // OBJECT_PRINT
+#ifdef DEBUG
void Script::ScriptVerify() {
CHECK(IsScript());
VerifyPointer(source());
@@ -1165,41 +1291,45 @@ void Script::ScriptVerify() {
VerifyPointer(line_ends());
VerifyPointer(id());
}
+#endif // DEBUG
-void Script::ScriptPrint() {
- HeapObject::PrintHeader("Script");
- PrintF("\n - source: ");
- source()->ShortPrint();
- PrintF("\n - name: ");
- name()->ShortPrint();
- PrintF("\n - line_offset: ");
- line_offset()->ShortPrint();
- PrintF("\n - column_offset: ");
- column_offset()->ShortPrint();
- PrintF("\n - type: ");
- type()->ShortPrint();
- PrintF("\n - id: ");
- id()->ShortPrint();
- PrintF("\n - data: ");
- data()->ShortPrint();
- PrintF("\n - context data: ");
- context_data()->ShortPrint();
- PrintF("\n - wrapper: ");
- wrapper()->ShortPrint();
- PrintF("\n - compilation type: ");
- compilation_type()->ShortPrint();
- PrintF("\n - line ends: ");
- line_ends()->ShortPrint();
- PrintF("\n - eval from shared: ");
- eval_from_shared()->ShortPrint();
- PrintF("\n - eval from instructions offset: ");
- eval_from_instructions_offset()->ShortPrint();
- PrintF("\n");
-}
+#ifdef OBJECT_PRINT
+void Script::ScriptPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "Script");
+ PrintF(out, "\n - source: ");
+ source()->ShortPrint(out);
+ PrintF(out, "\n - name: ");
+ name()->ShortPrint(out);
+ PrintF(out, "\n - line_offset: ");
+ line_offset()->ShortPrint(out);
+ PrintF(out, "\n - column_offset: ");
+ column_offset()->ShortPrint(out);
+ PrintF(out, "\n - type: ");
+ type()->ShortPrint(out);
+ PrintF(out, "\n - id: ");
+ id()->ShortPrint(out);
+ PrintF(out, "\n - data: ");
+ data()->ShortPrint(out);
+ PrintF(out, "\n - context data: ");
+ context_data()->ShortPrint(out);
+ PrintF(out, "\n - wrapper: ");
+ wrapper()->ShortPrint(out);
+ PrintF(out, "\n - compilation type: ");
+ compilation_type()->ShortPrint(out);
+ PrintF(out, "\n - line ends: ");
+ line_ends()->ShortPrint(out);
+ PrintF(out, "\n - eval from shared: ");
+ eval_from_shared()->ShortPrint(out);
+ PrintF(out, "\n - eval from instructions offset: ");
+ eval_from_instructions_offset()->ShortPrint(out);
+ PrintF(out, "\n");
+}
+#endif // OBJECT_PRINT
#ifdef ENABLE_DEBUGGER_SUPPORT
+#ifdef DEBUG
void DebugInfo::DebugInfoVerify() {
CHECK(IsDebugInfo());
VerifyPointer(shared());
@@ -1207,21 +1337,25 @@ void DebugInfo::DebugInfoVerify() {
VerifyPointer(code());
VerifyPointer(break_points());
}
+#endif // DEBUG
-void DebugInfo::DebugInfoPrint() {
- HeapObject::PrintHeader("DebugInfo");
- PrintF("\n - shared: ");
- shared()->ShortPrint();
- PrintF("\n - original_code: ");
- original_code()->ShortPrint();
- PrintF("\n - code: ");
- code()->ShortPrint();
- PrintF("\n - break_points: ");
- break_points()->Print();
+#ifdef OBJECT_PRINT
+void DebugInfo::DebugInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "DebugInfo");
+ PrintF(out, "\n - shared: ");
+ shared()->ShortPrint(out);
+ PrintF(out, "\n - original_code: ");
+ original_code()->ShortPrint(out);
+ PrintF(out, "\n - code: ");
+ code()->ShortPrint(out);
+ PrintF(out, "\n - break_points: ");
+ break_points()->Print(out);
}
+#endif // OBJECT_PRINT
+#ifdef DEBUG
void BreakPointInfo::BreakPointInfoVerify() {
CHECK(IsBreakPointInfo());
code_position()->SmiVerify();
@@ -1229,19 +1363,23 @@ void BreakPointInfo::BreakPointInfoVerify() {
statement_position()->SmiVerify();
VerifyPointer(break_point_objects());
}
+#endif // DEBUG
-void BreakPointInfo::BreakPointInfoPrint() {
- HeapObject::PrintHeader("BreakPointInfo");
- PrintF("\n - code_position: %d", code_position()->value());
- PrintF("\n - source_position: %d", source_position()->value());
- PrintF("\n - statement_position: %d", statement_position()->value());
- PrintF("\n - break_point_objects: ");
- break_point_objects()->ShortPrint();
+#ifdef OBJECT_PRINT
+void BreakPointInfo::BreakPointInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "BreakPointInfo");
+ PrintF(out, "\n - code_position: %d", code_position()->value());
+ PrintF(out, "\n - source_position: %d", source_position()->value());
+ PrintF(out, "\n - statement_position: %d", statement_position()->value());
+ PrintF(out, "\n - break_point_objects: ");
+ break_point_objects()->ShortPrint(out);
}
-#endif
+#endif // OBJECT_PRINT
+#endif // ENABLE_DEBUGGER_SUPPORT
+#ifdef DEBUG
void JSObject::IncrementSpillStatistics(SpillInformation* info) {
info->number_of_objects_++;
// Named properties
@@ -1324,20 +1462,24 @@ void JSObject::SpillInformation::Print() {
PrintF("\n");
}
+#endif // DEBUG
-void DescriptorArray::PrintDescriptors() {
- PrintF("Descriptor array %d\n", number_of_descriptors());
+#ifdef OBJECT_PRINT
+void DescriptorArray::PrintDescriptors(FILE* out) {
+ PrintF(out, "Descriptor array %d\n", number_of_descriptors());
for (int i = 0; i < number_of_descriptors(); i++) {
- PrintF(" %d: ", i);
+ PrintF(out, " %d: ", i);
Descriptor desc;
Get(i, &desc);
- desc.Print();
+ desc.Print(out);
}
- PrintF("\n");
+ PrintF(out, "\n");
}
+#endif // OBJECT_PRINT
+#ifdef DEBUG
bool DescriptorArray::IsSortedNoDuplicates() {
String* current_key = NULL;
uint32_t current = 0;
diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc
index 96f5c4b2470..ab2f9644705 100644
--- a/deps/v8/src/objects.cc
+++ b/deps/v8/src/objects.cc
@@ -553,11 +553,11 @@ Object* Object::GetPrototype() {
}
-void Object::ShortPrint() {
+void Object::ShortPrint(FILE* out) {
HeapStringAllocator allocator;
StringStream accumulator(&allocator);
ShortPrint(&accumulator);
- accumulator.OutputToStdOut();
+ accumulator.OutputToFile(out);
}
@@ -572,8 +572,8 @@ void Object::ShortPrint(StringStream* accumulator) {
}
-void Smi::SmiPrint() {
- PrintF("%d", value());
+void Smi::SmiPrint(FILE* out) {
+ PrintF(out, "%d", value());
}
@@ -587,8 +587,8 @@ void Failure::FailurePrint(StringStream* accumulator) {
}
-void Failure::FailurePrint() {
- PrintF("Failure(%p)", reinterpret_cast<void*>(value()));
+void Failure::FailurePrint(FILE* out) {
+ PrintF(out, "Failure(%p)", reinterpret_cast<void*>(value()));
}
@@ -1141,8 +1141,8 @@ Object* HeapNumber::HeapNumberToBoolean() {
}
-void HeapNumber::HeapNumberPrint() {
- PrintF("%.16g", Number());
+void HeapNumber::HeapNumberPrint(FILE* out) {
+ PrintF(out, "%.16g", Number());
}
@@ -5467,9 +5467,9 @@ Object* JSFunction::SetInstanceClassName(String* name) {
}
-void JSFunction::PrintName() {
+void JSFunction::PrintName(FILE* out) {
SmartPointer<char> name = shared()->DebugName()->ToCString();
- PrintF("%s", *name);
+ PrintF(out, "%s", *name);
}
@@ -5999,18 +5999,18 @@ Map* Code::FindFirstMap() {
#ifdef ENABLE_DISASSEMBLER
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
-void DeoptimizationInputData::DeoptimizationInputDataPrint() {
+void DeoptimizationInputData::DeoptimizationInputDataPrint(FILE* out) {
disasm::NameConverter converter;
int deopt_count = DeoptCount();
- PrintF("Deoptimization Input Data (deopt points = %d)\n", deopt_count);
+ PrintF(out, "Deoptimization Input Data (deopt points = %d)\n", deopt_count);
if (0 == deopt_count) return;
- PrintF("%6s %6s %6s %12s\n", "index", "ast id", "argc", "commands");
+ PrintF(out, "%6s %6s %6s %12s\n", "index", "ast id", "argc", "commands");
for (int i = 0; i < deopt_count; i++) {
int command_count = 0;
- PrintF("%6d %6d %6d",
+ PrintF(out, "%6d %6d %6d",
i, AstId(i)->value(), ArgumentsStackHeight(i)->value());
int translation_index = TranslationIndex(i)->value();
TranslationIterator iterator(TranslationByteArray(), translation_index);
@@ -6019,7 +6019,8 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
ASSERT(Translation::BEGIN == opcode);
int frame_count = iterator.Next();
if (FLAG_print_code_verbose) {
- PrintF(" %s {count=%d}\n", Translation::StringFor(opcode), frame_count);
+ PrintF(out, " %s {count=%d}\n", Translation::StringFor(opcode),
+ frame_count);
}
for (int i = 0; i < frame_count; ++i) {
@@ -6031,10 +6032,10 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
JSFunction::cast(LiteralArray()->get(function_id));
unsigned height = iterator.Next();
if (FLAG_print_code_verbose) {
- PrintF("%24s %s {ast_id=%d, function=",
+ PrintF(out, "%24s %s {ast_id=%d, function=",
"", Translation::StringFor(opcode), ast_id);
- function->PrintName();
- PrintF(", height=%u}\n", height);
+ function->PrintName(out);
+ PrintF(out, ", height=%u}\n", height);
}
// Size of translation is height plus all incoming arguments including
@@ -6044,13 +6045,13 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
for (int j = 0; j < size; ++j) {
opcode = static_cast<Translation::Opcode>(iterator.Next());
if (FLAG_print_code_verbose) {
- PrintF("%24s %s ", "", Translation::StringFor(opcode));
+ PrintF(out, "%24s %s ", "", Translation::StringFor(opcode));
}
if (opcode == Translation::DUPLICATE) {
opcode = static_cast<Translation::Opcode>(iterator.Next());
if (FLAG_print_code_verbose) {
- PrintF("%s ", Translation::StringFor(opcode));
+ PrintF(out, "%s ", Translation::StringFor(opcode));
}
--j; // Two commands share the same frame index.
}
@@ -6065,7 +6066,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
case Translation::REGISTER: {
int reg_code = iterator.Next();
if (FLAG_print_code_verbose) {
- PrintF("{input=%s}", converter.NameOfCPURegister(reg_code));
+ PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
}
break;
}
@@ -6073,7 +6074,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
case Translation::INT32_REGISTER: {
int reg_code = iterator.Next();
if (FLAG_print_code_verbose) {
- PrintF("{input=%s}", converter.NameOfCPURegister(reg_code));
+ PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
}
break;
}
@@ -6081,7 +6082,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
case Translation::DOUBLE_REGISTER: {
int reg_code = iterator.Next();
if (FLAG_print_code_verbose) {
- PrintF("{input=%s}",
+ PrintF(out, "{input=%s}",
DoubleRegister::AllocationIndexToString(reg_code));
}
break;
@@ -6090,7 +6091,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
case Translation::STACK_SLOT: {
int input_slot_index = iterator.Next();
if (FLAG_print_code_verbose) {
- PrintF("{input=%d}", input_slot_index);
+ PrintF(out, "{input=%d}", input_slot_index);
}
break;
}
@@ -6098,7 +6099,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
case Translation::INT32_STACK_SLOT: {
int input_slot_index = iterator.Next();
if (FLAG_print_code_verbose) {
- PrintF("{input=%d}", input_slot_index);
+ PrintF(out, "{input=%d}", input_slot_index);
}
break;
}
@@ -6106,7 +6107,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
case Translation::DOUBLE_STACK_SLOT: {
int input_slot_index = iterator.Next();
if (FLAG_print_code_verbose) {
- PrintF("{input=%d}", input_slot_index);
+ PrintF(out, "{input=%d}", input_slot_index);
}
break;
}
@@ -6114,7 +6115,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
case Translation::LITERAL: {
unsigned literal_index = iterator.Next();
if (FLAG_print_code_verbose) {
- PrintF("{literal_id=%u}", literal_index);
+ PrintF(out, "{literal_id=%u}", literal_index);
}
break;
}
@@ -6122,16 +6123,16 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
case Translation::ARGUMENTS_OBJECT:
break;
}
- if (FLAG_print_code_verbose) PrintF("\n");
+ if (FLAG_print_code_verbose) PrintF(out, "\n");
}
}
- if (!FLAG_print_code_verbose) PrintF(" %12d\n", command_count);
+ if (!FLAG_print_code_verbose) PrintF(out, " %12d\n", command_count);
}
}
-void DeoptimizationOutputData::DeoptimizationOutputDataPrint() {
- PrintF("Deoptimization Output Data (deopt points = %d)\n",
+void DeoptimizationOutputData::DeoptimizationOutputDataPrint(FILE* out) {
+ PrintF(out, "Deoptimization Output Data (deopt points = %d)\n",
this->DeoptPoints());
if (this->DeoptPoints() == 0) return;
@@ -6202,56 +6203,56 @@ const char* Code::PropertyType2String(PropertyType type) {
}
-void Code::Disassemble(const char* name) {
- PrintF("kind = %s\n", Kind2String(kind()));
+void Code::Disassemble(const char* name, FILE* out) {
+ PrintF(out, "kind = %s\n", Kind2String(kind()));
if (is_inline_cache_stub()) {
- PrintF("ic_state = %s\n", ICState2String(ic_state()));
- PrintF("ic_in_loop = %d\n", ic_in_loop() == IN_LOOP);
+ PrintF(out, "ic_state = %s\n", ICState2String(ic_state()));
+ PrintF(out, "ic_in_loop = %d\n", ic_in_loop() == IN_LOOP);
if (ic_state() == MONOMORPHIC) {
- PrintF("type = %s\n", PropertyType2String(type()));
+ PrintF(out, "type = %s\n", PropertyType2String(type()));
}
}
if ((name != NULL) && (name[0] != '\0')) {
- PrintF("name = %s\n", name);
+ PrintF(out, "name = %s\n", name);
}
if (kind() == OPTIMIZED_FUNCTION) {
- PrintF("stack_slots = %d\n", stack_slots());
+ PrintF(out, "stack_slots = %d\n", stack_slots());
}
- PrintF("Instructions (size = %d)\n", instruction_size());
- Disassembler::Decode(NULL, this);
- PrintF("\n");
+ PrintF(out, "Instructions (size = %d)\n", instruction_size());
+ Disassembler::Decode(out, this);
+ PrintF(out, "\n");
#ifdef DEBUG
if (kind() == FUNCTION) {
DeoptimizationOutputData* data =
DeoptimizationOutputData::cast(this->deoptimization_data());
- data->DeoptimizationOutputDataPrint();
+ data->DeoptimizationOutputDataPrint(out);
} else if (kind() == OPTIMIZED_FUNCTION) {
DeoptimizationInputData* data =
DeoptimizationInputData::cast(this->deoptimization_data());
- data->DeoptimizationInputDataPrint();
+ data->DeoptimizationInputDataPrint(out);
}
PrintF("\n");
#endif
if (kind() == OPTIMIZED_FUNCTION) {
SafepointTable table(this);
- PrintF("Safepoints (size = %u)\n", table.size());
+ PrintF(out, "Safepoints (size = %u)\n", table.size());
for (unsigned i = 0; i < table.length(); i++) {
unsigned pc_offset = table.GetPcOffset(i);
- PrintF("%p %4d ", (instruction_start() + pc_offset), pc_offset);
+ PrintF(out, "%p %4d ", (instruction_start() + pc_offset), pc_offset);
table.PrintEntry(i);
- PrintF(" (sp -> fp)");
+ PrintF(out, " (sp -> fp)");
int deoptimization_index = table.GetDeoptimizationIndex(i);
if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) {
- PrintF(" %6d", deoptimization_index);
+ PrintF(out, " %6d", deoptimization_index);
} else {
- PrintF(" <none>");
+ PrintF(out, " <none>");
}
- PrintF("\n");
+ PrintF(out, "\n");
}
- PrintF("\n");
+ PrintF(out, "\n");
} else if (kind() == FUNCTION) {
unsigned offset = stack_check_table_start();
// If there is no stack check table, the "table start" will at or after
@@ -6260,19 +6261,19 @@ void Code::Disassemble(const char* name) {
unsigned* address =
reinterpret_cast<unsigned*>(instruction_start() + offset);
unsigned length = address[0];
- PrintF("Stack checks (size = %u)\n", length);
- PrintF("ast_id pc_offset\n");
+ PrintF(out, "Stack checks (size = %u)\n", length);
+ PrintF(out, "ast_id pc_offset\n");
for (unsigned i = 0; i < length; ++i) {
unsigned index = (2 * i) + 1;
- PrintF("%6u %9u\n", address[index], address[index + 1]);
+ PrintF(out, "%6u %9u\n", address[index], address[index + 1]);
}
- PrintF("\n");
+ PrintF(out, "\n");
}
}
PrintF("RelocInfo (size = %d)\n", relocation_size());
- for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print();
- PrintF("\n");
+ for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out);
+ PrintF(out, "\n");
}
#endif // ENABLE_DISASSEMBLER
@@ -7421,22 +7422,22 @@ bool JSObject::ShouldConvertToFastElements() {
// class. This requires us to have the template functions put
// together, so even though this function belongs in objects-debug.cc,
// we keep it here instead to satisfy certain compilers.
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
template<typename Shape, typename Key>
-void Dictionary<Shape, Key>::Print() {
+void Dictionary<Shape, Key>::Print(FILE* out) {
int capacity = HashTable<Shape, Key>::Capacity();
for (int i = 0; i < capacity; i++) {
Object* k = HashTable<Shape, Key>::KeyAt(i);
if (HashTable<Shape, Key>::IsKey(k)) {
- PrintF(" ");
+ PrintF(out, " ");
if (k->IsString()) {
- String::cast(k)->StringPrint();
+ String::cast(k)->StringPrint(out);
} else {
- k->ShortPrint();
+ k->ShortPrint(out);
}
- PrintF(": ");
- ValueAt(i)->ShortPrint();
- PrintF("\n");
+ PrintF(out, ": ");
+ ValueAt(i)->ShortPrint(out);
+ PrintF(out, "\n");
}
}
}
diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h
index 498ee451bca..c5fda7d0385 100644
--- a/deps/v8/src/objects.h
+++ b/deps/v8/src/objects.h
@@ -607,10 +607,18 @@ class MaybeObject BASE_EMBEDDED {
return reinterpret_cast<Object*>(this);
}
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
// Prints this object with details.
- void Print();
- void PrintLn();
+ inline void Print() {
+ Print(stdout);
+ };
+ inline void PrintLn() {
+ PrintLn(stdout);
+ }
+ void Print(FILE* out);
+ void PrintLn(FILE* out);
+#endif
+#ifdef DEBUG
// Verifies the object.
void Verify();
#endif
@@ -762,7 +770,10 @@ class Object : public MaybeObject {
#endif
// Prints this object without details.
- void ShortPrint();
+ inline void ShortPrint() {
+ ShortPrint(stdout);
+ }
+ void ShortPrint(FILE* out);
// Prints this object without details to a message accumulator.
void ShortPrint(StringStream* accumulator);
@@ -801,7 +812,10 @@ class Smi: public Object {
static inline Smi* cast(Object* object);
// Dispatched behavior.
- void SmiPrint();
+ inline void SmiPrint() {
+ SmiPrint(stdout);
+ }
+ void SmiPrint(FILE* out);
void SmiPrint(StringStream* accumulator);
#ifdef DEBUG
void SmiVerify();
@@ -870,7 +884,10 @@ class Failure: public MaybeObject {
static inline Failure* cast(MaybeObject* object);
// Dispatched behavior.
- void FailurePrint();
+ inline void FailurePrint() {
+ FailurePrint(stdout);
+ }
+ void FailurePrint(FILE* out);
void FailurePrint(StringStream* accumulator);
#ifdef DEBUG
void FailureVerify();
@@ -1099,14 +1116,23 @@ class HeapObject: public Object {
// Dispatched behavior.
void HeapObjectShortPrint(StringStream* accumulator);
+#ifdef OBJECT_PRINT
+ inline void HeapObjectPrint() {
+ HeapObjectPrint(stdout);
+ }
+ void HeapObjectPrint(FILE* out);
+#endif
#ifdef DEBUG
- void HeapObjectPrint();
void HeapObjectVerify();
inline void VerifyObjectField(int offset);
inline void VerifySmiField(int offset);
+#endif
- void PrintHeader(const char* id);
+#ifdef OBJECT_PRINT
+ void PrintHeader(FILE* out, const char* id);
+#endif
+#ifdef DEBUG
// Verify a pointer is a valid HeapObject pointer that points to object
// areas in the heap.
static void VerifyHeapPointer(Object* p);
@@ -1189,7 +1215,10 @@ class HeapNumber: public HeapObject {
// Dispatched behavior.
Object* HeapNumberToBoolean();
- void HeapNumberPrint();
+ inline void HeapNumberPrint() {
+ HeapNumberPrint(stdout);
+ }
+ void HeapNumberPrint(FILE* out);
void HeapNumberPrint(StringStream* accumulator);
#ifdef DEBUG
void HeapNumberVerify();
@@ -1649,12 +1678,28 @@ class JSObject: public HeapObject {
// Dispatched behavior.
void JSObjectShortPrint(StringStream* accumulator);
+#ifdef OBJECT_PRINT
+ inline void JSObjectPrint() {
+ JSObjectPrint(stdout);
+ }
+ void JSObjectPrint(FILE* out);
+#endif
#ifdef DEBUG
- void JSObjectPrint();
void JSObjectVerify();
- void PrintProperties();
- void PrintElements();
+#endif
+#ifdef OBJECT_PRINT
+ inline void PrintProperties() {
+ PrintProperties(stdout);
+ }
+ void PrintProperties(FILE* out);
+
+ inline void PrintElements() {
+ PrintElements(stdout);
+ }
+ void PrintElements(FILE* out);
+#endif
+#ifdef DEBUG
// Structure for collecting spill information about JSObjects.
class SpillInformation {
public:
@@ -1689,7 +1734,7 @@ class JSObject: public HeapObject {
static const uint32_t kMaxGap = 1024;
static const int kMaxFastElementsLength = 5000;
static const int kInitialMaxFastElementArray = 100000;
- static const int kMaxFastProperties = 8;
+ static const int kMaxFastProperties = 12;
static const int kMaxInstanceSize = 255 * kPointerSize;
// When extending the backing storage for property values, we increase
// its size by more than the 1 entry necessary, so sequentially adding fields
@@ -1835,8 +1880,13 @@ class FixedArray: public HeapObject {
static const int kMaxLength = (kMaxSize - kHeaderSize) / kPointerSize;
// Dispatched behavior.
+#ifdef OBJECT_PRINT
+ inline void FixedArrayPrint() {
+ FixedArrayPrint(stdout);
+ }
+ void FixedArrayPrint(FILE* out);
+#endif
#ifdef DEBUG
- void FixedArrayPrint();
void FixedArrayVerify();
// Checks if two FixedArrays have identical contents.
bool IsEqualTo(FixedArray* other);
@@ -2012,10 +2062,15 @@ class DescriptorArray: public FixedArray {
static const int kEnumCacheBridgeCacheOffset =
kEnumCacheBridgeEnumOffset + kPointerSize;
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
// Print all the descriptors.
- void PrintDescriptors();
+ inline void PrintDescriptors() {
+ PrintDescriptors(stdout);
+ }
+ void PrintDescriptors(FILE* out);
+#endif
+#ifdef DEBUG
// Is the descriptor array sorted and without duplicates?
bool IsSortedNoDuplicates();
@@ -2396,8 +2451,11 @@ class Dictionary: public HashTable<Shape, Key> {
// Ensure enough space for n additional elements.
MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key);
-#ifdef DEBUG
- void Print();
+#ifdef OBJECT_PRINT
+ inline void Print() {
+ Print(stdout);
+ }
+ void Print(FILE* out);
#endif
// Returns the key (slow).
Object* SlowReverseLookup(Object* value);
@@ -2619,8 +2677,13 @@ class ByteArray: public HeapObject {
inline int ByteArraySize() {
return SizeFor(this->length());
}
+#ifdef OBJECT_PRINT
+ inline void ByteArrayPrint() {
+ ByteArrayPrint(stdout);
+ }
+ void ByteArrayPrint(FILE* out);
+#endif
#ifdef DEBUG
- void ByteArrayPrint();
void ByteArrayVerify();
#endif
@@ -2669,8 +2732,13 @@ class PixelArray: public HeapObject {
// Casting.
static inline PixelArray* cast(Object* obj);
+#ifdef OBJECT_PRINT
+ inline void PixelArrayPrint() {
+ PixelArrayPrint(stdout);
+ }
+ void PixelArrayPrint(FILE* out);
+#endif
#ifdef DEBUG
- void PixelArrayPrint();
void PixelArrayVerify();
#endif // DEBUG
@@ -2741,8 +2809,13 @@ class ExternalByteArray: public ExternalArray {
// Casting.
static inline ExternalByteArray* cast(Object* obj);
+#ifdef OBJECT_PRINT
+ inline void ExternalByteArrayPrint() {
+ ExternalByteArrayPrint(stdout);
+ }
+ void ExternalByteArrayPrint(FILE* out);
+#endif
#ifdef DEBUG
- void ExternalByteArrayPrint();
void ExternalByteArrayVerify();
#endif // DEBUG
@@ -2764,8 +2837,13 @@ class ExternalUnsignedByteArray: public ExternalArray {
// Casting.
static inline ExternalUnsignedByteArray* cast(Object* obj);
+#ifdef OBJECT_PRINT
+ inline void ExternalUnsignedByteArrayPrint() {
+ ExternalUnsignedByteArrayPrint(stdout);
+ }
+ void ExternalUnsignedByteArrayPrint(FILE* out);
+#endif
#ifdef DEBUG
- void ExternalUnsignedByteArrayPrint();
void ExternalUnsignedByteArrayVerify();
#endif // DEBUG
@@ -2787,8 +2865,13 @@ class ExternalShortArray: public ExternalArray {
// Casting.
static inline ExternalShortArray* cast(Object* obj);
+#ifdef OBJECT_PRINT
+ inline void ExternalShortArrayPrint() {
+ ExternalShortArrayPrint(stdout);
+ }
+ void ExternalShortArrayPrint(FILE* out);
+#endif
#ifdef DEBUG
- void ExternalShortArrayPrint();
void ExternalShortArrayVerify();
#endif // DEBUG
@@ -2810,8 +2893,13 @@ class ExternalUnsignedShortArray: public ExternalArray {
// Casting.
static inline ExternalUnsignedShortArray* cast(Object* obj);
+#ifdef OBJECT_PRINT
+ inline void ExternalUnsignedShortArrayPrint() {
+ ExternalUnsignedShortArrayPrint(stdout);
+ }
+ void ExternalUnsignedShortArrayPrint(FILE* out);
+#endif
#ifdef DEBUG
- void ExternalUnsignedShortArrayPrint();
void ExternalUnsignedShortArrayVerify();
#endif // DEBUG
@@ -2833,8 +2921,13 @@ class ExternalIntArray: public ExternalArray {
// Casting.
static inline ExternalIntArray* cast(Object* obj);
+#ifdef OBJECT_PRINT
+ inline void ExternalIntArrayPrint() {
+ ExternalIntArrayPrint(stdout);
+ }
+ void ExternalIntArrayPrint(FILE* out);
+#endif
#ifdef DEBUG
- void ExternalIntArrayPrint();
void ExternalIntArrayVerify();
#endif // DEBUG
@@ -2856,8 +2949,13 @@ class ExternalUnsignedIntArray: public ExternalArray {
// Casting.
static inline ExternalUnsignedIntArray* cast(Object* obj);
+#ifdef OBJECT_PRINT
+ inline void ExternalUnsignedIntArrayPrint() {
+ ExternalUnsignedIntArrayPrint(stdout);
+ }
+ void ExternalUnsignedIntArrayPrint(FILE* out);
+#endif
#ifdef DEBUG
- void ExternalUnsignedIntArrayPrint();
void ExternalUnsignedIntArrayVerify();
#endif // DEBUG
@@ -2879,8 +2977,13 @@ class ExternalFloatArray: public ExternalArray {
// Casting.
static inline ExternalFloatArray* cast(Object* obj);
+#ifdef OBJECT_PRINT
+ inline void ExternalFloatArrayPrint() {
+ ExternalFloatArrayPrint(stdout);
+ }
+ void ExternalFloatArrayPrint(FILE* out);
+#endif
#ifdef DEBUG
- void ExternalFloatArrayPrint();
void ExternalFloatArrayVerify();
#endif // DEBUG
@@ -2960,8 +3063,8 @@ class DeoptimizationInputData: public FixedArray {
// Casting.
static inline DeoptimizationInputData* cast(Object* obj);
-#ifdef DEBUG
- void DeoptimizationInputDataPrint();
+#ifdef OBJECT_PRINT
+ void DeoptimizationInputDataPrint(FILE* out);
#endif
private:
@@ -2999,8 +3102,8 @@ class DeoptimizationOutputData: public FixedArray {
// Casting.
static inline DeoptimizationOutputData* cast(Object* obj);
-#ifdef DEBUG
- void DeoptimizationOutputDataPrint();
+#ifdef OBJECT_PRINT
+ void DeoptimizationOutputDataPrint(FILE* out);
#endif
};
@@ -3049,7 +3152,10 @@ class Code: public HeapObject {
static const char* Kind2String(Kind kind);
static const char* ICState2String(InlineCacheState state);
static const char* PropertyType2String(PropertyType type);
- void Disassemble(const char* name);
+ inline void Disassemble(const char* name) {
+ Disassemble(name, stdout);
+ }
+ void Disassemble(const char* name, FILE* out);
#endif // ENABLE_DISASSEMBLER
// [instruction_size]: Size of the native instructions
@@ -3242,8 +3348,13 @@ class Code: public HeapObject {
template<typename StaticVisitor>
inline void CodeIterateBody();
+#ifdef OBJECT_PRINT
+ inline void CodePrint() {
+ CodePrint(stdout);
+ }
+ void CodePrint(FILE* out);
+#endif
#ifdef DEBUG
- void CodePrint();
void CodeVerify();
#endif
@@ -3531,8 +3642,13 @@ class Map: public HeapObject {
void ClearNonLiveTransitions(Object* real_prototype);
// Dispatched behavior.
+#ifdef OBJECT_PRINT
+ inline void MapPrint() {
+ MapPrint(stdout);
+ }
+ void MapPrint(FILE* out);
+#endif
#ifdef DEBUG
- void MapPrint();
void MapVerify();
void SharedMapVerify();
#endif
@@ -3688,8 +3804,13 @@ class Script: public Struct {
// resource is accessible. Otherwise, always return true.
inline bool HasValidSource();
+#ifdef OBJECT_PRINT
+ inline void ScriptPrint() {
+ ScriptPrint(stdout);
+ }
+ void ScriptPrint(FILE* out);
+#endif
#ifdef DEBUG
- void ScriptPrint();
void ScriptVerify();
#endif
@@ -4052,8 +4173,13 @@ class SharedFunctionInfo: public HeapObject {
// Dispatched behavior.
// Set max_length to -1 for unlimited length.
void SourceCodePrint(StringStream* accumulator, int max_length);
+#ifdef OBJECT_PRINT
+ inline void SharedFunctionInfoPrint() {
+ SharedFunctionInfoPrint(stdout);
+ }
+ void SharedFunctionInfoPrint(FILE* out);
+#endif
#ifdef DEBUG
- void SharedFunctionInfoPrint();
void SharedFunctionInfoVerify();
#endif
@@ -4285,7 +4411,10 @@ class JSFunction: public JSObject {
DECL_ACCESSORS(next_function_link, Object)
// Prints the name of the function using PrintF.
- void PrintName();
+ inline void PrintName() {
+ PrintName(stdout);
+ }
+ void PrintName(FILE* out);
// Casting.
static inline JSFunction* cast(Object* obj);
@@ -4295,8 +4424,13 @@ class JSFunction: public JSObject {
void JSFunctionIterateBody(int object_size, ObjectVisitor* v);
// Dispatched behavior.
+#ifdef OBJECT_PRINT
+ inline void JSFunctionPrint() {
+ JSFunctionPrint(stdout);
+ }
+ void JSFunctionPrint(FILE* out);
+#endif
#ifdef DEBUG
- void JSFunctionPrint();
void JSFunctionVerify();
#endif
@@ -4345,8 +4479,13 @@ class JSGlobalProxy : public JSObject {
static inline JSGlobalProxy* cast(Object* obj);
// Dispatched behavior.
+#ifdef OBJECT_PRINT
+ inline void JSGlobalProxyPrint() {
+ JSGlobalProxyPrint(stdout);
+ }
+ void JSGlobalProxyPrint(FILE* out);
+#endif
#ifdef DEBUG
- void JSGlobalProxyPrint();
void JSGlobalProxyVerify();
#endif
@@ -4416,8 +4555,13 @@ class JSGlobalObject: public GlobalObject {
static inline JSGlobalObject* cast(Object* obj);
// Dispatched behavior.
+#ifdef OBJECT_PRINT
+ inline void JSGlobalObjectPrint() {
+ JSGlobalObjectPrint(stdout);
+ }
+ void JSGlobalObjectPrint(FILE* out);
+#endif
#ifdef DEBUG
- void JSGlobalObjectPrint();
void JSGlobalObjectVerify();
#endif
@@ -4445,8 +4589,13 @@ class JSBuiltinsObject: public GlobalObject {
static inline JSBuiltinsObject* cast(Object* obj);
// Dispatched behavior.
+#ifdef OBJECT_PRINT
+ inline void JSBuiltinsObjectPrint() {
+ JSBuiltinsObjectPrint(stdout);
+ }
+ void JSBuiltinsObjectPrint(FILE* out);
+#endif
#ifdef DEBUG
- void JSBuiltinsObjectPrint();
void JSBuiltinsObjectVerify();
#endif
@@ -4483,8 +4632,13 @@ class JSValue: public JSObject {
static inline JSValue* cast(Object* obj);
// Dispatched behavior.
+#ifdef OBJECT_PRINT
+ inline void JSValuePrint() {
+ JSValuePrint(stdout);
+ }
+ void JSValuePrint(FILE* out);
+#endif
#ifdef DEBUG
- void JSValuePrint();
void JSValueVerify();
#endif
@@ -4673,8 +4827,13 @@ class CodeCache: public Struct {
static inline CodeCache* cast(Object* obj);
+#ifdef OBJECT_PRINT
+ inline void CodeCachePrint() {
+ CodeCachePrint(stdout);
+ }
+ void CodeCachePrint(FILE* out);
+#endif
#ifdef DEBUG
- void CodeCachePrint();
void CodeCacheVerify();
#endif
@@ -4975,8 +5134,13 @@ class String: public HeapObject {
// Dispatched behavior.
void StringShortPrint(StringStream* accumulator);
+#ifdef OBJECT_PRINT
+ inline void StringPrint() {
+ StringPrint(stdout);
+ }
+ void StringPrint(FILE* out);
+#endif
#ifdef DEBUG
- void StringPrint();
void StringVerify();
#endif
inline bool IsFlat();
@@ -5531,7 +5695,12 @@ class JSGlobalPropertyCell: public HeapObject {
#ifdef DEBUG
void JSGlobalPropertyCellVerify();
- void JSGlobalPropertyCellPrint();
+#endif
+#ifdef OBJECT_PRINT
+ inline void JSGlobalPropertyCellPrint() {
+ JSGlobalPropertyCellPrint(stdout);
+ }
+ void JSGlobalPropertyCellPrint(FILE* out);
#endif
// Layout description.
@@ -5566,8 +5735,13 @@ class Proxy: public HeapObject {
template<typename StaticVisitor>
inline void ProxyIterateBody();
+#ifdef OBJECT_PRINT
+ inline void ProxyPrint() {
+ ProxyPrint(stdout);
+ }
+ void ProxyPrint(FILE* out);
+#endif
#ifdef DEBUG
- void ProxyPrint();
void ProxyVerify();
#endif
@@ -5616,8 +5790,13 @@ class JSArray: public JSObject {
inline void EnsureSize(int minimum_size_of_backing_fixed_array);
// Dispatched behavior.
+#ifdef OBJECT_PRINT
+ inline void JSArrayPrint() {
+ JSArrayPrint(stdout);
+ }
+ void JSArrayPrint(FILE* out);
+#endif
#ifdef DEBUG
- void JSArrayPrint();
void JSArrayVerify();
#endif
@@ -5688,8 +5867,13 @@ class AccessorInfo: public Struct {
static inline AccessorInfo* cast(Object* obj);
+#ifdef OBJECT_PRINT
+ inline void AccessorInfoPrint() {
+ AccessorInfoPrint(stdout);
+ }
+ void AccessorInfoPrint(FILE* out);
+#endif
#ifdef DEBUG
- void AccessorInfoPrint();
void AccessorInfoVerify();
#endif
@@ -5719,8 +5903,13 @@ class AccessCheckInfo: public Struct {
static inline AccessCheckInfo* cast(Object* obj);
+#ifdef OBJECT_PRINT
+ inline void AccessCheckInfoPrint() {
+ AccessCheckInfoPrint(stdout);
+ }
+ void AccessCheckInfoPrint(FILE* out);
+#endif
#ifdef DEBUG
- void AccessCheckInfoPrint();
void AccessCheckInfoVerify();
#endif
@@ -5745,8 +5934,13 @@ class InterceptorInfo: public Struct {
static inline InterceptorInfo* cast(Object* obj);
+#ifdef OBJECT_PRINT
+ inline void InterceptorInfoPrint() {
+ InterceptorInfoPrint(stdout);
+ }
+ void InterceptorInfoPrint(FILE* out);
+#endif
#ifdef DEBUG
- void InterceptorInfoPrint();
void InterceptorInfoVerify();
#endif
@@ -5770,8 +5964,13 @@ class CallHandlerInfo: public Struct {
static inline CallHandlerInfo* cast(Object* obj);
+#ifdef OBJECT_PRINT
+ inline void CallHandlerInfoPrint() {
+ CallHandlerInfoPrint(stdout);
+ }
+ void CallHandlerInfoPrint(FILE* out);
+#endif
#ifdef DEBUG
- void CallHandlerInfoPrint();
void CallHandlerInfoVerify();
#endif
@@ -5827,8 +6026,13 @@ class FunctionTemplateInfo: public TemplateInfo {
static inline FunctionTemplateInfo* cast(Object* obj);
+#ifdef OBJECT_PRINT
+ inline void FunctionTemplateInfoPrint() {
+ FunctionTemplateInfoPrint(stdout);
+ }
+ void FunctionTemplateInfoPrint(FILE* out);
+#endif
#ifdef DEBUG
- void FunctionTemplateInfoPrint();
void FunctionTemplateInfoVerify();
#endif
@@ -5870,8 +6074,13 @@ class ObjectTemplateInfo: public TemplateInfo {
static inline ObjectTemplateInfo* cast(Object* obj);
+#ifdef OBJECT_PRINT
+ inline void ObjectTemplateInfoPrint() {
+ ObjectTemplateInfoPrint(stdout);
+ }
+ void ObjectTemplateInfoPrint(FILE* out);
+#endif
#ifdef DEBUG
- void ObjectTemplateInfoPrint();
void ObjectTemplateInfoVerify();
#endif
@@ -5889,8 +6098,13 @@ class SignatureInfo: public Struct {
static inline SignatureInfo* cast(Object* obj);
+#ifdef OBJECT_PRINT
+ inline void SignatureInfoPrint() {
+ SignatureInfoPrint(stdout);
+ }
+ void SignatureInfoPrint(FILE* out);
+#endif
#ifdef DEBUG
- void SignatureInfoPrint();
void SignatureInfoVerify();
#endif
@@ -5909,8 +6123,13 @@ class TypeSwitchInfo: public Struct {
static inline TypeSwitchInfo* cast(Object* obj);
+#ifdef OBJECT_PRINT
+ inline void TypeSwitchInfoPrint() {
+ TypeSwitchInfoPrint(stdout);
+ }
+ void TypeSwitchInfoPrint(FILE* out);
+#endif
#ifdef DEBUG
- void TypeSwitchInfoPrint();
void TypeSwitchInfoVerify();
#endif
@@ -5956,8 +6175,13 @@ class DebugInfo: public Struct {
static inline DebugInfo* cast(Object* obj);
+#ifdef OBJECT_PRINT
+ inline void DebugInfoPrint() {
+ DebugInfoPrint(stdout);
+ }
+ void DebugInfoPrint(FILE* out);
+#endif
#ifdef DEBUG
- void DebugInfoPrint();
void DebugInfoVerify();
#endif
@@ -6009,8 +6233,13 @@ class BreakPointInfo: public Struct {
static inline BreakPointInfo* cast(Object* obj);
+#ifdef OBJECT_PRINT
+ inline void BreakPointInfoPrint() {
+ BreakPointInfoPrint(stdout);
+ }
+ void BreakPointInfoPrint(FILE* out);
+#endif
#ifdef DEBUG
- void BreakPointInfoPrint();
void BreakPointInfoVerify();
#endif
diff --git a/deps/v8/src/parser.cc b/deps/v8/src/parser.cc
index 94ad57c9c28..08f77b8f304 100644
--- a/deps/v8/src/parser.cc
+++ b/deps/v8/src/parser.cc
@@ -3730,7 +3730,7 @@ RegExpParser::RegExpParser(FlatStringReader* in,
contains_anchor_(false),
is_scanned_for_captures_(false),
failed_(false) {
- Advance(1);
+ Advance();
}
@@ -3768,8 +3768,8 @@ void RegExpParser::Reset(int pos) {
void RegExpParser::Advance(int dist) {
- for (int i = 0; i < dist; i++)
- Advance();
+ next_pos_ += dist - 1;
+ Advance();
}
diff --git a/deps/v8/src/platform-nullos.cc b/deps/v8/src/platform-nullos.cc
index f34483dbc4d..72ea0e57673 100644
--- a/deps/v8/src/platform-nullos.cc
+++ b/deps/v8/src/platform-nullos.cc
@@ -128,6 +128,19 @@ void OS::VPrint(const char* format, va_list args) {
}
+void OS::FPrint(FILE* out, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ VFPrint(out, format, args);
+ va_end(args);
+}
+
+
+void OS::VFPrint(FILE* out, const char* format, va_list args) {
+ vfprintf(out, format, args);
+}
+
+
// Print error message to console.
void OS::PrintError(const char* format, ...) {
// Minimalistic implementation for bootstrapping.
diff --git a/deps/v8/src/platform-posix.cc b/deps/v8/src/platform-posix.cc
index c50d396ad38..ab5c0a37687 100644
--- a/deps/v8/src/platform-posix.cc
+++ b/deps/v8/src/platform-posix.cc
@@ -142,6 +142,23 @@ void OS::VPrint(const char* format, va_list args) {
}
+void OS::FPrint(FILE* out, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ VFPrint(out, format, args);
+ va_end(args);
+}
+
+
+void OS::VFPrint(FILE* out, const char* format, va_list args) {
+#if defined(ANDROID)
+ LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, format, args);
+#else
+ vfprintf(out, format, args);
+#endif
+}
+
+
void OS::PrintError(const char* format, ...) {
va_list args;
va_start(args, format);
@@ -173,7 +190,9 @@ int OS::VSNPrintF(Vector<char> str,
va_list args) {
int n = vsnprintf(str.start(), str.length(), format, args);
if (n < 0 || n >= str.length()) {
- str[str.length() - 1] = '\0';
+ // If the length is zero, the assignment fails.
+ if (str.length() > 0)
+ str[str.length() - 1] = '\0';
return -1;
} else {
return n;
@@ -204,6 +223,14 @@ class POSIXSocket : public Socket {
explicit POSIXSocket() {
// Create the socket.
socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (IsValid()) {
+ // Allow rapid reuse.
+ static const int kOn = 1;
+ int ret = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
+ &kOn, sizeof(kOn));
+ ASSERT(ret == 0);
+ USE(ret);
+ }
}
explicit POSIXSocket(int socket): socket_(socket) { }
virtual ~POSIXSocket() { Shutdown(); }
diff --git a/deps/v8/src/platform-win32.cc b/deps/v8/src/platform-win32.cc
index badc31beb3d..4438045eaf5 100644
--- a/deps/v8/src/platform-win32.cc
+++ b/deps/v8/src/platform-win32.cc
@@ -688,6 +688,19 @@ void OS::VPrint(const char* format, va_list args) {
}
+void OS::FPrint(FILE* out, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ VFPrint(out, format, args);
+ va_end(args);
+}
+
+
+void OS::VFPrint(FILE* out, const char* format, va_list args) {
+ VPrintHelper(out, format, args);
+}
+
+
// Print error message to console.
void OS::PrintError(const char* format, ...) {
va_list args;
@@ -716,7 +729,8 @@ int OS::VSNPrintF(Vector<char> str, const char* format, va_list args) {
// Make sure to zero-terminate the string if the output was
// truncated or if there was an error.
if (n < 0 || n >= str.length()) {
- str[str.length() - 1] = '\0';
+ if (str.length() > 0)
+ str[str.length() - 1] = '\0';
return -1;
} else {
return n;
diff --git a/deps/v8/src/platform.h b/deps/v8/src/platform.h
index 690f83c7fbb..bdfbbab6981 100644
--- a/deps/v8/src/platform.h
+++ b/deps/v8/src/platform.h
@@ -184,6 +184,10 @@ class OS {
static void Print(const char* format, ...);
static void VPrint(const char* format, va_list args);
+ // Print output to a file. This is mostly used for debugging output.
+ static void FPrint(FILE* out, const char* format, ...);
+ static void VFPrint(FILE* out, const char* format, va_list args);
+
// Print error output to console. This is mostly used for error message
// output. On platforms that has standard terminal output, the output
// should go to stderr.
diff --git a/deps/v8/src/profile-generator.cc b/deps/v8/src/profile-generator.cc
index 364f51d4f1c..34d18771cf1 100644
--- a/deps/v8/src/profile-generator.cc
+++ b/deps/v8/src/profile-generator.cc
@@ -2218,7 +2218,7 @@ void HeapSnapshotGenerator::SetGcRootsReference(Object* child_obj) {
void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) {
if (control_ == NULL) return;
- HeapIterator iterator(HeapIterator::kPreciseFiltering);
+ HeapIterator iterator(HeapIterator::kFilterUnreachable);
int objects_count = 0;
for (HeapObject* obj = iterator.next();
obj != NULL;
@@ -2342,8 +2342,6 @@ bool HeapSnapshotGenerator::SetEntriesDominators() {
ASSERT(dominators[i] != NULL);
ordered_entries[i]->set_dominator(dominators[i]);
}
- // For nodes unreachable from root, set dominator to itself.
- snapshot_->SetDominatorsToSelf();
return true;
}
@@ -2373,9 +2371,9 @@ bool HeapSnapshotGenerator::ApproximateRetainedSizes() {
bool HeapSnapshotGenerator::IterateAndExtractReferences() {
- HeapIterator iterator(HeapIterator::kPreciseFiltering);
+ HeapIterator iterator(HeapIterator::kFilterUnreachable);
bool interrupted = false;
- // Heap iteration with precise filtering must be finished in any case.
+ // Heap iteration with filtering must be finished in any case.
for (HeapObject* obj = iterator.next();
obj != NULL;
obj = iterator.next(), IncProgressCounter()) {
diff --git a/deps/v8/src/property.cc b/deps/v8/src/property.cc
index b579b687b66..96774333e81 100644
--- a/deps/v8/src/property.cc
+++ b/deps/v8/src/property.cc
@@ -31,62 +31,62 @@ namespace v8 {
namespace internal {
-#ifdef DEBUG
-void LookupResult::Print() {
+#ifdef OBJECT_PRINT
+void LookupResult::Print(FILE* out) {
if (!IsFound()) {
- PrintF("Not Found\n");
+ PrintF(out, "Not Found\n");
return;
}
- PrintF("LookupResult:\n");
- PrintF(" -cacheable = %s\n", IsCacheable() ? "true" : "false");
- PrintF(" -attributes = %x\n", GetAttributes());
+ PrintF(out, "LookupResult:\n");
+ PrintF(out, " -cacheable = %s\n", IsCacheable() ? "true" : "false");
+ PrintF(out, " -attributes = %x\n", GetAttributes());
switch (type()) {
case NORMAL:
- PrintF(" -type = normal\n");
- PrintF(" -entry = %d", GetDictionaryEntry());
+ PrintF(out, " -type = normal\n");
+ PrintF(out, " -entry = %d", GetDictionaryEntry());
break;
case MAP_TRANSITION:
- PrintF(" -type = map transition\n");
- PrintF(" -map:\n");
- GetTransitionMap()->Print();
- PrintF("\n");
+ PrintF(out, " -type = map transition\n");
+ PrintF(out, " -map:\n");
+ GetTransitionMap()->Print(out);
+ PrintF(out, "\n");
break;
case CONSTANT_FUNCTION:
- PrintF(" -type = constant function\n");
- PrintF(" -function:\n");
- GetConstantFunction()->Print();
- PrintF("\n");
+ PrintF(out, " -type = constant function\n");
+ PrintF(out, " -function:\n");
+ GetConstantFunction()->Print(out);
+ PrintF(out, "\n");
break;
case FIELD:
- PrintF(" -type = field\n");
- PrintF(" -index = %d", GetFieldIndex());
- PrintF("\n");
+ PrintF(out, " -type = field\n");
+ PrintF(out, " -index = %d", GetFieldIndex());
+ PrintF(out, "\n");
break;
case CALLBACKS:
- PrintF(" -type = call backs\n");
- PrintF(" -callback object:\n");
- GetCallbackObject()->Print();
+ PrintF(out, " -type = call backs\n");
+ PrintF(out, " -callback object:\n");
+ GetCallbackObject()->Print(out);
break;
case INTERCEPTOR:
- PrintF(" -type = lookup interceptor\n");
+ PrintF(out, " -type = lookup interceptor\n");
break;
case CONSTANT_TRANSITION:
- PrintF(" -type = constant property transition\n");
+ PrintF(out, " -type = constant property transition\n");
break;
case NULL_DESCRIPTOR:
- PrintF(" =type = null descriptor\n");
+ PrintF(out, " =type = null descriptor\n");
break;
}
}
-void Descriptor::Print() {
- PrintF("Descriptor ");
- GetKey()->ShortPrint();
- PrintF(" @ ");
- GetValue()->ShortPrint();
- PrintF(" %d\n", GetDetails().index());
+void Descriptor::Print(FILE* out) {
+ PrintF(out, "Descriptor ");
+ GetKey()->ShortPrint(out);
+ PrintF(out, " @ ");
+ GetValue()->ShortPrint(out);
+ PrintF(out, " %d\n", GetDetails().index());
}
diff --git a/deps/v8/src/property.h b/deps/v8/src/property.h
index 537b4e6e269..c39fe41e75d 100644
--- a/deps/v8/src/property.h
+++ b/deps/v8/src/property.h
@@ -60,8 +60,8 @@ class Descriptor BASE_EMBEDDED {
Object* GetValue() { return value_; }
PropertyDetails GetDetails() { return details_; }
-#ifdef DEBUG
- void Print();
+#ifdef OBJECT_PRINT
+ void Print(FILE* out);
#endif
void SetEnumerationIndex(int index) {
@@ -310,8 +310,8 @@ class LookupResult BASE_EMBEDDED {
return GetValue();
}
-#ifdef DEBUG
- void Print();
+#ifdef OBJECT_PRINT
+ void Print(FILE* out);
#endif
Object* GetValue() {
diff --git a/deps/v8/src/regexp.js b/deps/v8/src/regexp.js
index dd27266a947..0de66c644ed 100644
--- a/deps/v8/src/regexp.js
+++ b/deps/v8/src/regexp.js
@@ -32,7 +32,7 @@ const $RegExp = global.RegExp;
// A recursive descent parser for Patterns according to the grammar of
// ECMA-262 15.10.1, with deviations noted below.
-function DoConstructRegExp(object, pattern, flags, isConstructorCall) {
+function DoConstructRegExp(object, pattern, flags) {
// RegExp : Called as constructor; see ECMA-262, section 15.10.4.
if (IS_REGEXP(pattern)) {
if (!IS_UNDEFINED(flags)) {
@@ -80,7 +80,7 @@ function DoConstructRegExp(object, pattern, flags, isConstructorCall) {
function RegExpConstructor(pattern, flags) {
if (%_IsConstructCall()) {
- DoConstructRegExp(this, pattern, flags, true);
+ DoConstructRegExp(this, pattern, flags);
} else {
// RegExp : Called as function; see ECMA-262, section 15.10.3.1.
if (IS_REGEXP(pattern) && IS_UNDEFINED(flags)) {
@@ -104,9 +104,9 @@ function CompileRegExp(pattern, flags) {
// the empty string. For compatibility with JSC, we match their
// behavior.
if (IS_UNDEFINED(pattern) && %_ArgumentsLength() != 0) {
- DoConstructRegExp(this, 'undefined', flags, false);
+ DoConstructRegExp(this, 'undefined', flags);
} else {
- DoConstructRegExp(this, pattern, flags, false);
+ DoConstructRegExp(this, pattern, flags);
}
}
@@ -150,12 +150,12 @@ function BuildResultFromMatchInfo(lastMatchInfo, s) {
function RegExpExecNoTests(regexp, string, start) {
// Must be called with RegExp, string and positive integer as arguments.
- var matchInfo = DoRegExpExec(regexp, string, start);
- var result = null;
+ var matchInfo = %_RegExpExec(regexp, string, start, lastMatchInfo);
if (matchInfo !== null) {
- result = BuildResultFromMatchInfo(matchInfo, string);
+ lastMatchInfoOverride = null;
+ return BuildResultFromMatchInfo(matchInfo, string);
}
- return result;
+ return null;
}
@@ -261,11 +261,14 @@ function RegExpTest(string) {
%_StringCharCodeAt(this.source, 2) != 63) { // '?'
if (!%_ObjectEquals(regexp_key, this)) {
regexp_key = this;
- regexp_val = new $RegExp(this.source.substring(2, this.source.length),
- (this.ignoreCase ? 'i' : '')
- + (this.multiline ? 'm' : ''));
+ regexp_val = new $RegExp(SubString(this.source, 2, this.source.length),
+ (!this.ignoreCase
+ ? !this.multiline ? "" : "m"
+ : !this.multiline ? "i" : "im"));
+ }
+ if (%_RegExpExec(regexp_val, string, 0, lastMatchInfo) === null) {
+ return false;
}
- if (!regexp_val.test(string)) return false;
}
%_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, string, lastIndex]);
// matchIndices is either null or the lastMatchInfo array.
diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc
index 0fd2f8b4bfc..724a4363483 100644
--- a/deps/v8/src/runtime.cc
+++ b/deps/v8/src/runtime.cc
@@ -7204,7 +7204,7 @@ static MaybeObject* Runtime_StoreContextSlot(Arguments args) {
// extension object itself.
if ((attributes & READ_ONLY) == 0 ||
(context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) {
- Handle<Object> set = SetProperty(context_ext, name, value, attributes);
+ Handle<Object> set = SetProperty(context_ext, name, value, NONE);
if (set.is_null()) {
// Failure::Exception is converted to a null handle in the
// handle-based methods such as SetProperty. We therefore need
diff --git a/deps/v8/src/spaces.cc b/deps/v8/src/spaces.cc
index 8e9d889607f..fca10329696 100644
--- a/deps/v8/src/spaces.cc
+++ b/deps/v8/src/spaces.cc
@@ -364,15 +364,15 @@ void MemoryAllocator::TearDown() {
}
-void MemoryAllocator::FreeChunkTables(AtomicWord* array, int len, int level) {
+void MemoryAllocator::FreeChunkTables(uintptr_t* array, int len, int level) {
for (int i = 0; i < len; i++) {
if (array[i] != kUnusedChunkTableEntry) {
- AtomicWord* subarray = reinterpret_cast<AtomicWord*>(array[i]);
+ uintptr_t* subarray = reinterpret_cast<uintptr_t*>(array[i]);
if (level > 1) {
- Release_Store(&array[i], kUnusedChunkTableEntry);
+ array[i] = kUnusedChunkTableEntry;
FreeChunkTables(subarray, 1 << kChunkTableBitsPerLevel, level - 1);
} else {
- Release_Store(&array[i], kUnusedChunkTableEntry);
+ array[i] = kUnusedChunkTableEntry;
}
delete[] subarray;
}
@@ -822,7 +822,7 @@ void MemoryAllocator::AddToAllocatedChunks(Address addr, intptr_t size) {
void MemoryAllocator::AddChunkUsingAddress(uintptr_t chunk_start,
uintptr_t chunk_index_base) {
- AtomicWord* fine_grained = AllocatedChunksFinder(
+ uintptr_t* fine_grained = AllocatedChunksFinder(
chunk_table_,
chunk_index_base,
kChunkSizeLog2 + (kChunkTableLevels - 1) * kChunkTableBitsPerLevel,
@@ -830,7 +830,7 @@ void MemoryAllocator::AddChunkUsingAddress(uintptr_t chunk_start,
int index = FineGrainedIndexForAddress(chunk_index_base);
if (fine_grained[index] != kUnusedChunkTableEntry) index++;
ASSERT(fine_grained[index] == kUnusedChunkTableEntry);
- Release_Store(&fine_grained[index], chunk_start);
+ fine_grained[index] = chunk_start;
}
@@ -845,7 +845,7 @@ void MemoryAllocator::RemoveFromAllocatedChunks(Address addr, intptr_t size) {
void MemoryAllocator::RemoveChunkFoundUsingAddress(
uintptr_t chunk_start,
uintptr_t chunk_index_base) {
- AtomicWord* fine_grained = AllocatedChunksFinder(
+ uintptr_t* fine_grained = AllocatedChunksFinder(
chunk_table_,
chunk_index_base,
kChunkSizeLog2 + (kChunkTableLevels - 1) * kChunkTableBitsPerLevel,
@@ -854,22 +854,23 @@ void MemoryAllocator::RemoveChunkFoundUsingAddress(
ASSERT(fine_grained != kUnusedChunkTableEntry);
int index = FineGrainedIndexForAddress(chunk_index_base);
ASSERT(fine_grained[index] != kUnusedChunkTableEntry);
- if (fine_grained[index] != static_cast<AtomicWord>(chunk_start)) {
+ if (fine_grained[index] != chunk_start) {
index++;
- ASSERT(fine_grained[index] == static_cast<AtomicWord>(chunk_start));
- Release_Store(&fine_grained[index], kUnusedChunkTableEntry);
+ ASSERT(fine_grained[index] == chunk_start);
+ fine_grained[index] = kUnusedChunkTableEntry;
} else {
- Release_Store(&fine_grained[index], fine_grained[index + 1]);
- // Here for a moment the two entries are duplicates, but the reader can
- // handle that.
- NoBarrier_Store(&fine_grained[index + 1], kUnusedChunkTableEntry);
+ // If only one of the entries is used it must be the first, since
+ // InAllocatedChunks relies on that. Move things around so that this is
+ // the case.
+ fine_grained[index] = fine_grained[index + 1];
+ fine_grained[index + 1] = kUnusedChunkTableEntry;
}
}
bool MemoryAllocator::InAllocatedChunks(Address addr) {
uintptr_t int_address = reinterpret_cast<uintptr_t>(addr);
- AtomicWord* fine_grained = AllocatedChunksFinder(
+ uintptr_t* fine_grained = AllocatedChunksFinder(
chunk_table_,
int_address,
kChunkSizeLog2 + (kChunkTableLevels - 1) * kChunkTableBitsPerLevel,
@@ -877,21 +878,18 @@ bool MemoryAllocator::InAllocatedChunks(Address addr) {
if (fine_grained == NULL) return false;
int index = FineGrainedIndexForAddress(int_address);
if (fine_grained[index] == kUnusedChunkTableEntry) return false;
- uintptr_t entry = static_cast<uintptr_t>(fine_grained[index]);
+ uintptr_t entry = fine_grained[index];
if (entry <= int_address && entry + kChunkSize > int_address) return true;
index++;
if (fine_grained[index] == kUnusedChunkTableEntry) return false;
- entry = static_cast<uintptr_t>(fine_grained[index]);
- // At this point it would seem that we must have a hit, but there is a small
- // window during RemoveChunkFoundUsingAddress where the two entries are
- // duplicates and we have to handle that.
+ entry = fine_grained[index];
if (entry <= int_address && entry + kChunkSize > int_address) return true;
return false;
}
-AtomicWord* MemoryAllocator::AllocatedChunksFinder(
- AtomicWord* table,
+uintptr_t* MemoryAllocator::AllocatedChunksFinder(
+ uintptr_t* table,
uintptr_t address,
int bit_position,
CreateTables create_as_needed) {
@@ -906,8 +904,8 @@ AtomicWord* MemoryAllocator::AllocatedChunksFinder(
address & ((V8_INTPTR_C(1) << bit_position) - 1);
ASSERT((table == chunk_table_ && index < kChunkTableTopLevelEntries) ||
(table != chunk_table_ && index < 1 << kChunkTableBitsPerLevel));
- AtomicWord* more_fine_grained_table =
- reinterpret_cast<AtomicWord*>(table[index]);
+ uintptr_t* more_fine_grained_table =
+ reinterpret_cast<uintptr_t*>(table[index]);
if (more_fine_grained_table == kUnusedChunkTableEntry) {
if (create_as_needed == kDontCreateTables) return NULL;
int words_needed = 1 << kChunkTableBitsPerLevel;
@@ -915,12 +913,11 @@ AtomicWord* MemoryAllocator::AllocatedChunksFinder(
words_needed =
(1 << kChunkTableBitsPerLevel) * kChunkTableFineGrainedWordsPerEntry;
}
- more_fine_grained_table = new AtomicWord[words_needed];
+ more_fine_grained_table = new uintptr_t[words_needed];
for (int i = 0; i < words_needed; i++) {
more_fine_grained_table[i] = kUnusedChunkTableEntry;
}
- Release_Store(&table[index],
- reinterpret_cast<AtomicWord>(more_fine_grained_table));
+ table[index] = reinterpret_cast<uintptr_t>(more_fine_grained_table);
}
return AllocatedChunksFinder(
more_fine_grained_table,
@@ -930,7 +927,7 @@ AtomicWord* MemoryAllocator::AllocatedChunksFinder(
}
-AtomicWord MemoryAllocator::chunk_table_[kChunkTableTopLevelEntries];
+uintptr_t MemoryAllocator::chunk_table_[kChunkTableTopLevelEntries];
// -----------------------------------------------------------------------------
diff --git a/deps/v8/src/spaces.h b/deps/v8/src/spaces.h
index 2c17ef00887..4f2d07b0c81 100644
--- a/deps/v8/src/spaces.h
+++ b/deps/v8/src/spaces.h
@@ -28,7 +28,6 @@
#ifndef V8_SPACES_H_
#define V8_SPACES_H_
-#include "atomicops.h"
#include "list-inl.h"
#include "log.h"
@@ -688,7 +687,7 @@ class MemoryAllocator : public AllStatic {
// The chunks are not chunk-size aligned so for a given chunk-sized area of
// memory there can be two chunks that cover it.
static const int kChunkTableFineGrainedWordsPerEntry = 2;
- static const AtomicWord kUnusedChunkTableEntry = 0;
+ static const uintptr_t kUnusedChunkTableEntry = 0;
// Maximum space size in bytes.
static intptr_t capacity_;
@@ -696,7 +695,7 @@ class MemoryAllocator : public AllStatic {
static intptr_t capacity_executable_;
// Top level table to track whether memory is part of a chunk or not.
- static AtomicWord chunk_table_[kChunkTableTopLevelEntries];
+ static uintptr_t chunk_table_[kChunkTableTopLevelEntries];
// Allocated space size in bytes.
static intptr_t size_;
@@ -766,11 +765,11 @@ class MemoryAllocator : public AllStatic {
// Controls whether the lookup creates intermediate levels of tables as
// needed.
enum CreateTables { kDontCreateTables, kCreateTablesAsNeeded };
- static AtomicWord* AllocatedChunksFinder(AtomicWord* table,
- uintptr_t address,
- int bit_position,
- CreateTables create_as_needed);
- static void FreeChunkTables(AtomicWord* array, int length, int level);
+ static uintptr_t* AllocatedChunksFinder(uintptr_t* table,
+ uintptr_t address,
+ int bit_position,
+ CreateTables create_as_needed);
+ static void FreeChunkTables(uintptr_t* array, int length, int level);
static int FineGrainedIndexForAddress(uintptr_t address) {
int index = ((address >> kChunkSizeLog2) &
((1 << kChunkTableBitsPerLevel) - 1));
diff --git a/deps/v8/src/string-stream.cc b/deps/v8/src/string-stream.cc
index d1859a20fa9..7abd1bbe858 100644
--- a/deps/v8/src/string-stream.cc
+++ b/deps/v8/src/string-stream.cc
@@ -264,7 +264,7 @@ void StringStream::Log() {
}
-void StringStream::OutputToStdOut() {
+void StringStream::OutputToFile(FILE* out) {
// Dump the output to stdout, but make sure to break it up into
// manageable chunks to avoid losing parts of the output in the OS
// printing code. This is a problem on Windows in particular; see
@@ -273,10 +273,10 @@ void StringStream::OutputToStdOut() {
for (unsigned next; (next = position + 2048) < length_; position = next) {
char save = buffer_[next];
buffer_[next] = '\0';
- internal::PrintF("%s", &buffer_[position]);
+ internal::PrintF(out, "%s", &buffer_[position]);
buffer_[next] = save;
}
- internal::PrintF("%s", &buffer_[position]);
+ internal::PrintF(out, "%s", &buffer_[position]);
}
diff --git a/deps/v8/src/string-stream.h b/deps/v8/src/string-stream.h
index b74c7939588..b3f2e0d76e8 100644
--- a/deps/v8/src/string-stream.h
+++ b/deps/v8/src/string-stream.h
@@ -138,7 +138,8 @@ class StringStream {
FmtElm arg3);
// Getting the message out.
- void OutputToStdOut();
+ void OutputToFile(FILE* out);
+ void OutputToStdOut() { OutputToFile(stdout); }
void Log();
Handle<String> ToString();
SmartPointer<const char> ToCString() const;
diff --git a/deps/v8/src/string.js b/deps/v8/src/string.js
index 6d4e0c18f7d..95275995e13 100644
--- a/deps/v8/src/string.js
+++ b/deps/v8/src/string.js
@@ -159,7 +159,7 @@ function StringLocaleCompare(other) {
function StringMatch(regexp) {
var subject = TO_STRING_INLINE(this);
if (IS_REGEXP(regexp)) {
- if (!regexp.global) return regexp.exec(subject);
+ if (!regexp.global) return RegExpExecNoTests(regexp, subject, 0);
%_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]);
// lastMatchInfo is defined in regexp.js.
return %StringMatch(subject, regexp, lastMatchInfo);
@@ -245,17 +245,18 @@ function StringReplace(search, replace) {
// Expand the $-expressions in the string and return a new string with
// the result.
function ExpandReplacement(string, subject, matchInfo, builder) {
+ var length = string.length;
+ var builder_elements = builder.elements;
var next = %StringIndexOf(string, '$', 0);
if (next < 0) {
- builder.add(string);
+ if (length > 0) builder_elements.push(string);
return;
}
// Compute the number of captures; see ECMA-262, 15.5.4.11, p. 102.
var m = NUMBER_OF_CAPTURES(matchInfo) >> 1; // Includes the match.
- if (next > 0) builder.add(SubString(string, 0, next));
- var length = string.length;
+ if (next > 0) builder_elements.push(SubString(string, 0, next));
while (true) {
var expansion = '$';
@@ -264,7 +265,7 @@ function ExpandReplacement(string, subject, matchInfo, builder) {
var peek = %_StringCharCodeAt(string, position);
if (peek == 36) { // $$
++position;
- builder.add('$');
+ builder_elements.push('$');
} else if (peek == 38) { // $& - match
++position;
builder.addSpecialSlice(matchInfo[CAPTURE0],
@@ -301,14 +302,14 @@ function ExpandReplacement(string, subject, matchInfo, builder) {
// digit capture references, we can only enter here when a
// single digit capture reference is outside the range of
// captures.
- builder.add('$');
+ builder_elements.push('$');
--position;
}
} else {
- builder.add('$');
+ builder_elements.push('$');
}
} else {
- builder.add('$');
+ builder_elements.push('$');
}
// Go the the next $ in the string.
@@ -318,13 +319,15 @@ function ExpandReplacement(string, subject, matchInfo, builder) {
// haven't reached the end, we need to append the suffix.
if (next < 0) {
if (position < length) {
- builder.add(SubString(string, position, length));
+ builder_elements.push(SubString(string, position, length));
}
return;
}
// Append substring between the previous and the next $ character.
- builder.add(SubString(string, position, next));
+ if (next > position) {
+ builder_elements.push(SubString(string, position, next));
+ }
}
};
@@ -559,23 +562,22 @@ function StringSplit(separator, limit) {
var currentIndex = 0;
var startIndex = 0;
+ var startMatch = 0;
var result = [];
outer_loop:
while (true) {
if (startIndex === length) {
- result.push(subject.slice(currentIndex, length));
+ result.push(SubString(subject, currentIndex, length));
break;
}
- var matchInfo = splitMatch(separator, subject, currentIndex, startIndex);
-
- if (IS_NULL(matchInfo)) {
- result.push(subject.slice(currentIndex, length));
+ var matchInfo = DoRegExpExec(separator, subject, startIndex);
+ if (matchInfo == null || length === (startMatch = matchInfo[CAPTURE0])) {
+ result.push(SubString(subject, currentIndex, length));
break;
}
-
var endIndex = matchInfo[CAPTURE1];
// We ignore a zero-length match at the currentIndex.
@@ -584,7 +586,12 @@ function StringSplit(separator, limit) {
continue;
}
- result.push(SubString(subject, currentIndex, matchInfo[CAPTURE0]));
+ if (currentIndex + 1 == startMatch) {
+ result.push(%_StringCharAt(subject, currentIndex));
+ } else {
+ result.push(%_SubString(subject, currentIndex, startMatch));
+ }
+
if (result.length === limit) break;
var matchinfo_len = NUMBER_OF_CAPTURES(matchInfo) + REGEXP_FIRST_CAPTURE;
@@ -609,19 +616,6 @@ function StringSplit(separator, limit) {
}
-// ECMA-262 section 15.5.4.14
-// Helper function used by split. This version returns the matchInfo
-// instead of allocating a new array with basically the same information.
-function splitMatch(separator, subject, current_index, start_index) {
- var matchInfo = DoRegExpExec(separator, subject, start_index);
- if (matchInfo == null) return null;
- // Section 15.5.4.14 paragraph two says that we do not allow zero length
- // matches at the end of the string.
- if (matchInfo[CAPTURE0] === subject.length) return null;
- return matchInfo;
-}
-
-
// ECMA-262 section 15.5.4.15
function StringSubstring(start, end) {
var s = TO_STRING_INLINE(this);
@@ -844,24 +838,21 @@ function ReplaceResultBuilder(str) {
ReplaceResultBuilder.prototype.add = function(str) {
str = TO_STRING_INLINE(str);
- if (str.length > 0) {
- var elements = this.elements;
- elements[elements.length] = str;
- }
+ if (str.length > 0) this.elements.push(str);
}
ReplaceResultBuilder.prototype.addSpecialSlice = function(start, end) {
var len = end - start;
if (start < 0 || len <= 0) return;
- var elements = this.elements;
if (start < 0x80000 && len < 0x800) {
- elements[elements.length] = (start << 11) | len;
+ this.elements.push((start << 11) | len);
} else {
// 0 < len <= String::kMaxLength and Smi::kMaxValue >= String::kMaxLength,
// so -len is a smi.
- elements[elements.length] = -len;
- elements[elements.length] = start;
+ var elements = this.elements;
+ elements.push(-len);
+ elements.push(start);
}
}
diff --git a/deps/v8/src/utils.cc b/deps/v8/src/utils.cc
index 2c234bb7622..d0ec4ef5286 100644
--- a/deps/v8/src/utils.cc
+++ b/deps/v8/src/utils.cc
@@ -45,8 +45,16 @@ void PrintF(const char* format, ...) {
}
-void Flush() {
- fflush(stdout);
+void PrintF(FILE* out, const char* format, ...) {
+ va_list arguments;
+ va_start(arguments, format);
+ OS::VFPrint(out, format, arguments);
+ va_end(arguments);
+}
+
+
+void Flush(FILE* out) {
+ fflush(out);
}
diff --git a/deps/v8/src/v8-counters.h b/deps/v8/src/v8-counters.h
index a5cf42e9057..fa5d581eab0 100644
--- a/deps/v8/src/v8-counters.h
+++ b/deps/v8/src/v8-counters.h
@@ -28,7 +28,9 @@
#ifndef V8_V8_COUNTERS_H_
#define V8_V8_COUNTERS_H_
+#include "allocation.h"
#include "counters.h"
+#include "v8globals.h"
namespace v8 {
namespace internal {
diff --git a/deps/v8/src/v8utils.h b/deps/v8/src/v8utils.h
index 59b3898bda1..b000d144099 100644
--- a/deps/v8/src/v8utils.h
+++ b/deps/v8/src/v8utils.h
@@ -43,18 +43,26 @@ namespace internal {
// so it works on MacOSX.
#if defined(__MACH__) && defined(__APPLE__)
#define PRINTF_CHECKING
+#define FPRINTF_CHECKING
#else // MacOsX.
#define PRINTF_CHECKING __attribute__ ((format (printf, 1, 2)))
+#define FPRINTF_CHECKING __attribute__ ((format (printf, 2, 3)))
#endif
#else
#define PRINTF_CHECKING
+#define FPRINTF_CHECKING
#endif
// Our version of printf().
void PRINTF_CHECKING PrintF(const char* format, ...);
+void FPRINTF_CHECKING PrintF(FILE* out, const char* format, ...);
// Our version of fflush.
-void Flush();
+void Flush(FILE* out);
+
+inline void Flush() {
+ Flush(stdout);
+}
// Read a line of characters after printing the prompt to stdout. The resulting
diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc
index 60e61b1164c..d2c0960508d 100644
--- a/deps/v8/src/version.cc
+++ b/deps/v8/src/version.cc
@@ -34,8 +34,8 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3
#define MINOR_VERSION 0
-#define BUILD_NUMBER 3
-#define PATCH_LEVEL 0
+#define BUILD_NUMBER 4
+#define PATCH_LEVEL 1
#define CANDIDATE_VERSION false
// Define SONAME to have the SCons build the put a specific SONAME into the
diff --git a/deps/v8/src/x64/codegen-x64.cc b/deps/v8/src/x64/codegen-x64.cc
index 6c8b3339846..9a255722981 100644
--- a/deps/v8/src/x64/codegen-x64.cc
+++ b/deps/v8/src/x64/codegen-x64.cc
@@ -6784,9 +6784,9 @@ void CodeGenerator::GenerateSwapElements(ZoneList<Expression*>* args) {
// Check that both indices are valid.
__ movq(tmp2.reg(), FieldOperand(object.reg(), JSArray::kLengthOffset));
- __ cmpl(tmp2.reg(), index1.reg());
+ __ SmiCompare(tmp2.reg(), index1.reg());
deferred->Branch(below_equal);
- __ cmpl(tmp2.reg(), index2.reg());
+ __ SmiCompare(tmp2.reg(), index2.reg());
deferred->Branch(below_equal);
// Bring addresses into index1 and index2.
diff --git a/deps/v8/test/cctest/test-heap.cc b/deps/v8/test/cctest/test-heap.cc
index aa5fe59bd99..a23ee171f2a 100644
--- a/deps/v8/test/cctest/test-heap.cc
+++ b/deps/v8/test/cctest/test-heap.cc
@@ -1216,7 +1216,7 @@ TEST(TestInternalWeakListsTraverseWithGC) {
TEST(TestSizeOfObjectsVsHeapIteratorPrecision) {
InitializeVM();
intptr_t size_of_objects_1 = Heap::SizeOfObjects();
- HeapIterator iterator(HeapIterator::kPreciseFiltering);
+ HeapIterator iterator(HeapIterator::kFilterFreeListNodes);
intptr_t size_of_objects_2 = 0;
for (HeapObject* obj = iterator.next();
obj != NULL;
@@ -1240,3 +1240,65 @@ TEST(TestSizeOfObjectsVsHeapIteratorPrecision) {
CHECK_GT(size_of_objects_2 / 100, delta);
}
}
+
+
+class HeapIteratorTestHelper {
+ public:
+ HeapIteratorTestHelper(Object* a, Object* b)
+ : a_(a), b_(b), a_found_(false), b_found_(false) {}
+ bool a_found() { return a_found_; }
+ bool b_found() { return b_found_; }
+ void IterateHeap(HeapIterator::HeapObjectsFiltering mode) {
+ HeapIterator iterator(mode);
+ for (HeapObject* obj = iterator.next();
+ obj != NULL;
+ obj = iterator.next()) {
+ if (obj == a_)
+ a_found_ = true;
+ else if (obj == b_)
+ b_found_ = true;
+ }
+ }
+ private:
+ Object* a_;
+ Object* b_;
+ bool a_found_;
+ bool b_found_;
+};
+
+TEST(HeapIteratorFilterUnreachable) {
+ InitializeVM();
+ v8::HandleScope scope;
+ CompileRun("a = {}; b = {};");
+ v8::Handle<Object> a(Top::context()->global()->GetProperty(
+ *Factory::LookupAsciiSymbol("a"))->ToObjectChecked());
+ v8::Handle<Object> b(Top::context()->global()->GetProperty(
+ *Factory::LookupAsciiSymbol("b"))->ToObjectChecked());
+ CHECK_NE(*a, *b);
+ {
+ HeapIteratorTestHelper helper(*a, *b);
+ helper.IterateHeap(HeapIterator::kFilterUnreachable);
+ CHECK(helper.a_found());
+ CHECK(helper.b_found());
+ }
+ CHECK(Top::context()->global()->DeleteProperty(
+ *Factory::LookupAsciiSymbol("a"), JSObject::FORCE_DELETION));
+ // We ensure that GC will not happen, so our raw pointer stays valid.
+ AssertNoAllocation no_alloc;
+ Object* a_saved = *a;
+ a.Clear();
+ // Verify that "a" object still resides in the heap...
+ {
+ HeapIteratorTestHelper helper(a_saved, *b);
+ helper.IterateHeap(HeapIterator::kNoFiltering);
+ CHECK(helper.a_found());
+ CHECK(helper.b_found());
+ }
+ // ...but is now unreachable.
+ {
+ HeapIteratorTestHelper helper(a_saved, *b);
+ helper.IterateHeap(HeapIterator::kFilterUnreachable);
+ CHECK(!helper.a_found());
+ CHECK(helper.b_found());
+ }
+}
diff --git a/deps/v8/test/mjsunit/array-slice.js b/deps/v8/test/mjsunit/array-slice.js
index 8f9ce535862..50b5b273064 100644
--- a/deps/v8/test/mjsunit/array-slice.js
+++ b/deps/v8/test/mjsunit/array-slice.js
@@ -218,3 +218,16 @@
assertTrue(delete Array.prototype[5]);
}
})();
+
+// Check slicing on arguments object.
+(function() {
+ function func(expected, a0, a1, a2) {
+ assertEquals(expected, Array.prototype.slice.call(arguments, 1));
+ }
+
+ func([]);
+ func(['a'], 'a');
+ func(['a', 1], 'a', 1);
+ func(['a', 1, undefined], 'a', 1, undefined);
+ func(['a', 1, undefined, void(0)], 'a', 1, undefined, void(0));
+})();
diff --git a/deps/v8/test/mjsunit/array-sort.js b/deps/v8/test/mjsunit/array-sort.js
index a082abcb174..7060c5f366a 100644
--- a/deps/v8/test/mjsunit/array-sort.js
+++ b/deps/v8/test/mjsunit/array-sort.js
@@ -1,4 +1,4 @@
-// Copyright 2008 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -360,3 +360,18 @@ function TestSpecialCasesInheritedElementSort() {
}
TestSpecialCasesInheritedElementSort();
+
+// Test that sort calls compare function with global object as receiver,
+// and with only elements of the array as arguments.
+function o(v) {
+ return {__proto__: o.prototype, val: v};
+}
+var arr = [o(1), o(2), o(4), o(8), o(16), o(32), o(64), o(128), o(256), o(-0)];
+var global = this;
+function cmpTest(a, b) {
+ assertEquals(global, this);
+ assertTrue(a instanceof o);
+ assertTrue(b instanceof o);
+ return a.val - b.val;
+}
+arr.sort(cmpTest); \ No newline at end of file
diff --git a/deps/v8/test/mjsunit/with-readonly.js b/deps/v8/test/mjsunit/with-readonly.js
new file mode 100644
index 00000000000..e29520a4dcc
--- /dev/null
+++ b/deps/v8/test/mjsunit/with-readonly.js
@@ -0,0 +1,43 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test that readonly variables are treated correctly.
+
+// Create an object with a read-only length property in the prototype
+// chain by putting the string split function in the prototype chain.
+var o = {};
+o.__proto__ = String.prototype.split;
+
+function f() {
+ with (o) {
+ length = 23;
+ length = 24;
+ assertEquals(24, length);
+ }
+}
+f();
+
diff --git a/deps/v8/tools/gyp/v8.gyp b/deps/v8/tools/gyp/v8.gyp
index 91cbd6ab3be..6af6611d1be 100644
--- a/deps/v8/tools/gyp/v8.gyp
+++ b/deps/v8/tools/gyp/v8.gyp
@@ -70,7 +70,8 @@
'DEBUG',
'_DEBUG',
'ENABLE_DISASSEMBLER',
- 'V8_ENABLE_CHECKS'
+ 'V8_ENABLE_CHECKS',
+ 'OBJECT_PRINT',
],
'msvs_settings': {
'VCCLCompilerTool': {
diff --git a/deps/v8/tools/v8.xcodeproj/project.pbxproj b/deps/v8/tools/v8.xcodeproj/project.pbxproj
index 51f1cfbf076..5254c6e665a 100644
--- a/deps/v8/tools/v8.xcodeproj/project.pbxproj
+++ b/deps/v8/tools/v8.xcodeproj/project.pbxproj
@@ -1850,6 +1850,7 @@
DEBUG,
ENABLE_LOGGING_AND_PROFILING,
V8_ENABLE_CHECKS,
+ OBJECT_PRINT,
ENABLE_VMSTATE_TRACKING,
);
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
@@ -1914,6 +1915,7 @@
V8_TARGET_ARCH_IA32,
DEBUG,
V8_ENABLE_CHECKS,
+ OBJECT_PRINT,
ENABLE_DEBUGGER_SUPPORT,
);
HEADER_SEARCH_PATHS = ../src;
@@ -1976,6 +1978,7 @@
V8_TARGET_ARCH_IA32,
DEBUG,
V8_ENABLE_CHECKS,
+ OBJECT_PRINT,
ENABLE_DEBUGGER_SUPPORT,
);
HEADER_SEARCH_PATHS = ../src;
diff --git a/deps/v8/tools/visual_studio/debug.vsprops b/deps/v8/tools/visual_studio/debug.vsprops
index 5e3555a9d7f..60b79fe07c0 100644
--- a/deps/v8/tools/visual_studio/debug.vsprops
+++ b/deps/v8/tools/visual_studio/debug.vsprops
@@ -7,7 +7,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- PreprocessorDefinitions="DEBUG;_DEBUG;ENABLE_DISASSEMBLER;V8_ENABLE_CHECKS"
+ PreprocessorDefinitions="DEBUG;_DEBUG;ENABLE_DISASSEMBLER;V8_ENABLE_CHECKS,OBJECT_PRINT"
RuntimeLibrary="1"
/>
<Tool
diff --git a/doc/api/addons.markdown b/doc/api/addons.markdown
index 115bd078d75..315015f571e 100644
--- a/doc/api/addons.markdown
+++ b/doc/api/addons.markdown
@@ -12,7 +12,7 @@ knowledge of several libraries:
descriptor to become readable, wait for a timer, or wait for a signal to
received one will need to interface with libev. That is, if you perform
any I/O, libev will need to be used. Node uses the `EV_DEFAULT` event
- loop. Documentation can be found http:/cvs.schmorp.de/libev/ev.html[here].
+ loop. Documentation can be found [here](http://cvs.schmorp.de/libev/ev.html).
- libeio, C thread pool library. Used to execute blocking POSIX system
calls asynchronously. Mostly wrappers already exist for such calls, in
@@ -69,7 +69,7 @@ like this:
Running `node-waf configure build` will create a file
`build/default/hello.node` which is our Addon.
-`node-waf` is just [WAF](http://code.google.com/p/waf/), the python-based build system. `node-waf` is
+`node-waf` is just [WAF](http://code.google.com/p/waf), the python-based build system. `node-waf` is
provided for the ease of users.
All Node addons must export a function called `init` with this signature:
diff --git a/doc/api/appendix_1.markdown b/doc/api/appendix_1.markdown
index 3274fdacd38..395a9414f47 100644
--- a/doc/api/appendix_1.markdown
+++ b/doc/api/appendix_1.markdown
@@ -2,7 +2,7 @@
There are many third party modules for Node. At the time of writing, August
2010, the master repository of modules is
-http://github.com/ry/node/wiki/modules[the wiki page].
+[the wiki page](http://github.com/ry/node/wiki/modules).
This appendix is intended as a SMALL guide to new-comers to help them
quickly find what are considered to be quality modules. It is not intended
diff --git a/doc/api/assert.markdown b/doc/api/assert.markdown
index 24685ebf38a..a0607e2d3dc 100644
--- a/doc/api/assert.markdown
+++ b/doc/api/assert.markdown
@@ -65,8 +65,8 @@ Custom error validation:
throw new Error("Wrong value");
},
function(err) {
- if ( !(err instanceof Error) || !/value/.test(err) ) {
- return false;
+ if ( (err instanceof Error) && /value/.test(err) ) {
+ return true;
}
},
"unexpected error"
diff --git a/doc/api/os.markdown b/doc/api/os.markdown
index 4429bddbfb6..3c4e1b44fdc 100644
--- a/doc/api/os.markdown
+++ b/doc/api/os.markdown
@@ -2,6 +2,101 @@
Use `require('os')` to access this module.
-### os.getHostname()
+### os.hostname()
Returns the hostname of the operating system.
+
+### os.type()
+
+Returns the operating system name.
+
+### os.release()
+
+Returns the operating system release.
+
+### os.uptime()
+
+Returns the system uptime in seconds.
+
+### os.loadavg()
+
+Returns an array containing the 1, 5, and 15 minute load averages.
+
+### os.totalmem()
+
+Returns the total amount of system memory in bytes.
+
+### os.freemem()
+
+Returns the amount of free system memory in bytes.
+
+### os.cpus()
+
+Returns an array of objects containing information about each CPU/core installed: model, speed (in MHz), and times (an object containing the number of CPU ticks spent in: user, nice, sys, idle, and irq).
+
+Example inspection of os.cpus:
+
+ [ { model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz',
+ speed: 2926,
+ times:
+ { user: 252020,
+ nice: 0,
+ sys: 30340,
+ idle: 1070356870,
+ irq: 0 } },
+ { model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz',
+ speed: 2926,
+ times:
+ { user: 306960,
+ nice: 0,
+ sys: 26980,
+ idle: 1071569080,
+ irq: 0 } },
+ { model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz',
+ speed: 2926,
+ times:
+ { user: 248450,
+ nice: 0,
+ sys: 21750,
+ idle: 1070919370,
+ irq: 0 } },
+ { model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz',
+ speed: 2926,
+ times:
+ { user: 256880,
+ nice: 0,
+ sys: 19430,
+ idle: 1070905480,
+ irq: 20 } },
+ { model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz',
+ speed: 2926,
+ times:
+ { user: 511580,
+ nice: 20,
+ sys: 40900,
+ idle: 1070842510,
+ irq: 0 } },
+ { model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz',
+ speed: 2926,
+ times:
+ { user: 291660,
+ nice: 0,
+ sys: 34360,
+ idle: 1070888000,
+ irq: 10 } },
+ { model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz',
+ speed: 2926,
+ times:
+ { user: 308260,
+ nice: 0,
+ sys: 55410,
+ idle: 1071129970,
+ irq: 880 } },
+ { model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz',
+ speed: 2926,
+ times:
+ { user: 266450,
+ nice: 1480,
+ sys: 34920,
+ idle: 1072572010,
+ irq: 30 } } ] \ No newline at end of file
diff --git a/doc/api/process.markdown b/doc/api/process.markdown
index 5fee9a16da1..3383d59a9f5 100644
--- a/doc/api/process.markdown
+++ b/doc/api/process.markdown
@@ -59,7 +59,8 @@ standard POSIX signal names such as SIGINT, SIGUSR1, etc.
Example of listening for `SIGINT`:
- var stdin = process.openStdin();
+ // Start reading from stdin so we don't exit.
+ process.stdin.resume();
process.on('SIGINT', function () {
console.log('Got SIGINT. Press Control-D to exit.');
@@ -80,21 +81,21 @@ Example: the definition of `console.log`
};
-### process.openStdin()
+### process.stdin
-Opens the standard input stream, returns a `Readable Stream`.
+A `Readable Stream` for stdin. The stdin stream is paused by default, so one
+must call `process.stdin.resume()` to read from it.
Example of opening standard input and listening for both events:
- var stdin = process.openStdin();
+ process.stdin.resume();
+ process.stdin.setEncoding('utf8');
- stdin.setEncoding('utf8');
-
- stdin.on('data', function (chunk) {
+ process.stdin.on('data', function (chunk) {
process.stdout.write('data: ' + chunk);
});
- stdin.on('end', function () {
+ process.stdin.on('end', function () {
process.stdout.write('end');
});
diff --git a/doc/api/repl.markdown b/doc/api/repl.markdown
index 8ae3623a48c..1bdb4f2fcb5 100644
--- a/doc/api/repl.markdown
+++ b/doc/api/repl.markdown
@@ -27,11 +27,11 @@ For example, you could add this to your bashrc file:
alias node="env NODE_NO_READLINE=1 rlwrap node"
-### repl.start(prompt='> ', stream=process.openStdin())
+### repl.start(prompt='> ', stream=process.stdin)
Starts a REPL with `prompt` as the prompt and `stream` for all I/O. `prompt`
is optional and defaults to `> `. `stream` is optional and defaults to
-`process.openStdin()`.
+`process.stdin`.
Multiple REPLs may be started against the same running instance of node. Each
will share the same global object but will have unique I/O.
diff --git a/doc/api/streams.markdown b/doc/api/streams.markdown
index 88ae04f5c03..51540cc1c03 100644
--- a/doc/api/streams.markdown
+++ b/doc/api/streams.markdown
@@ -65,7 +65,7 @@ Resumes the incoming `'data'` events after a `pause()`.
Closes the underlying file descriptor. Stream will not emit any more events.
-### stream.pipe(destination, [options], [filter])
+### stream.pipe(destination, [options])
This is a `Stream.prototype` method available on all `Stream`s.
@@ -75,7 +75,8 @@ streams are kept in sync by pausing and resuming as necessary.
Emulating the Unix `cat` command:
- process.openStdin().pipe(process.stdout);
+ process.stdin.resume();
+ process.stdin.pipe(process.stdout);
By default `end()` is called on the destination when the source stream emits
@@ -84,56 +85,18 @@ By default `end()` is called on the destination when the source stream emits
This keeps `process.stdout` open so that "Goodbye" can be written at the end.
- var stdin = process.openStdin();
- stdin.pipe(process.stdout, { end: false });
- stdin.on("end", function() { process.stdout.write("Goodbye\n"); });
+ process.stdin.resume();
+
+ process.stdin.pipe(process.stdout, { end: false });
+
+ process.stdin.on("end", function() {
+ process.stdout.write("Goodbye\n");
+ });
NOTE: If the source stream does not support `pause()` and `resume()`, this function
adds simple definitions which simply emit `'pause'` and `'resume'` events on
the source stream.
-
-The `filter` argument is an optional callback which can be used to filter all
-data passing through the pipe. This makes it easy to do arbitrary transforms
-(like gzip) while still maintaining the proper throttling. `filter` gets
-three arguments: a buffer, a write function, and a done function. Here is an
-example of a chat which uses a `filter` to append each message with the
-address of the sender.
-
- var net = require('net');
- var people = [];
-
- function address(socket) {
- return '<' + socket.remoteAddress + ':' + socket.remotePort + '> ';
- }
-
- net.Server(function (socket) {
- socket.write("hello!\r\n");
-
- people.forEach(function (p) {
- socket.pipe(p, { end: false }, function (d, write, done) {
- write(address(socket));
- write(d);
- done();
- });
-
- p.pipe(socket, { end: false }, function (d, write, done) {
- write(address(p));
- write(d);
- done();
- });
- });
-
- people.push(socket);
-
- socket.on('end', function () {
- people.splice(people.indexOf(socket), 1);
- });
- }).listen(8000);
-
-
-
-
## Writable Stream
A `Writable Stream` has the following methods, members, and events.
diff --git a/doc/index.html b/doc/index.html
index 24db2721111..da1c96296d9 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -24,7 +24,7 @@
<li><a href="#links">Links</a></li>
<li><a href="#contributing">Contributing</a></li>
<li><a href="http://nodejs.org/docs/v0.3.2/api">v0.3.2 docs</a></li>
- <li><a href="http://nodejs.org/docs/v0.2.5/api.html">v0.2.5 docs</a></li>
+ <li><a href="http://nodejs.org/docs/v0.2.6/api.html">v0.2.6 docs</a></li>
</ol>
</div>
<div id="content">
@@ -86,9 +86,9 @@ net.createServer(function (socket) {
<a href="http://github.com/ry/node/tree/master">git repo</a>
</p>
<p>
- Stable: 2010.11.16
- <a href="http://nodejs.org/dist/node-v0.2.5.tar.gz">node-v0.2.5.tar.gz</a>
- (<a href="http://nodejs.org/docs/v0.2.5/api.html">Documentation</a>)
+ Stable: 2010.12.30
+ <a href="http://nodejs.org/dist/node-v0.2.6.tar.gz">node-v0.2.6.tar.gz</a>
+ (<a href="http://nodejs.org/docs/v0.2.6/api.html">Documentation</a>)
</p>
<p>
diff --git a/lib/assert.js b/lib/assert.js
index 3b18f05cb4b..b46f28b8625 100644
--- a/lib/assert.js
+++ b/lib/assert.js
@@ -246,13 +246,14 @@ function expectedException(actual, expected) {
}
if (expected instanceof RegExp) {
- if (expected.test(actual)) {
- return true;
- }
- } else if (actual instanceof expected ||
- expected.call({}, actual) !== false) {
+ return expected.test(actual);
+ } else if (actual instanceof expected) {
+ return true;
+ } else if ( expected.call({}, actual) === true ) {
return true;
}
+
+ return false;
}
function _throws(shouldThrow, block, expected, message) {
diff --git a/lib/console.js b/lib/console.js
index 857199cf5c9..8f09c5aab6a 100644
--- a/lib/console.js
+++ b/lib/console.js
@@ -3,8 +3,10 @@ var writeError = process.binding('stdio').writeError;
// console object
var formatRegExp = /%[sdj]/g;
function format(f) {
+ var util = require('util');
+
if (typeof f !== 'string') {
- var objects = [], util = require('util');
+ var objects = [];
for (var i = 0; i < arguments.length; i++) {
objects.push(util.inspect(arguments[i]));
}
@@ -16,15 +18,19 @@ function format(f) {
var args = arguments;
var str = String(f).replace(formatRegExp, function(x) {
switch (x) {
- case '%s': return args[i++];
- case '%d': return +args[i++];
+ case '%s': return String(args[i++]);
+ case '%d': return Number(args[i++]);
case '%j': return JSON.stringify(args[i++]);
default:
return x;
}
});
- for (var len = args.length; i < len; ++i) {
- str += ' ' + args[i];
+ for (var len = args.length, x = args[i]; i < len; x = args[++i]) {
+ if (x === null || typeof x !== 'object') {
+ str += ' ' + x;
+ } else {
+ str += ' ' + util.inspect(x);
+ }
}
return str;
}
diff --git a/lib/events.js b/lib/events.js
index 26e0f061933..ad3ce726c74 100644
--- a/lib/events.js
+++ b/lib/events.js
@@ -89,6 +89,8 @@ EventEmitter.prototype.once = function(type, listener) {
self.removeListener(type, g);
listener.apply(this, arguments);
});
+
+ return this;
};
EventEmitter.prototype.removeListener = function(type, listener) {
diff --git a/lib/os.js b/lib/os.js
index 14a582c2e21..5b1bb22d18c 100644
--- a/lib/os.js
+++ b/lib/os.js
@@ -1,3 +1,10 @@
var binding = process.binding('os');
-exports.getHostname = binding.getHostname;
+exports.hostname = binding.getHostname;
+exports.loadavg = binding.getLoadAvg;
+exports.uptime = binding.getUptime;
+exports.freemem = binding.getFreeMem;
+exports.totalmem = binding.getTotalMem;
+exports.cpus = binding.getCPUs;
+exports.type = binding.getOSType;
+exports.release = binding.getOSRelease; \ No newline at end of file
diff --git a/lib/readline.js b/lib/readline.js
index cc62922623b..341b20b4795 100644
--- a/lib/readline.js
+++ b/lib/readline.js
@@ -83,7 +83,13 @@ Interface.prototype.__defineGetter__('columns', function() {
Interface.prototype.setPrompt = function(prompt, length) {
this._prompt = prompt;
- this._promptLength = length ? length : Buffer.byteLength(prompt);
+ if (length) {
+ this._promptLength = length;
+ } else {
+ var lines = prompt.split(/[\r\n]/);
+ var lastLine = lines[lines.length - 1];
+ this._promptLength = Buffer.byteLength(lastLine);
+ }
};
@@ -97,6 +103,28 @@ Interface.prototype.prompt = function() {
};
+Interface.prototype.question = function(query, cb) {
+ if (cb) {
+ this._oldPrompt = this._prompt;
+ this.setPrompt(query);
+ this._questionCallback = cb;
+ this.prompt();
+ }
+};
+
+
+Interface.prototype._onLine = function(line) {
+ if (this._questionCallback) {
+ var cb = this._questionCallback;
+ this._questionCallback = null;
+ this.setPrompt(this._oldPrompt);
+ cb(line)
+ } else {
+ this.emit('line', line);
+ }
+};
+
+
Interface.prototype._addHistory = function() {
if (this.line.length === 0) return '';
@@ -149,7 +177,7 @@ Interface.prototype.write = function(d) {
Interface.prototype._normalWrite = function(b) {
// Very simple implementation right now. Should try to break on
// new lines.
- this.emit('line', b.toString());
+ this._onLine(b.toString());
};
Interface.prototype._insertString = function(c) {
@@ -304,7 +332,7 @@ Interface.prototype._ttyWrite = function(b) {
case 13: /* enter */
var line = this._addHistory();
this.output.write('\r\n');
- this.emit('line', line);
+ this._onLine(line);
break;
case 127: /* backspace */
diff --git a/lib/repl.js b/lib/repl.js
index 4d144f17cdf..aef0e9e2d3b 100644
--- a/lib/repl.js
+++ b/lib/repl.js
@@ -20,20 +20,21 @@
*/
var util = require('util');
-var Script = process.binding('evals').Script;
-var evalcx = Script.runInContext;
+var vm = require('vm');
var path = require('path');
var fs = require('fs');
var rl = require('readline');
-var context;
+var context;
var disableColors = process.env.NODE_DISABLE_COLORS ? true : false;
+
// hack for require.resolve("./relative") to work properly.
module.filename = process.cwd() + '/repl';
+
function resetContext() {
- context = Script.createContext();
+ context = vm.createContext();
for (var i in global) context[i] = global[i];
context.module = module;
context.require = require;
@@ -43,12 +44,13 @@ function resetContext() {
// Can overridden with custom print functions, such as `probe` or `eyes.js`
exports.writer = util.inspect;
+
function REPLServer(prompt, stream) {
var self = this;
if (!context) resetContext();
if (!exports.repl) exports.repl = this;
self.context = context;
- self.buffered_cmd = '';
+ self.bufferedCommand = '';
self.stream = stream || process.openStdin();
self.prompt = prompt || '> ';
@@ -70,9 +72,9 @@ function REPLServer(prompt, stream) {
rli.setPrompt(self.prompt);
rli.on('SIGINT', function() {
- if (self.buffered_cmd && self.buffered_cmd.length > 0) {
+ if (self.bufferedCommand && self.bufferedCommand.length > 0) {
rli.write('\n');
- self.buffered_cmd = '';
+ self.bufferedCommand = '';
self.displayPrompt();
} else {
rli.close();
@@ -104,18 +106,31 @@ function REPLServer(prompt, stream) {
if (!skipCatchall) {
// The catchall for errors
try {
- self.buffered_cmd += cmd;
+ self.bufferedCommand += cmd + '\n';
// This try is for determining if the command is complete, or should
// continue onto the next line.
try {
- // Use evalcx to supply the global context
- var ret = evalcx(self.buffered_cmd, context, 'repl');
+ // We try to evaluate both expressions e.g.
+ // '{ a : 1 }'
+ // and statements e.g.
+ // 'for (var i = 0; i < 10; i++) console.log(i);'
+
+ var ret;
+ try {
+ // First we attempt to eval as expression with parens.
+ // This catches '{a : 1}' properly.
+ ret = vm.runInContext('(' + self.bufferedCommand + ')', context, 'repl');
+ } catch (e) {
+ // Now as statement without parens.
+ ret = vm.runInContext(self.bufferedCommand, context, 'repl');
+ }
+
if (ret !== undefined) {
context._ = ret;
self.stream.write(exports.writer(ret) + '\n');
}
- self.buffered_cmd = '';
+ self.bufferedCommand = '';
} catch (e) {
// instanceof doesn't work across context switches.
if (!(e && e.constructor && e.constructor.name === 'SyntaxError')) {
@@ -135,7 +150,7 @@ function REPLServer(prompt, stream) {
} else {
self.stream.write(e.toString() + '\n');
}
- self.buffered_cmd = '';
+ self.bufferedCommand = '';
}
}
@@ -150,21 +165,30 @@ function REPLServer(prompt, stream) {
}
exports.REPLServer = REPLServer;
+
// prompt is a string to print on each line for the prompt,
// source is a stream to use for I/O, defaulting to stdin/stdout.
exports.start = function(prompt, source) {
return new REPLServer(prompt, source);
};
+
REPLServer.prototype.displayPrompt = function() {
- this.rli.setPrompt(this.buffered_cmd.length ? '... ' : this.prompt);
+ this.rli.setPrompt(this.bufferedCommand.length ? '... ' : this.prompt);
this.rli.prompt();
};
+
// read a line from the stream, then eval it
REPLServer.prototype.readline = function(cmd) {
};
+
+var requireRE = /\brequire\s*\(['"](([\w\.\/-]+\/)?([\w\.\/-]*))/;
+var simpleExpressionRE =
+ /(([a-zA-Z_$](?:\w|\$)*)\.)*([a-zA-Z_$](?:\w|\$)*)\.?$/;
+
+
// Provide a list of completions for the given leading text. This is
// given to the readline interface for handling tab completion.
//
@@ -192,8 +216,8 @@ REPLServer.prototype.complete = function(line) {
if (match[1].length > 1) {
filter = match[1];
}
- } else if (match =
- line.match(/\brequire\s*\(['"](([\w\.\/-]+\/)?([\w\.\/-]*))/)) {
+
+ } else if (match = line.match(requireRE)) {
// require('...<Tab>')
//TODO: suggest require.exts be exposed to be introspec registered
//extensions?
@@ -261,7 +285,6 @@ REPLServer.prototype.complete = function(line) {
'url'];
completionGroups.push(builtinLibs);
}
- }
// Handle variable member lookup.
// We support simple chained expressions like the following (no function
@@ -273,10 +296,8 @@ REPLServer.prototype.complete = function(line) {
// spam.eggs.<|> # completions for 'spam.eggs' with filter ''
// foo<|> # all scope vars with filter 'foo'
// foo.<|> # completions for 'foo' with filter ''
- else if (line.length === 0 || line[line.length - 1].match(/\w|\.|\$/)) {
- var simpleExpressionPat =
- /(([a-zA-Z_$](?:\w|\$)*)\.)*([a-zA-Z_$](?:\w|\$)*)\.?$/;
- match = simpleExpressionPat.exec(line);
+ } else if (line.length === 0 || line[line.length - 1].match(/\w|\.|\$/)) {
+ match = simpleExpressionRE.exec(line);
if (line.length === 0 || match) {
var expr;
completeOn = (match ? match[0] : '');
@@ -320,7 +341,7 @@ REPLServer.prototype.complete = function(line) {
}
} else {
try {
- obj = evalcx(expr, this.context, 'repl');
+ obj = vm.runInContext(expr, this.context, 'repl');
} catch (e) {
//console.log("completion eval error, expr='"+expr+"': "+e);
}
@@ -373,6 +394,7 @@ REPLServer.prototype.complete = function(line) {
}
completionGroups = newCompletionGroups;
}
+
if (completionGroups.length) {
var uniq = {}; // unique completions across all groups
completions = [];
@@ -398,13 +420,13 @@ REPLServer.prototype.complete = function(line) {
return [completions || [], completeOn];
};
+
/**
* Used to parse and execute the Node REPL commands.
*
* @param {keyword} keyword The command entered to check.
* @return {Boolean} If true it means don't continue parsing the command.
*/
-
REPLServer.prototype.parseREPLKeyword = function(keyword, rest) {
var cmd = this.commands[keyword];
if (cmd) {
@@ -414,20 +436,23 @@ REPLServer.prototype.parseREPLKeyword = function(keyword, rest) {
return false;
};
+
REPLServer.prototype.defineCommand = function(keyword, cmd) {
- if (typeof cmd === 'function') cmd = {action: cmd};
- else if (typeof cmd.action !== 'function') {
+ if (typeof cmd === 'function') {
+ cmd = {action: cmd};
+ } else if (typeof cmd.action !== 'function') {
throw new Error('bad argument, action must be a function');
}
this.commands['.' + keyword] = cmd;
};
+
function defineDefaultCommands(repl) {
// TODO remove me after 0.3.x
repl.defineCommand('break', {
help: 'Sometimes you get stuck, this gets you out',
action: function() {
- this.buffered_cmd = '';
+ this.bufferedCommand = '';
this.displayPrompt();
}
});
@@ -436,7 +461,7 @@ function defineDefaultCommands(repl) {
help: 'Break, and also clear the local context',
action: function() {
this.stream.write('Clearing context...\n');
- this.buffered_cmd = '';
+ this.bufferedCommand = '';
resetContext();
this.displayPrompt();
}
@@ -462,6 +487,7 @@ function defineDefaultCommands(repl) {
});
}
+
function trimWhitespace(cmd) {
var trimmer = /^\s*(.+)\s*$/m,
matches = trimmer.exec(cmd);
@@ -471,6 +497,7 @@ function trimWhitespace(cmd) {
}
}
+
function regexpEscape(s) {
return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
}
@@ -496,9 +523,9 @@ REPLServer.prototype.convertToContext = function(cmd) {
}
// Replaces: function foo() {}; with: foo = function foo() {};
- matches = scopeFunc.exec(self.buffered_cmd);
+ matches = scopeFunc.exec(self.bufferedCommand);
if (matches && matches.length === 2) {
- return matches[1] + ' = ' + self.buffered_cmd;
+ return matches[1] + ' = ' + self.bufferedCommand;
}
return cmd;
diff --git a/lib/stream.js b/lib/stream.js
index e92c1bc5dbe..98f0c37fcbc 100644
--- a/lib/stream.js
+++ b/lib/stream.js
@@ -7,55 +7,16 @@ function Stream() {
util.inherits(Stream, events.EventEmitter);
exports.Stream = Stream;
-Stream.prototype.pipe = function(dest /* options, filter */) {
+Stream.prototype.pipe = function(dest, options) {
var source = this;
- // parse arguments
- var options, filter;
- if (typeof arguments[1] == 'object') {
- options = arguments[1];
- filter = arguments[2];
- } else {
- filter = arguments[1];
- }
-
function ondata(chunk) {
- // FIXME shouldn't need to test writable - this is working around bug.
- // .writable should not change before a 'end' event is fired.
if (dest.writable) {
if (false === dest.write(chunk)) source.pause();
}
}
- if (!filter) {
- source.on('data', ondata);
- } else {
- //
- // TODO: needs tests
- //
- var wait = false;
- var waitQueue = [];
-
- function done () {
- wait = false;
- // Drain the waitQueue
- if (dest.writable && waitQueue.length) {
- wait = true;
- filter(waitQueue.shift(), ondata, done);
- }
- }
-
- source.on('data', function (d) {
- if (wait) {
- waitQueue.push(d);
- source.pause();
- } else {
- wait = true;
- filter(d, ondata, done);
- }
- });
- }
-
+ source.on('data', ondata);
function ondrain() {
if (source.readable) source.resume();
diff --git a/src/node.cc b/src/node.cc
index d6a17450360..f42c82481e9 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -1200,7 +1200,7 @@ static void CheckStatus(EV_P_ ev_timer *watcher, int revents) {
// check memory
size_t rss, vsize;
- if (!ev_is_active(&gc_idle) && OS::GetMemory(&rss, &vsize) == 0) {
+ if (!ev_is_active(&gc_idle) && Platform::GetMemory(&rss, &vsize) == 0) {
if (rss > 1024*1024*128) {
// larger than 128 megs, just start the idle watcher
ev_idle_start(EV_A_ &gc_idle);
@@ -1225,7 +1225,7 @@ v8::Handle<v8::Value> MemoryUsage(const v8::Arguments& args) {
size_t rss, vsize;
- int r = OS::GetMemory(&rss, &vsize);
+ int r = Platform::GetMemory(&rss, &vsize);
if (r != 0) {
return ThrowException(Exception::Error(String::New(strerror(errno))));
@@ -1260,7 +1260,7 @@ v8::Handle<v8::Value> MemoryUsage(const v8::Arguments& args) {
Handle<Value> Kill(const Arguments& args) {
HandleScope scope;
- if (args.Length() != 2 || !args[0]->IsNumber() || !args[1]->IsNumber()) {
+ if (args.Length() != 2) {
return ThrowException(Exception::Error(String::New("Bad argument.")));
}
@@ -1537,7 +1537,7 @@ static Handle<Value> ProcessTitleGetter(Local<String> property,
const AccessorInfo& info) {
HandleScope scope;
int len;
- const char *s = OS::GetProcessTitle(&len);
+ const char *s = Platform::GetProcessTitle(&len);
return scope.Close(s ? String::New(s, len) : String::Empty());
}
@@ -1547,7 +1547,7 @@ static void ProcessTitleSetter(Local<String> property,
const AccessorInfo& info) {
HandleScope scope;
String::Utf8Value title(value->ToString());
- OS::SetProcessTitle(*title);
+ Platform::SetProcessTitle(*title);
}
@@ -1636,6 +1636,8 @@ static Handle<Array> EnvEnumerator(const AccessorInfo& info) {
static void Load(int argc, char *argv[]) {
HandleScope scope;
+ int i, j;
+
Local<FunctionTemplate> process_template = FunctionTemplate::New();
node::EventEmitter::Initialize(process_template);
@@ -1661,6 +1663,22 @@ static void Load(int argc, char *argv[]) {
versions->Set(String::NewSymbol("ares"), String::New(ARES_VERSION_STR));
snprintf(buf, 20, "%d.%d", ev_version_major(), ev_version_minor());
versions->Set(String::NewSymbol("ev"), String::New(buf));
+#ifdef HAVE_OPENSSL
+ // Stupid code to slice out the version string.
+ int c, l = strlen(OPENSSL_VERSION_TEXT);
+ for (i = 0; i < l; i++) {
+ c = OPENSSL_VERSION_TEXT[i];
+ if ('0' <= c && c <= '9') {
+ for (j = i + 1; j < l; j++) {
+ c = OPENSSL_VERSION_TEXT[j];
+ if (c == ' ') break;
+ }
+ break;
+ }
+ }
+ versions->Set(String::NewSymbol("openssl"),
+ String::New(OPENSSL_VERSION_TEXT + i, j - i));
+#endif
@@ -1668,7 +1686,6 @@ static void Load(int argc, char *argv[]) {
process->Set(String::NewSymbol("platform"), String::New("PLATFORM"));
// process.argv
- int i, j;
Local<Array> arguments = Array::New(argc - option_end_index + 1);
arguments->Set(Integer::New(0), String::New(argv[0]));
for (j = 1, i = option_end_index; i < argc; j++, i++) {
@@ -1711,7 +1728,7 @@ static void Load(int argc, char *argv[]) {
size_t size = 2*PATH_MAX;
char execPath[size];
- if (OS::GetExecutablePath(execPath, &size) != 0) {
+ if (Platform::GetExecutablePath(execPath, &size) != 0) {
// as a last ditch effort, fallback on argv[0] ?
process->Set(String::NewSymbol("execPath"), String::New(argv[0]));
} else {
@@ -1906,7 +1923,7 @@ static int RegisterSignalHandler(int signal, void (*handler)(int)) {
int Start(int argc, char *argv[]) {
// Hack aroung with the argv pointer. Used for process.title = "blah".
- argv = node::OS::SetupArgs(argc, argv);
+ argv = node::Platform::SetupArgs(argc, argv);
// Parse a few arguments which are specific to Node.
node::ParseArgs(&argc, argv);
diff --git a/src/node.js b/src/node.js
index 2bb46a60f5e..f017d3ab80a 100644
--- a/src/node.js
+++ b/src/node.js
@@ -35,7 +35,9 @@
if (!x) throw new Error(msg || 'assertion error');
};
- var evals = process.binding('evals');
+ var Script = process.binding('evals').Script;
+ var runInThisContext = Script.runInThisContext;
+ var runInNewContext = Script.runInNewContext;
// lazy loaded.
var constants;
@@ -86,9 +88,10 @@
if (internalModuleCache[id]) return internalModuleCache[id].exports;
if (!natives[id]) throw new Error('No such native module ' + id);
- var fn = evals.Script.runInThisContext(
+ var fn = runInThisContext(
'(function (module, exports, require) {' + natives[id] + '\n})',
- id + '.js');
+ id + '.js',
+ true);
var m = {id: id, exports: {}};
fn(m, m.exports, requireNative);
m.loaded = true;
@@ -332,7 +335,7 @@
sandbox.global = sandbox;
sandbox.root = root;
- return evals.Script.runInNewContext(content, sandbox, filename);
+ return runInNewContext(content, sandbox, filename, true);
} else {
debug('load root module');
// root module
@@ -342,7 +345,7 @@
global.__dirname = dirname;
global.module = self;
- return evals.Script.runInThisContext(content, filename);
+ return runInThisContext(content, filename, true);
}
} else {
@@ -352,7 +355,7 @@
content +
'\n});';
- var compiledWrapper = evals.Script.runInThisContext(wrapper, filename);
+ var compiledWrapper = runInThisContext(wrapper, filename, true);
if (filename === process.argv[1] && global.v8debug) {
global.v8debug.Debug.setBreakPoint(compiledWrapper, 0, 0);
}
@@ -461,7 +464,9 @@
};
- var stdout;
+ var stdout, stdin;
+
+
process.__defineGetter__('stdout', function() {
if (stdout) return stdout;
@@ -484,8 +489,8 @@
return stdout;
});
- var stdin;
- process.openStdin = function() {
+
+ process.__defineGetter__('stdin', function() {
if (stdin) return stdin;
var binding = process.binding('stdio'),
@@ -500,9 +505,13 @@
stdin.readable = true;
}
- stdin.resume();
-
return stdin;
+ });
+
+
+ process.openStdin = function() {
+ process.stdin.resume();
+ return process.stdin;
};
diff --git a/src/node_crypto.cc b/src/node_crypto.cc
index 3970a2a514f..ae9e32d2c83 100644
--- a/src/node_crypto.cc
+++ b/src/node_crypto.cc
@@ -177,8 +177,8 @@ Handle<Value> SecureContext::SetKey(const Arguments& args) {
}
SSL_CTX_use_PrivateKey(sc->ctx_, key);
+ EVP_PKEY_free(key);
BIO_free(bio);
- // XXX Free key?
return True();
}
@@ -1719,19 +1719,19 @@ class Decipher : public ObjectWrap {
if (alloc_buf) {
delete [] buf;
- alloc_buf = false;
}
buf = ciphertext;
len = ciphertext_len;
+ alloc_buf = true;
} else if (strcasecmp(*encoding, "base64") == 0) {
unbase64((unsigned char*)buf, len, (char **)&ciphertext, &ciphertext_len);
if (alloc_buf) {
delete [] buf;
- alloc_buf = false;
}
buf = ciphertext;
len = ciphertext_len;
+ alloc_buf = true;
} else if (strcasecmp(*encoding, "binary") == 0) {
// Binary - do nothing
diff --git a/src/node_net.cc b/src/node_net.cc
index 8b9b061bfe8..b711c396921 100644
--- a/src/node_net.cc
+++ b/src/node_net.cc
@@ -462,62 +462,84 @@ static Handle<Value> Connect(const Arguments& args) {
#ifdef __POSIX__
-#define ADDRESS_TO_JS(info, address_storage) \
+#define ADDRESS_TO_JS(info, address_storage, addrlen) \
do { \
char ip[INET6_ADDRSTRLEN]; \
int port; \
struct sockaddr_in *a4; \
struct sockaddr_in6 *a6; \
struct sockaddr_un *au; \
- switch ((address_storage).ss_family) { \
- case AF_INET6: \
- a6 = (struct sockaddr_in6*)&(address_storage); \
- inet_ntop(AF_INET6, &(a6->sin6_addr), ip, INET6_ADDRSTRLEN); \
- port = ntohs(a6->sin6_port); \
- (info)->Set(address_symbol, String::New(ip)); \
- (info)->Set(port_symbol, Integer::New(port)); \
- break; \
- case AF_INET: \
- a4 = (struct sockaddr_in*)&(address_storage); \
- inet_ntop(AF_INET, &(a4->sin_addr), ip, INET6_ADDRSTRLEN); \
- port = ntohs(a4->sin_port); \
- (info)->Set(address_symbol, String::New(ip)); \
- (info)->Set(port_symbol, Integer::New(port)); \
- break; \
- case AF_UNIX: \
- au = (struct sockaddr_un*)&(address_storage); \
- (info)->Set(address_symbol, String::New(au->sun_path)); \
- break; \
- default: \
- (info)->Set(address_symbol, String::Empty()); \
+ if (addrlen == 0) { \
+ (info)->Set(address_symbol, String::Empty()); \
+ } else { \
+ switch ((address_storage).ss_family) { \
+ case AF_INET6: \
+ a6 = (struct sockaddr_in6*)&(address_storage); \
+ inet_ntop(AF_INET6, &(a6->sin6_addr), ip, INET6_ADDRSTRLEN); \
+ port = ntohs(a6->sin6_port); \
+ (info)->Set(address_symbol, String::New(ip)); \
+ (info)->Set(port_symbol, Integer::New(port)); \
+ break; \
+ case AF_INET: \
+ a4 = (struct sockaddr_in*)&(address_storage); \
+ inet_ntop(AF_INET, &(a4->sin_addr), ip, INET6_ADDRSTRLEN); \
+ port = ntohs(a4->sin_port); \
+ (info)->Set(address_symbol, String::New(ip)); \
+ (info)->Set(port_symbol, Integer::New(port)); \
+ break; \
+ case AF_UNIX: \
+ /*
+ * Three types of addresses (see man 7 unix):
+ * * unnamed: sizeof(sa_family_t) (sun_path should not be used)
+ * * abstract (Linux extension): sizeof(struct sockaddr_un)
+ * * pathname: sizeof(sa_family_t) + strlen(sun_path) + 1
+ */ \
+ au = (struct sockaddr_un*)&(address_storage); \
+ if (addrlen == sizeof(sa_family_t)) { \
+ (info)->Set(address_symbol, String::Empty()); \
+ } else if (addrlen == sizeof(struct sockaddr_un)) { \
+ /* first byte is '\0' and all remaining bytes are name;
+ * it is not NUL-terminated and may contain embedded NULs */ \
+ (info)->Set(address_symbol, String::New(au->sun_path + 1, sizeof(au->sun_path - 1))); \
+ } else { \
+ (info)->Set(address_symbol, String::New(au->sun_path)); \
+ } \
+ break; \
+ default: \
+ (info)->Set(address_symbol, String::Empty()); \
+ } \
} \
} while (0)
#else // __MINGW32__
-#define ADDRESS_TO_JS(info, address_storage) \
+#define ADDRESS_TO_JS(info, address_storage, addrlen) \
do { \
char ip[INET6_ADDRSTRLEN]; \
int port; \
struct sockaddr_in *a4; \
struct sockaddr_in6 *a6; \
- switch ((address_storage).ss_family) { \
- case AF_INET6: \
- a6 = (struct sockaddr_in6*)&(address_storage); \
- inet_ntop(AF_INET6, &(a6->sin6_addr), ip, INET6_ADDRSTRLEN); \
- port = ntohs(a6->sin6_port); \
- (info)->Set(address_symbol, String::New(ip)); \
- (info)->Set(port_symbol, Integer::New(port)); \
- break; \
- case AF_INET: \
- a4 = (struct sockaddr_in*)&(address_storage); \
- inet_ntop(AF_INET, &(a4->sin_addr), ip, INET6_ADDRSTRLEN); \
- port = ntohs(a4->sin_port); \
- (info)->Set(address_symbol, String::New(ip)); \
- (info)->Set(port_symbol, Integer::New(port)); \
- break; \
- default: \
- (info)->Set(address_symbol, String::Empty()); \
+ if (addrlen == 0) { \
+ (info)->Set(address_symbol, String::Empty()); \
+ } else { \
+ switch ((address_storage).ss_family) { \
+ case AF_INET6: \
+ a6 = (struct sockaddr_in6*)&(address_storage); \
+ inet_ntop(AF_INET6, &(a6->sin6_addr), ip, INET6_ADDRSTRLEN); \
+ port = ntohs(a6->sin6_port); \
+ (info)->Set(address_symbol, String::New(ip)); \
+ (info)->Set(port_symbol, Integer::New(port)); \
+ break; \
+ case AF_INET: \
+ a4 = (struct sockaddr_in*)&(address_storage); \
+ inet_ntop(AF_INET, &(a4->sin_addr), ip, INET6_ADDRSTRLEN); \
+ port = ntohs(a4->sin_port); \
+ (info)->Set(address_symbol, String::New(ip)); \
+ (info)->Set(port_symbol, Integer::New(port)); \
+ break; \
+ default: \
+ (info)->Set(address_symbol, String::Empty()); \
+ } \
} \
} while (0)
@@ -542,7 +564,7 @@ static Handle<Value> GetSockName(const Arguments& args) {
Local<Object> info = Object::New();
- ADDRESS_TO_JS(info, address_storage);
+ ADDRESS_TO_JS(info, address_storage, len);
return scope.Close(info);
}
@@ -564,7 +586,7 @@ static Handle<Value> GetPeerName(const Arguments& args) {
Local<Object> info = Object::New();
- ADDRESS_TO_JS(info, address_storage);
+ ADDRESS_TO_JS(info, address_storage, len);
return scope.Close(info);
}
@@ -614,6 +636,7 @@ static Handle<Value> Accept(const Arguments& args) {
if (peer_fd < 0) {
if (errno == EAGAIN) return scope.Close(Null());
+ if (errno == ECONNABORTED) return scope.Close(Null());
return ThrowException(ErrnoException(errno, "accept"));
}
#else // __MINGW32__
@@ -642,7 +665,7 @@ static Handle<Value> Accept(const Arguments& args) {
peer_info->Set(fd_symbol, Integer::New(peer_fd));
- ADDRESS_TO_JS(peer_info, address_storage);
+ ADDRESS_TO_JS(peer_info, address_storage, len);
return scope.Close(peer_info);
}
@@ -787,7 +810,7 @@ static Handle<Value> RecvFrom(const Arguments& args) {
info->Set(size_symbol, Integer::New(bytes_read));
- ADDRESS_TO_JS(info, address_storage);
+ ADDRESS_TO_JS(info, address_storage, addrlen);
return scope.Close(info);
}
diff --git a/src/node_os.cc b/src/node_os.cc
index 2c17d33c81a..9765955d864 100644
--- a/src/node_os.cc
+++ b/src/node_os.cc
@@ -3,10 +3,14 @@
#include <node.h>
#include <v8.h>
+#include "platform.h"
+
#include <errno.h>
+#include <string.h>
#ifdef __POSIX__
-# include <unistd.h> // gethostname
+# include <unistd.h> // gethostname, sysconf
+# include <sys/utsname.h>
#else // __MINGW32__
# include <winsock2.h> // gethostname
#endif // __MINGW32__
@@ -30,13 +34,101 @@ static Handle<Value> GetHostname(const Arguments& args) {
return scope.Close(String::New(s));
}
+static Handle<Value> GetOSType(const Arguments& args) {
+ HandleScope scope;
+ char type[256];
+ struct utsname info;
+
+ uname(&info);
+ strncpy(type, info.sysname, strlen(info.sysname));
+ type[strlen(info.sysname)] = 0;
+
+ return scope.Close(String::New(type));
+}
+
+static Handle<Value> GetOSRelease(const Arguments& args) {
+ HandleScope scope;
+ char release[256];
+ struct utsname info;
+
+ uname(&info);
+ strncpy(release, info.release, strlen(info.release));
+ release[strlen(info.release)] = 0;
+
+ return scope.Close(String::New(release));
+}
+
+static Handle<Value> GetCPUInfo(const Arguments& args) {
+ HandleScope scope;
+ Local<Array> cpus;
+ int r = Platform::GetCPUInfo(&cpus);
+
+ if (r < 0) {
+ return Undefined();
+ }
+
+ return scope.Close(cpus);
+}
+
+static Handle<Value> GetFreeMemory(const Arguments& args) {
+ HandleScope scope;
+ double amount = Platform::GetFreeMemory();
+
+ if (amount < 0) {
+ return Undefined();
+ }
+
+ return scope.Close(Number::New(amount));
+}
+
+static Handle<Value> GetTotalMemory(const Arguments& args) {
+ HandleScope scope;
+ double amount = Platform::GetTotalMemory();
+
+ if (amount < 0) {
+ return Undefined();
+ }
+
+ return scope.Close(Number::New(amount));
+}
+
+static Handle<Value> GetUptime(const Arguments& args) {
+ HandleScope scope;
+ double uptime = Platform::GetUptime();
+
+ if (uptime < 0) {
+ return Undefined();
+ }
+
+ return scope.Close(Number::New(uptime));
+}
+
+static Handle<Value> GetLoadAvg(const Arguments& args) {
+ HandleScope scope;
+ Local<Array> loads = Array::New(3);
+ int r = Platform::GetLoadAvg(&loads);
+
+ if (r < 0) {
+ return Undefined();
+ }
+
+ return scope.Close(loads);
+}
+
void OS::Initialize(v8::Handle<v8::Object> target) {
HandleScope scope;
NODE_SET_METHOD(target, "getHostname", GetHostname);
+ NODE_SET_METHOD(target, "getLoadAvg", GetLoadAvg);
+ NODE_SET_METHOD(target, "getUptime", GetUptime);
+ NODE_SET_METHOD(target, "getTotalMem", GetTotalMemory);
+ NODE_SET_METHOD(target, "getFreeMem", GetFreeMemory);
+ NODE_SET_METHOD(target, "getCPUs", GetCPUInfo);
+ NODE_SET_METHOD(target, "getOSType", GetOSType);
+ NODE_SET_METHOD(target, "getOSRelease", GetOSRelease);
}
} // namespace node
-NODE_MODULE(node_os, node::OS::Initialize);
+NODE_MODULE(node_os, node::OS::Initialize); \ No newline at end of file
diff --git a/src/node_script.cc b/src/node_script.cc
index 5c4223d10e4..609b6166227 100644
--- a/src/node_script.cc
+++ b/src/node_script.cc
@@ -2,109 +2,198 @@
#include <node_script.h>
#include <assert.h>
+namespace node {
+using v8::Context;
+using v8::Script;
+using v8::Value;
+using v8::Handle;
+using v8::HandleScope;
+using v8::Object;
+using v8::Arguments;
+using v8::ThrowException;
+using v8::TryCatch;
+using v8::String;
+using v8::Exception;
+using v8::Local;
+using v8::Array;
+using v8::Persistent;
+using v8::Integer;
+using v8::FunctionTemplate;
-using namespace v8;
-using namespace node;
+class WrappedContext : ObjectWrap {
+ public:
+ static void Initialize(Handle<Object> target);
+ static Handle<Value> New(const Arguments& args);
-Persistent<FunctionTemplate> node::Context::constructor_template;
+ Persistent<Context> GetV8Context();
+ static Local<Object> NewInstance();
+ protected:
-void node::Context::Initialize (Handle<Object> target) {
+ static Persistent<FunctionTemplate> constructor_template;
+
+ WrappedContext();
+ ~WrappedContext();
+
+ Persistent<Context> context_;
+};
+
+
+Persistent<FunctionTemplate> WrappedContext::constructor_template;
+
+
+class WrappedScript : ObjectWrap {
+ public:
+ static void Initialize(Handle<Object> target);
+
+ enum EvalInputFlags { compileCode, unwrapExternal };
+ enum EvalContextFlags { thisContext, newContext, userContext };
+ enum EvalOutputFlags { returnResult, wrapExternal };
+
+ template <EvalInputFlags input_flag,
+ EvalContextFlags context_flag,
+ EvalOutputFlags output_flag>
+ static Handle<Value> EvalMachine(const Arguments& args);
+
+ protected:
+ static Persistent<FunctionTemplate> constructor_template;
+
+ WrappedScript() : ObjectWrap() {}
+ ~WrappedScript();
+
+ static Handle<Value> New(const Arguments& args);
+ static Handle<Value> CreateContext(const Arguments& arg);
+ static Handle<Value> RunInContext(const Arguments& args);
+ static Handle<Value> RunInThisContext(const Arguments& args);
+ static Handle<Value> RunInNewContext(const Arguments& args);
+ static Handle<Value> CompileRunInContext(const Arguments& args);
+ static Handle<Value> CompileRunInThisContext(const Arguments& args);
+ static Handle<Value> CompileRunInNewContext(const Arguments& args);
+
+ Persistent<Script> script_;
+};
+
+
+void WrappedContext::Initialize(Handle<Object> target) {
HandleScope scope;
- Local<FunctionTemplate> t = FunctionTemplate::New(node::Context::New);
+ Local<FunctionTemplate> t = FunctionTemplate::New(WrappedContext::New);
constructor_template = Persistent<FunctionTemplate>::New(t);
constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
constructor_template->SetClassName(String::NewSymbol("Context"));
- target->Set(String::NewSymbol("Context"), constructor_template->GetFunction());
+ target->Set(String::NewSymbol("Context"),
+ constructor_template->GetFunction());
}
-Handle<Value> node::Context::New (const Arguments& args) {
+Handle<Value> WrappedContext::New(const Arguments& args) {
HandleScope scope;
- node::Context *t = new node::Context();
+ WrappedContext *t = new WrappedContext();
t->Wrap(args.This());
return args.This();
}
-node::Context::Context() : ObjectWrap() {
- context_ = v8::Context::New();
+WrappedContext::WrappedContext() : ObjectWrap() {
+ context_ = Context::New();
}
-node::Context::~Context() {
+WrappedContext::~WrappedContext() {
context_.Dispose();
}
-Local<Object> node::Context::NewInstance() {
+Local<Object> WrappedContext::NewInstance() {
Local<Object> context = constructor_template->GetFunction()->NewInstance();
return context;
}
-v8::Persistent<v8::Context> node::Context::GetV8Context() {
- return context_;
+Persistent<Context> WrappedContext::GetV8Context() {
+ return context_;
}
-Persistent<FunctionTemplate> node::Script::constructor_template;
+Persistent<FunctionTemplate> WrappedScript::constructor_template;
-void node::Script::Initialize (Handle<Object> target) {
+void WrappedScript::Initialize(Handle<Object> target) {
HandleScope scope;
- Local<FunctionTemplate> t = FunctionTemplate::New(node::Script::New);
+ Local<FunctionTemplate> t = FunctionTemplate::New(WrappedScript::New);
constructor_template = Persistent<FunctionTemplate>::New(t);
constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
constructor_template->SetClassName(String::NewSymbol("Script"));
- NODE_SET_PROTOTYPE_METHOD(constructor_template, "createContext", node::Script::CreateContext);
- NODE_SET_PROTOTYPE_METHOD(constructor_template, "runInContext", node::Script::RunInContext);
- NODE_SET_PROTOTYPE_METHOD(constructor_template, "runInThisContext", node::Script::RunInThisContext);
- NODE_SET_PROTOTYPE_METHOD(constructor_template, "runInNewContext", node::Script::RunInNewContext);
- NODE_SET_METHOD(constructor_template, "createContext", node::Script::CreateContext);
- NODE_SET_METHOD(constructor_template, "runInContext", node::Script::CompileRunInContext);
- NODE_SET_METHOD(constructor_template, "runInThisContext", node::Script::CompileRunInThisContext);
- NODE_SET_METHOD(constructor_template, "runInNewContext", node::Script::CompileRunInNewContext);
+ NODE_SET_PROTOTYPE_METHOD(constructor_template,
+ "createContext",
+ WrappedScript::CreateContext);
+
+ NODE_SET_PROTOTYPE_METHOD(constructor_template,
+ "runInContext",
+ WrappedScript::RunInContext);
- target->Set(String::NewSymbol("Script"), constructor_template->GetFunction());
+ NODE_SET_PROTOTYPE_METHOD(constructor_template,
+ "runInThisContext",
+ WrappedScript::RunInThisContext);
+
+ NODE_SET_PROTOTYPE_METHOD(constructor_template,
+ "runInNewContext",
+ WrappedScript::RunInNewContext);
+
+ NODE_SET_METHOD(constructor_template,
+ "createContext",
+ WrappedScript::CreateContext);
+
+ NODE_SET_METHOD(constructor_template,
+ "runInContext",
+ WrappedScript::CompileRunInContext);
+
+ NODE_SET_METHOD(constructor_template,
+ "runInThisContext",
+ WrappedScript::CompileRunInThisContext);
+
+ NODE_SET_METHOD(constructor_template,
+ "runInNewContext",
+ WrappedScript::CompileRunInNewContext);
+
+ target->Set(String::NewSymbol("Script"),
+ constructor_template->GetFunction());
}
-Handle<Value> node::Script::New (const Arguments& args) {
+Handle<Value> WrappedScript::New(const Arguments& args) {
if (!args.IsConstructCall()) {
return FromConstructorTemplate(constructor_template, args);
}
HandleScope scope;
- node::Script *t = new node::Script();
+ WrappedScript *t = new WrappedScript();
t->Wrap(args.Holder());
return
- node::Script::EvalMachine<compileCode, thisContext, wrapExternal>(args);
+ WrappedScript::EvalMachine<compileCode, thisContext, wrapExternal>(args);
}
-node::Script::~Script() {
+WrappedScript::~WrappedScript() {
script_.Dispose();
}
-Handle<Value> node::Script::CreateContext (const Arguments& args) {
+Handle<Value> WrappedScript::CreateContext(const Arguments& args) {
HandleScope scope;
- Local<v8::Object> context = node::Context::NewInstance();
+ Local<Object> context = WrappedContext::NewInstance();
if (args.Length() > 0) {
-
Local<Object> sandbox = args[0]->ToObject();
Local<Array> keys = sandbox->GetPropertyNames();
@@ -120,93 +209,102 @@ Handle<Value> node::Script::CreateContext (const Arguments& args) {
}
-Handle<Value> node::Script::RunInContext (const Arguments& args) {
+Handle<Value> WrappedScript::RunInContext(const Arguments& args) {
return
- node::Script::EvalMachine<unwrapExternal, userContext, returnResult>(args);
+ WrappedScript::EvalMachine<unwrapExternal, userContext, returnResult>(args);
}
-Handle<Value> node::Script::RunInThisContext (const Arguments& args) {
+Handle<Value> WrappedScript::RunInThisContext(const Arguments& args) {
return
- node::Script::EvalMachine<unwrapExternal, thisContext, returnResult>(args);
+ WrappedScript::EvalMachine<unwrapExternal, thisContext, returnResult>(args);
}
-Handle<Value> node::Script::RunInNewContext(const Arguments& args) {
+Handle<Value> WrappedScript::RunInNewContext(const Arguments& args) {
return
- node::Script::EvalMachine<unwrapExternal, newContext, returnResult>(args);
+ WrappedScript::EvalMachine<unwrapExternal, newContext, returnResult>(args);
}
-Handle<Value> node::Script::CompileRunInContext (const Arguments& args) {
+Handle<Value> WrappedScript::CompileRunInContext(const Arguments& args) {
return
- node::Script::EvalMachine<compileCode, userContext, returnResult>(args);
+ WrappedScript::EvalMachine<compileCode, userContext, returnResult>(args);
}
-Handle<Value> node::Script::CompileRunInThisContext (const Arguments& args) {
+Handle<Value> WrappedScript::CompileRunInThisContext(const Arguments& args) {
return
- node::Script::EvalMachine<compileCode, thisContext, returnResult>(args);
+ WrappedScript::EvalMachine<compileCode, thisContext, returnResult>(args);
}
-Handle<Value> node::Script::CompileRunInNewContext(const Arguments& args) {
+Handle<Value> WrappedScript::CompileRunInNewContext(const Arguments& args) {
return
- node::Script::EvalMachine<compileCode, newContext, returnResult>(args);
+ WrappedScript::EvalMachine<compileCode, newContext, returnResult>(args);
}
-template <node::Script::EvalInputFlags iFlag,
- node::Script::EvalContextFlags cFlag,
- node::Script::EvalOutputFlags oFlag>
- Handle<Value> node::Script::EvalMachine(const Arguments& args) {
-
+template <WrappedScript::EvalInputFlags input_flag,
+ WrappedScript::EvalContextFlags context_flag,
+ WrappedScript::EvalOutputFlags output_flag>
+Handle<Value> WrappedScript::EvalMachine(const Arguments& args) {
HandleScope scope;
- if (iFlag == compileCode && args.Length() < 1) {
+ if (input_flag == compileCode && args.Length() < 1) {
return ThrowException(Exception::TypeError(
String::New("needs at least 'code' argument.")));
}
- const int sbIndex = iFlag == compileCode ? 1 : 0;
- if (cFlag == userContext && args.Length() < (sbIndex + 1)) {
+ const int sandbox_index = input_flag == compileCode ? 1 : 0;
+ if (context_flag == userContext && args.Length() < (sandbox_index + 1)) {
return ThrowException(Exception::TypeError(
String::New("needs a 'context' argument.")));
}
Local<String> code;
- if (iFlag == compileCode) code = args[0]->ToString();
+ if (input_flag == compileCode) code = args[0]->ToString();
Local<Object> sandbox;
- if (cFlag == newContext) {
- sandbox = args[sbIndex]->IsObject() ? args[sbIndex]->ToObject() : Object::New();
- } else if (cFlag == userContext) {
- sandbox = args[sbIndex]->ToObject();
+ if (context_flag == newContext) {
+ sandbox = args[sandbox_index]->IsObject() ? args[sandbox_index]->ToObject()
+ : Object::New();
+ } else if (context_flag == userContext) {
+ sandbox = args[sandbox_index]->ToObject();
}
- const int fnIndex = sbIndex + (cFlag == newContext ? 1 : 0);
- Local<String> filename = args.Length() > fnIndex
- ? args[fnIndex]->ToString()
+ const int filename_index = sandbox_index +
+ (context_flag == newContext ? 1 : 0);
+ Local<String> filename = args.Length() > filename_index
+ ? args[filename_index]->ToString()
: String::New("evalmachine.<anonymous>");
- Persistent<v8::Context> context;
+ const int display_error_index = args.Length() - 1;
+ bool display_error = false;
+ if (args.Length() > display_error_index &&
+ args[display_error_index]->IsBoolean() &&
+ args[display_error_index]->BooleanValue() == true) {
+ display_error = true;
+ }
+
+ Persistent<Context> context;
Local<Array> keys;
unsigned int i;
- if (cFlag == newContext) {
+ if (context_flag == newContext) {
// Create the new context
- context = v8::Context::New();
+ context = Context::New();
- } else if (cFlag == userContext) {
+ } else if (context_flag == userContext) {
// Use the passed in context
- Local<Object> contextArg = args[sbIndex]->ToObject();
- node::Context *nContext = ObjectWrap::Unwrap<node::Context>(sandbox);
+ Local<Object> contextArg = args[sandbox_index]->ToObject();
+ WrappedContext *nContext = ObjectWrap::Unwrap<WrappedContext>(sandbox);
context = nContext->GetV8Context();
}
// New and user context share code. DRY it up.
- if (cFlag == userContext || cFlag == newContext) {
+ if (context_flag == userContext || context_flag == newContext) {
// Enter the context
context->Enter();
@@ -226,48 +324,49 @@ template <node::Script::EvalInputFlags iFlag,
TryCatch try_catch;
Handle<Value> result;
- Handle<v8::Script> script;
+ Handle<Script> script;
- if (iFlag == compileCode) {
- // well, here node::Script::New would suffice in all cases, but maybe
+ if (input_flag == compileCode) {
+ // well, here WrappedScript::New would suffice in all cases, but maybe
// Compile has a little better performance where possible
- script = oFlag == returnResult ? v8::Script::Compile(code, filename)
- : v8::Script::New(code, filename);
+ script = output_flag == returnResult ? Script::Compile(code, filename)
+ : Script::New(code, filename);
if (script.IsEmpty()) {
// FIXME UGLY HACK TO DISPLAY SYNTAX ERRORS.
- DisplayExceptionLine(try_catch);
+ if (display_error) DisplayExceptionLine(try_catch);
// Hack because I can't get a proper stacktrace on SyntaxError
return try_catch.ReThrow();
}
} else {
- node::Script *nScript = ObjectWrap::Unwrap<node::Script>(args.Holder());
- if (!nScript) {
+ WrappedScript *n_script = ObjectWrap::Unwrap<WrappedScript>(args.Holder());
+ if (!n_script) {
return ThrowException(Exception::Error(
String::New("Must be called as a method of Script.")));
- } else if (nScript->script_.IsEmpty()) {
+ } else if (n_script->script_.IsEmpty()) {
return ThrowException(Exception::Error(
- String::New("'this' must be a result of previous new Script(code) call.")));
+ String::New("'this' must be a result of previous "
+ "new Script(code) call.")));
}
- script = nScript->script_;
+ script = n_script->script_;
}
- if (oFlag == returnResult) {
+ if (output_flag == returnResult) {
result = script->Run();
if (result.IsEmpty()) return try_catch.ReThrow();
} else {
- node::Script *nScript = ObjectWrap::Unwrap<node::Script>(args.Holder());
- if (!nScript) {
+ WrappedScript *n_script = ObjectWrap::Unwrap<WrappedScript>(args.Holder());
+ if (!n_script) {
return ThrowException(Exception::Error(
String::New("Must be called as a method of Script.")));
}
- nScript->script_ = Persistent<v8::Script>::New(script);
+ n_script->script_ = Persistent<Script>::New(script);
result = args.This();
}
- if (cFlag == userContext || cFlag == newContext) {
+ if (context_flag == userContext || context_flag == newContext) {
// success! copy changes back onto the sandbox object.
keys = context->Global()->GetPropertyNames();
for (i = 0; i < keys->Length(); i++) {
@@ -278,12 +377,12 @@ template <node::Script::EvalInputFlags iFlag,
}
}
- if (cFlag == newContext) {
+ if (context_flag == newContext) {
// Clean up, clean up, everybody everywhere!
context->DetachGlobal();
context->Exit();
context.Dispose();
- } else if (cFlag == userContext) {
+ } else if (context_flag == userContext) {
// Exit the passed in context.
context->Exit();
}
@@ -291,11 +390,17 @@ template <node::Script::EvalInputFlags iFlag,
return result == args.This() ? result : scope.Close(result);
}
-void node::InitEvals(Handle<Object> target) {
+
+void InitEvals(Handle<Object> target) {
HandleScope scope;
- node::Context::Initialize(target);
- node::Script::Initialize(target);
+ WrappedContext::Initialize(target);
+ WrappedScript::Initialize(target);
}
+
+} // namespace node
+
+
NODE_MODULE(node_evals, node::InitEvals);
+
diff --git a/src/node_script.h b/src/node_script.h
index bd300459f51..364bd18ca8a 100644
--- a/src/node_script.h
+++ b/src/node_script.h
@@ -8,54 +8,6 @@
namespace node {
-class Context : ObjectWrap {
- public:
- static void Initialize (v8::Handle<v8::Object> target);
- static v8::Handle<v8::Value> New (const v8::Arguments& args);
-
- v8::Persistent<v8::Context> GetV8Context();
- static v8::Local<v8::Object> NewInstance();
-
- protected:
-
- static v8::Persistent<v8::FunctionTemplate> constructor_template;
-
- Context ();
- ~Context();
-
- v8::Persistent<v8::Context> context_;
-};
-
-
-class Script : ObjectWrap {
- public:
- static void Initialize (v8::Handle<v8::Object> target);
-
- enum EvalInputFlags { compileCode, unwrapExternal };
- enum EvalContextFlags { thisContext, newContext, userContext };
- enum EvalOutputFlags { returnResult, wrapExternal };
-
- template <EvalInputFlags iFlag, EvalContextFlags cFlag, EvalOutputFlags oFlag>
- static v8::Handle<v8::Value> EvalMachine(const v8::Arguments& args);
-
- protected:
- static v8::Persistent<v8::FunctionTemplate> constructor_template;
-
- Script () : ObjectWrap () {}
- ~Script();
-
- static v8::Handle<v8::Value> New (const v8::Arguments& args);
- static v8::Handle<v8::Value> CreateContext (const v8::Arguments& arg);
- static v8::Handle<v8::Value> RunInContext (const v8::Arguments& args);
- static v8::Handle<v8::Value> RunInThisContext (const v8::Arguments& args);
- static v8::Handle<v8::Value> RunInNewContext (const v8::Arguments& args);
- static v8::Handle<v8::Value> CompileRunInContext (const v8::Arguments& args);
- static v8::Handle<v8::Value> CompileRunInThisContext (const v8::Arguments& args);
- static v8::Handle<v8::Value> CompileRunInNewContext (const v8::Arguments& args);
-
- v8::Persistent<v8::Script> script_;
-};
-
void InitEvals(v8::Handle<v8::Object> target);
diff --git a/src/platform.h b/src/platform.h
index f0252307257..bf7cd52fa3a 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -1,9 +1,11 @@
#ifndef NODE_PLATFORM_H_
#define NODE_PLATFORM_H_
+#include <v8.h>
+
namespace node {
-class OS {
+class Platform {
public:
static char** SetupArgs(int argc, char *argv[]);
static void SetProcessTitle(char *title);
@@ -11,6 +13,11 @@ class OS {
static int GetMemory(size_t *rss, size_t *vsize);
static int GetExecutablePath(char* buffer, size_t* size);
+ static int GetCPUInfo(v8::Local<v8::Array> *cpus);
+ static double GetFreeMemory();
+ static double GetTotalMemory();
+ static double GetUptime();
+ static int GetLoadAvg(v8::Local<v8::Array> *loads);
};
diff --git a/src/platform_cygwin.cc b/src/platform_cygwin.cc
index 2c874c74b7d..416cb1735fb 100644
--- a/src/platform_cygwin.cc
+++ b/src/platform_cygwin.cc
@@ -1,13 +1,21 @@
#include "node.h"
#include "platform.h"
+#include <v8.h>
+
#include <sys/param.h> // for MAXPATHLEN
-#include <unistd.h> // getpagesize
+#include <sys/sysinfo.h>
+#include <unistd.h> // getpagesize, sysconf
+#include <stdio.h> // sscanf, snprintf
+#include <string.h>
+
#include <windows.h>
namespace node {
+using namespace v8;
+
static char buf[MAXPATHLEN + 1];
static char *process_title = NULL;
@@ -30,12 +38,12 @@ static void _winapi_perror(const char* prefix = NULL) {
}
-char** OS::SetupArgs(int argc, char *argv[]) {
+char** Platform::SetupArgs(int argc, char *argv[]) {
return argv;
}
-void OS::SetProcessTitle(char *title) {
+void Platform::SetProcessTitle(char *title) {
// We need to convert _title_ to UTF-16 first, because that's what windows uses internally.
// It would be more efficient to use the UTF-16 value that we can obtain from v8,
// but it's not accessible from here.
@@ -139,7 +147,7 @@ static inline char* _getProcessTitle() {
}
-const char* OS::GetProcessTitle(int *len) {
+const char* Platform::GetProcessTitle(int *len) {
// If the process_title was never read before nor explicitly set,
// we must query it with getConsoleTitleW
if (!process_title) {
@@ -156,7 +164,7 @@ const char* OS::GetProcessTitle(int *len) {
}
-int OS::GetMemory(size_t *rss, size_t *vsize) {
+int Platform::GetMemory(size_t *rss, size_t *vsize) {
FILE *f = fopen("/proc/self/stat", "r");
if (!f) return -1;
@@ -236,11 +244,115 @@ error:
}
-int OS::GetExecutablePath(char* buffer, size_t* size) {
+int Platform::GetExecutablePath(char* buffer, size_t* size) {
*size = readlink("/proc/self/exe", buffer, *size - 1);
if (*size <= 0) return -1;
buffer[*size] = '\0';
return 0;
}
+int Platform::GetCPUInfo(Local<Array> *cpus) {
+ Local<Object> cpuinfo;
+ Local<Object> cputimes;
+ unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK),
+ multiplier = ((uint64_t)1000L / ticks), cpuspeed;
+ int numcpus = 0, i = 0;
+ unsigned long long ticks_user, ticks_sys, ticks_idle, ticks_nice, ticks_intr;
+ char line[512], speedPath[256], model[512];
+ FILE *fpStat = fopen("/proc/stat", "r");
+ FILE *fpModel = fopen("/proc/cpuinfo", "r");
+ FILE *fpSpeed;
+
+ if (fpModel) {
+ while (fgets(line, 511, fpModel) != NULL) {
+ if (strncmp(line, "model name", 10) == 0) {
+ numcpus++;
+ if (numcpus == 1) {
+ char *p = strchr(line, ':') + 2;
+ strcpy(model, p);
+ model[strlen(model)-1] = 0;
+ }
+ } else if (strncmp(line, "cpu MHz", 7) == 0) {
+ if (numcpus == 1) {
+ sscanf(line, "%*s %*s : %u", &cpuspeed);
+ }
+ }
+ }
+ fclose(fpModel);
+ }
+
+ *cpus = Array::New(numcpus);
+
+ if (fpStat) {
+ while (fgets(line, 511, fpStat) != NULL) {
+ if (strncmp(line, "cpu ", 4) == 0)
+ continue;
+ else if (strncmp(line, "intr ", 5) == 0)
+ break;
+ sscanf(line, "%*s %llu %llu %llu %llu",
+ &ticks_user, &ticks_nice, &ticks_sys, &ticks_idle);
+ snprintf(speedPath, sizeof(speedPath),
+ "/sys/devices/system/cpu/cpu%u/cpufreq/cpuinfo_max_freq", i);
+ fpSpeed = fopen(speedPath, "r");
+ if (fpSpeed) {
+ if (fgets(line, 511, fpSpeed) != NULL) {
+ sscanf(line, "%u", &cpuspeed);
+ cpuspeed /= 1000;
+ }
+ fclose(fpSpeed);
+ }
+ cpuinfo = Object::New();
+ cputimes = Object::New();
+ cputimes->Set(String::New("user"), Number::New(ticks_user * multiplier));
+ cputimes->Set(String::New("nice"), Number::New(ticks_nice * multiplier));
+ cputimes->Set(String::New("sys"), Number::New(ticks_sys * multiplier));
+ cputimes->Set(String::New("idle"), Number::New(ticks_idle * multiplier));
+ cputimes->Set(String::New("irq"), Number::New(0));
+
+ cpuinfo->Set(String::New("model"), String::New(model));
+ cpuinfo->Set(String::New("speed"), Number::New(cpuspeed));
+
+ cpuinfo->Set(String::New("times"), cputimes);
+ (*cpus)->Set(i++, cpuinfo);
+ }
+ fclose(fpStat);
+ }
+
+ return 0;
+}
+
+double Platform::GetFreeMemory() {
+ double pagesize = static_cast<double>(sysconf(_SC_PAGESIZE));
+ double pages = static_cast<double>(sysconf(_SC_AVPHYS_PAGES));
+
+ return static_cast<double>(pages * pagesize);
+}
+
+double Platform::GetTotalMemory() {
+ double pagesize = static_cast<double>(sysconf(_SC_PAGESIZE));
+ double pages = static_cast<double>(sysconf(_SC_PHYS_PAGES));
+
+ return pages * pagesize;
+}
+
+double Platform::GetUptime() {
+ double amount;
+ char line[512];
+ FILE *fpUptime = fopen("/proc/uptime", "r");
+
+ if (fpUptime) {
+ if (fgets(line, 511, fpUptime) != NULL) {
+ sscanf(line, "%lf %*lf", &amount);
+ }
+ fclose(fpUptime);
+ }
+
+ return amount;
+}
+
+int Platform::GetLoadAvg(Local<Array> *loads) {
+ // Unsupported as of cygwin 1.7.7
+ return -1;
+}
+
} // namespace node
diff --git a/src/platform_darwin.cc b/src/platform_darwin.cc
index f02dc494a39..828d5110564 100644
--- a/src/platform_darwin.cc
+++ b/src/platform_darwin.cc
@@ -1,27 +1,38 @@
#include "node.h"
#include "platform.h"
+#include <v8.h>
+
#include <mach/task.h>
-#include <mach/mach_init.h>
+#include <mach/mach.h>
+#include <mach/mach_host.h>
#include <mach-o/dyld.h> /* _NSGetExecutablePath */
#include <limits.h> /* PATH_MAX */
+#include <unistd.h> // sysconf
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <time.h>
+
namespace node {
+
+using namespace v8;
+
static char *process_title;
-char** OS::SetupArgs(int argc, char *argv[]) {
+char** Platform::SetupArgs(int argc, char *argv[]) {
process_title = argc ? strdup(argv[0]) : NULL;
return argv;
}
-// OS::SetProcessTitle implemented in platform_darwin_proctitle.cc
+// Platform::SetProcessTitle implemented in platform_darwin_proctitle.cc
} // namespace node
#include "platform_darwin_proctitle.cc"
namespace node {
-const char* OS::GetProcessTitle(int *len) {
+const char* Platform::GetProcessTitle(int *len) {
if (process_title) {
*len = strlen(process_title);
return process_title;
@@ -32,7 +43,7 @@ const char* OS::GetProcessTitle(int *len) {
// Researched by Tim Becker and Michael Knight
// http://blog.kuriositaet.de/?p=257
-int OS::GetMemory(size_t *rss, size_t *vsize) {
+int Platform::GetMemory(size_t *rss, size_t *vsize) {
struct task_basic_info t_info;
mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
@@ -50,7 +61,7 @@ int OS::GetMemory(size_t *rss, size_t *vsize) {
}
-int OS::GetExecutablePath(char* buffer, size_t* size) {
+int Platform::GetExecutablePath(char* buffer, size_t* size) {
uint32_t usize = *size;
int result = _NSGetExecutablePath(buffer, &usize);
if (result) return result;
@@ -68,4 +79,112 @@ int OS::GetExecutablePath(char* buffer, size_t* size) {
return 0;
}
+int Platform::GetCPUInfo(Local<Array> *cpus) {
+ Local<Object> cpuinfo;
+ Local<Object> cputimes;
+ unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK),
+ multiplier = ((uint64_t)1000L / ticks);
+ char model[512];
+ uint64_t cpuspeed;
+ size_t size;
+
+ size = sizeof(model);
+ if (sysctlbyname("hw.model", &model, &size, NULL, 0) < 0) {
+ return -1;
+ }
+ size = sizeof(cpuspeed);
+ if (sysctlbyname("hw.cpufrequency", &cpuspeed, &size, NULL, 0) < 0) {
+ return -1;
+ }
+
+ natural_t numcpus;
+ mach_msg_type_number_t count;
+ processor_cpu_load_info_data_t *info;
+ if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numcpus,
+ reinterpret_cast<processor_info_array_t*>(&info),
+ &count) != KERN_SUCCESS) {
+ return -1;
+ }
+ *cpus = Array::New(numcpus);
+ for (int i = 0; i < numcpus; i++) {
+ cpuinfo = Object::New();
+ cputimes = Object::New();
+ cputimes->Set(String::New("user"),
+ Number::New((uint64_t)(info[i].cpu_ticks[0]) * multiplier));
+ cputimes->Set(String::New("nice"),
+ Number::New((uint64_t)(info[i].cpu_ticks[3]) * multiplier));
+ cputimes->Set(String::New("sys"),
+ Number::New((uint64_t)(info[i].cpu_ticks[1]) * multiplier));
+ cputimes->Set(String::New("idle"),
+ Number::New((uint64_t)(info[i].cpu_ticks[2]) * multiplier));
+ cputimes->Set(String::New("irq"), Number::New(0));
+
+ cpuinfo->Set(String::New("model"), String::New(model));
+ cpuinfo->Set(String::New("speed"), Number::New(cpuspeed/1000000));
+
+ cpuinfo->Set(String::New("times"), cputimes);
+ (*cpus)->Set(i, cpuinfo);
+ }
+ vm_deallocate(mach_task_self(), (vm_address_t)info, count);
+
+ return 0;
+}
+
+double Platform::GetFreeMemory() {
+ double pagesize = static_cast<double>(sysconf(_SC_PAGESIZE));
+ vm_statistics_data_t info;
+ mach_msg_type_number_t count = sizeof(info) / sizeof(integer_t);
+
+ if (host_statistics(mach_host_self(), HOST_VM_INFO,
+ (host_info_t)&info, &count) != KERN_SUCCESS) {
+ return -1;
+ }
+
+ return (static_cast<double>(info.free_count)) * pagesize;
+}
+
+double Platform::GetTotalMemory() {
+ uint64_t info;
+ static int which[] = {CTL_HW, HW_MEMSIZE};
+ size_t size = sizeof(info);
+
+ if (sysctl(which, 2, &info, &size, NULL, 0) < 0) {
+ return -1;
+ }
+
+ return static_cast<double>(info);
+}
+
+double Platform::GetUptime() {
+ time_t now;
+ struct timeval info;
+ size_t size = sizeof(info);
+ static int which[] = {CTL_KERN, KERN_BOOTTIME};
+
+ if (sysctl(which, 2, &info, &size, NULL, 0) < 0) {
+ return -1;
+ }
+ now = time(NULL);
+
+ return static_cast<double>(now - info.tv_sec);
+}
+
+int Platform::GetLoadAvg(Local<Array> *loads) {
+ struct loadavg info;
+ size_t size = sizeof(info);
+ static int which[] = {CTL_VM, VM_LOADAVG};
+
+ if (sysctl(which, 2, &info, &size, NULL, 0) < 0) {
+ return -1;
+ }
+ (*loads)->Set(0, Number::New(static_cast<double>(info.ldavg[0])
+ / static_cast<double>(info.fscale)));
+ (*loads)->Set(1, Number::New(static_cast<double>(info.ldavg[1])
+ / static_cast<double>(info.fscale)));
+ (*loads)->Set(2, Number::New(static_cast<double>(info.ldavg[2])
+ / static_cast<double>(info.fscale)));
+
+ return 0;
+}
+
} // namespace node
diff --git a/src/platform_darwin_proctitle.cc b/src/platform_darwin_proctitle.cc
index 6c58ae1c948..e6a1ddd371d 100644
--- a/src/platform_darwin_proctitle.cc
+++ b/src/platform_darwin_proctitle.cc
@@ -38,7 +38,7 @@
namespace node {
-void OS::SetProcessTitle(char *title) {
+void Platform::SetProcessTitle(char *title) {
static int symbol_lookup_status = 0; // 1=ok, 2=unavailable
if (symbol_lookup_status == 2) {
// feature is unavailable
diff --git a/src/platform_freebsd.cc b/src/platform_freebsd.cc
index 0c8b2599f91..6eb5ca2903a 100644
--- a/src/platform_freebsd.cc
+++ b/src/platform_freebsd.cc
@@ -1,33 +1,41 @@
#include "node.h"
#include "platform.h"
+#include <v8.h>
+
#include <stdlib.h>
#include <kvm.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/user.h>
+#include <sys/dkstat.h>
+#include <vm/vm_param.h>
#include <string.h>
#include <paths.h>
#include <fcntl.h>
#include <unistd.h>
+#include <time.h>
namespace node {
+
+using namespace v8;
+
static char *process_title;
-char** OS::SetupArgs(int argc, char *argv[]) {
+char** Platform::SetupArgs(int argc, char *argv[]) {
process_title = argc ? strdup(argv[0]) : NULL;
return argv;
}
-void OS::SetProcessTitle(char *title) {
+void Platform::SetProcessTitle(char *title) {
if (process_title) free(process_title);
process_title = strdup(title);
setproctitle(title);
}
-const char* OS::GetProcessTitle(int *len) {
+const char* Platform::GetProcessTitle(int *len) {
if (process_title) {
*len = strlen(process_title);
return process_title;
@@ -36,7 +44,7 @@ const char* OS::GetProcessTitle(int *len) {
return NULL;
}
-int OS::GetMemory(size_t *rss, size_t *vsize) {
+int Platform::GetMemory(size_t *rss, size_t *vsize) {
kvm_t *kd = NULL;
struct kinfo_proc *kinfo = NULL;
pid_t pid;
@@ -64,7 +72,7 @@ error:
}
-int OS::GetExecutablePath(char* buffer, size_t* size) {
+int Platform::GetExecutablePath(char* buffer, size_t* size) {
int mib[4];
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
@@ -78,4 +86,125 @@ int OS::GetExecutablePath(char* buffer, size_t* size) {
return 0;
}
+int Platform::GetCPUInfo(Local<Array> *cpus) {
+ Local<Object> cpuinfo;
+ Local<Object> cputimes;
+ unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK),
+ multiplier = ((uint64_t)1000L / ticks), cpuspeed, maxcpus,
+ cur = 0;
+ char model[512];
+ int numcpus;
+ size_t size;
+
+ size = sizeof(model);
+ if (sysctlbyname("hw.model", &model, &size, NULL, 0) < 0) {
+ return -1;
+ }
+ size = sizeof(numcpus);
+ if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0) < 0) {
+ return -1;
+ }
+
+ *cpus = Array::New(numcpus);
+
+ size = sizeof(cpuspeed);
+ if (sysctlbyname("hw.clockrate", &cpuspeed, &size, NULL, 0) < 0) {
+ return -1;
+ }
+ // kern.cp_times on FreeBSD i386 gives an array up to maxcpus instead of ncpu
+ size = sizeof(maxcpus);
+ if (sysctlbyname("kern.smp.maxcpus", &maxcpus, &size, NULL, 0) < 0) {
+ return -1;
+ }
+ size = maxcpus * CPUSTATES * sizeof(long);
+ long cp_times[size];
+ if (sysctlbyname("kern.cp_times", &cp_times, &size, NULL, 0) < 0) {
+ return -1;
+ }
+ for (int i = 0; i < numcpus; i++) {
+ cpuinfo = Object::New();
+ cputimes = Object::New();
+ cputimes->Set(String::New("user"),
+ Number::New((uint64_t)(cp_times[CP_USER+cur]) * multiplier));
+ cputimes->Set(String::New("nice"),
+ Number::New((uint64_t)(cp_times[CP_NICE+cur]) * multiplier));
+ cputimes->Set(String::New("sys"),
+ Number::New((uint64_t)(cp_times[CP_SYS+cur]) * multiplier));
+ cputimes->Set(String::New("idle"),
+ Number::New((uint64_t)(cp_times[CP_IDLE+cur]) * multiplier));
+ cputimes->Set(String::New("irq"),
+ Number::New((uint64_t)(cp_times[CP_INTR+cur]) * multiplier));
+
+ cpuinfo->Set(String::New("model"), String::New(model));
+ cpuinfo->Set(String::New("speed"), Number::New(cpuspeed));
+
+ cpuinfo->Set(String::New("times"), cputimes);
+ (*cpus)->Set(i, cpuinfo);
+ cur+=CPUSTATES;
+ }
+
+ return 0;
+}
+
+double Platform::GetFreeMemory() {
+ double pagesize = static_cast<double>(sysconf(_SC_PAGESIZE));
+ unsigned long info;
+ size_t size = sizeof(info);
+
+ if (sysctlbyname("vm.stats.vm.v_free_count", &info, &size, NULL, 0) < 0) {
+ return -1;
+ }
+
+ return (static_cast<double>(info)) * pagesize;
+}
+
+double Platform::GetTotalMemory() {
+#if defined(HW_PHYSMEM64)
+ uint64_t info;
+ static int which[] = {CTL_HW, HW_PHYSMEM64};
+#else
+ unsigned int info;
+ static int which[] = {CTL_HW, HW_PHYSMEM};
+#endif
+ size_t size = sizeof(info);
+
+ if (sysctl(which, 2, &info, &size, NULL, 0) < 0) {
+ return -1;
+ }
+
+ return static_cast<double>(info);
+}
+
+double Platform::GetUptime() {
+ time_t now;
+ struct timeval info;
+ size_t size = sizeof(info);
+ static int which[] = {CTL_KERN, KERN_BOOTTIME};
+
+ if (sysctl(which, 2, &info, &size, NULL, 0) < 0) {
+ return -1;
+ }
+ now = time(NULL);
+
+ return static_cast<double>(now - info.tv_sec);
+}
+
+int Platform::GetLoadAvg(Local<Array> *loads) {
+ struct loadavg info;
+ size_t size = sizeof(info);
+ static int which[] = {CTL_VM, VM_LOADAVG};
+
+ if (sysctl(which, 2, &info, &size, NULL, 0) < 0) {
+ return -1;
+ }
+ (*loads)->Set(0, Number::New(static_cast<double>(info.ldavg[0])
+ / static_cast<double>(info.fscale)));
+ (*loads)->Set(1, Number::New(static_cast<double>(info.ldavg[1])
+ / static_cast<double>(info.fscale)));
+ (*loads)->Set(2, Number::New(static_cast<double>(info.ldavg[2])
+ / static_cast<double>(info.fscale)));
+
+ return 0;
+}
+
} // namespace node
diff --git a/src/platform_linux.cc b/src/platform_linux.cc
index 9c4ccc4c99e..00732a0c03e 100644
--- a/src/platform_linux.cc
+++ b/src/platform_linux.cc
@@ -1,8 +1,13 @@
#include "node.h"
#include "platform.h"
+#include <v8.h>
+
#include <sys/param.h> // for MAXPATHLEN
-#include <unistd.h> // getpagesize
+#include <sys/sysctl.h>
+#include <sys/sysinfo.h>
+#include <unistd.h> // getpagesize, sysconf
+#include <stdio.h> // sscanf, snprintf
/* SetProcessTitle */
#include <sys/prctl.h>
@@ -10,27 +15,28 @@
#include <stdlib.h> // free
#include <string.h> // strdup
-
namespace node {
+using namespace v8;
+
static char buf[MAXPATHLEN + 1];
static char *process_title;
-char** OS::SetupArgs(int argc, char *argv[]) {
+char** Platform::SetupArgs(int argc, char *argv[]) {
process_title = strdup(argv[0]);
return argv;
}
-void OS::SetProcessTitle(char *title) {
+void Platform::SetProcessTitle(char *title) {
if (process_title) free(process_title);
process_title = strdup(title);
prctl(PR_SET_NAME, process_title);
}
-const char* OS::GetProcessTitle(int *len) {
+const char* Platform::GetProcessTitle(int *len) {
if (process_title) {
*len = strlen(process_title);
return process_title;
@@ -40,7 +46,7 @@ const char* OS::GetProcessTitle(int *len) {
}
-int OS::GetMemory(size_t *rss, size_t *vsize) {
+int Platform::GetMemory(size_t *rss, size_t *vsize) {
FILE *f = fopen("/proc/self/stat", "r");
if (!f) return -1;
@@ -135,11 +141,119 @@ error:
}
-int OS::GetExecutablePath(char* buffer, size_t* size) {
+int Platform::GetExecutablePath(char* buffer, size_t* size) {
*size = readlink("/proc/self/exe", buffer, *size - 1);
if (*size <= 0) return -1;
buffer[*size] = '\0';
return 0;
}
+int Platform::GetCPUInfo(Local<Array> *cpus) {
+ HandleScope scope;
+ Local<Object> cpuinfo;
+ Local<Object> cputimes;
+ unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK),
+ multiplier = ((uint64_t)1000L / ticks), cpuspeed;
+ int numcpus = 0, i = 0;
+ unsigned long long ticks_user, ticks_sys, ticks_idle, ticks_nice, ticks_intr;
+ char line[512], speedPath[256], model[512];
+ FILE *fpStat = fopen("/proc/stat", "r");
+ FILE *fpModel = fopen("/proc/cpuinfo", "r");
+ FILE *fpSpeed;
+
+ if (fpModel) {
+ while (fgets(line, 511, fpModel) != NULL) {
+ if (strncmp(line, "model name", 10) == 0) {
+ numcpus++;
+ if (numcpus == 1) {
+ char *p = strchr(line, ':') + 2;
+ strcpy(model, p);
+ model[strlen(model)-1] = 0;
+ }
+ } else if (strncmp(line, "cpu MHz", 7) == 0) {
+ if (numcpus == 1) {
+ sscanf(line, "%*s %*s : %u", &cpuspeed);
+ }
+ }
+ }
+ fclose(fpModel);
+ }
+
+ *cpus = Array::New(numcpus);
+
+ if (fpStat) {
+ while (fgets(line, 511, fpStat) != NULL) {
+ if (strncmp(line, "cpu ", 4) == 0)
+ continue;
+ else if (strncmp(line, "intr ", 5) == 0)
+ break;
+ sscanf(line, "%*s %llu %llu %llu %llu %*llu %llu",
+ &ticks_user, &ticks_nice, &ticks_sys, &ticks_idle, &ticks_intr);
+ snprintf(speedPath, sizeof(speedPath),
+ "/sys/devices/system/cpu/cpu%u/cpufreq/cpuinfo_max_freq", i);
+ fpSpeed = fopen(speedPath, "r");
+ if (fpSpeed) {
+ if (fgets(line, 511, fpSpeed) != NULL) {
+ sscanf(line, "%u", &cpuspeed);
+ cpuspeed /= 1000;
+ }
+ fclose(fpSpeed);
+ }
+ cpuinfo = Object::New();
+ cputimes = Object::New();
+ cputimes->Set(String::New("user"), Number::New(ticks_user * multiplier));
+ cputimes->Set(String::New("nice"), Number::New(ticks_nice * multiplier));
+ cputimes->Set(String::New("sys"), Number::New(ticks_sys * multiplier));
+ cputimes->Set(String::New("idle"), Number::New(ticks_idle * multiplier));
+ cputimes->Set(String::New("irq"), Number::New(ticks_intr * multiplier));
+
+ cpuinfo->Set(String::New("model"), String::New(model));
+ cpuinfo->Set(String::New("speed"), Number::New(cpuspeed));
+
+ cpuinfo->Set(String::New("times"), cputimes);
+ (*cpus)->Set(i++, cpuinfo);
+ }
+ fclose(fpStat);
+ }
+
+ return 0;
+}
+
+double Platform::GetFreeMemory() {
+ double pagesize = static_cast<double>(sysconf(_SC_PAGESIZE));
+ double pages = static_cast<double>(sysconf(_SC_AVPHYS_PAGES));
+
+ return static_cast<double>(pages * pagesize);
+}
+
+double Platform::GetTotalMemory() {
+ double pagesize = static_cast<double>(sysconf(_SC_PAGESIZE));
+ double pages = static_cast<double>(sysconf(_SC_PHYS_PAGES));
+
+ return pages * pagesize;
+}
+
+double Platform::GetUptime() {
+ struct sysinfo info;
+
+ if (sysinfo(&info) < 0) {
+ return -1;
+ }
+
+ return static_cast<double>(info.uptime);
+}
+
+int Platform::GetLoadAvg(Local<Array> *loads) {
+ struct sysinfo info;
+
+ if (sysinfo(&info) < 0) {
+ return -1;
+ }
+ (*loads)->Set(0, Number::New(static_cast<double>(info.loads[0]) / 65536.0));
+ (*loads)->Set(1, Number::New(static_cast<double>(info.loads[1]) / 65536.0));
+ (*loads)->Set(2, Number::New(static_cast<double>(info.loads[2]) / 65536.0));
+
+ return 0;
+}
+
} // namespace node
diff --git a/src/platform_openbsd.cc b/src/platform_openbsd.cc
new file mode 100644
index 00000000000..b8a3209bcd7
--- /dev/null
+++ b/src/platform_openbsd.cc
@@ -0,0 +1,201 @@
+#include "node.h"
+#include "platform.h"
+
+#include <v8.h>
+
+#include <stdlib.h>
+#include <kvm.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <sys/dkstat.h>
+#include <uvm/uvm_param.h>
+#include <string.h>
+#include <paths.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <time.h>
+
+#include <stdio.h>
+namespace node {
+
+using namespace v8;
+
+static char *process_title;
+
+char** Platform::SetupArgs(int argc, char *argv[]) {
+ process_title = argc ? strdup(argv[0]) : NULL;
+ return argv;
+}
+
+
+void Platform::SetProcessTitle(char *title) {
+ if (process_title) free(process_title);
+ process_title = strdup(title);
+ setproctitle(title);
+}
+
+const char* Platform::GetProcessTitle(int *len) {
+ if (process_title) {
+ *len = strlen(process_title);
+ return process_title;
+ }
+ *len = 0;
+ return NULL;
+}
+
+int Platform::GetMemory(size_t *rss, size_t *vsize) {
+ kvm_t *kd = NULL;
+ struct kinfo_proc2 *kinfo = NULL;
+ pid_t pid;
+ int nprocs, max_size = sizeof(struct kinfo_proc2);
+ size_t page_size = getpagesize();
+
+ pid = getpid();
+
+ kd = kvm_open(NULL, _PATH_MEM, NULL, O_RDONLY, "kvm_open");
+ if (kd == NULL) goto error;
+
+ kinfo = kvm_getproc2(kd, KERN_PROC_PID, pid, max_size, &nprocs);
+ if (kinfo == NULL) goto error;
+
+ *rss = kinfo->p_vm_rssize * page_size;
+ *vsize = kinfo->p_uru_ixrss;
+
+ kvm_close(kd);
+
+ return 0;
+
+error:
+ if (kd) kvm_close(kd);
+ return -1;
+}
+
+
+int Platform::GetExecutablePath(char* buffer, size_t* size) {
+ *size = 0;
+ return -1;
+}
+
+int Platform::GetCPUInfo(Local<Array> *cpus) {
+ Local<Object> cpuinfo;
+ Local<Object> cputimes;
+ unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK),
+ multiplier = ((uint64_t)1000L / ticks), cpuspeed;
+ uint64_t info[CPUSTATES];
+ char model[512];
+ int numcpus = 1;
+ static int which[] = {CTL_HW, HW_MODEL, NULL};
+ size_t size;
+
+ size = sizeof(model);
+ if (sysctl(which, 2, &model, &size, NULL, 0) < 0) {
+ return -1;
+ }
+ which[1] = HW_NCPU;
+ size = sizeof(numcpus);
+ if (sysctl(which, 2, &numcpus, &size, NULL, 0) < 0) {
+ return -1;
+ }
+
+ *cpus = Array::New(numcpus);
+
+ which[1] = HW_CPUSPEED;
+ size = sizeof(cpuspeed);
+ if (sysctl(which, 2, &cpuspeed, &size, NULL, 0) < 0) {
+ return -1;
+ }
+ size = sizeof(info);
+ which[0] = CTL_KERN;
+ which[1] = KERN_CPTIME2;
+ for (int i = 0; i < numcpus; i++) {
+ which[2] = i;
+ size = sizeof(info);
+ if (sysctl(which, 3, &info, &size, NULL, 0) < 0) {
+ return -1;
+ }
+ cpuinfo = Object::New();
+ cputimes = Object::New();
+ cputimes->Set(String::New("user"),
+ Number::New((uint64_t)(info[CP_USER]) * multiplier));
+ cputimes->Set(String::New("nice"),
+ Number::New((uint64_t)(info[CP_NICE]) * multiplier));
+ cputimes->Set(String::New("sys"),
+ Number::New((uint64_t)(info[CP_SYS]) * multiplier));
+ cputimes->Set(String::New("idle"),
+ Number::New((uint64_t)(info[CP_IDLE]) * multiplier));
+ cputimes->Set(String::New("irq"),
+ Number::New((uint64_t)(info[CP_INTR]) * multiplier));
+
+ cpuinfo->Set(String::New("model"), String::New(model));
+ cpuinfo->Set(String::New("speed"), Number::New(cpuspeed));
+
+ cpuinfo->Set(String::New("times"), cputimes);
+ (*cpus)->Set(i, cpuinfo);
+ }
+ return 0;
+}
+
+double Platform::GetFreeMemory() {
+ double pagesize = static_cast<double>(sysconf(_SC_PAGESIZE));
+ struct uvmexp info;
+ size_t size = sizeof(info);
+ static int which[] = {CTL_VM, VM_UVMEXP};
+
+ if (sysctl(which, 2, &info, &size, NULL, 0) < 0) {
+ return -1;
+ }
+
+ return static_cast<double>(info.free) * pagesize;
+}
+
+double Platform::GetTotalMemory() {
+#if defined(HW_PHYSMEM64)
+ uint64_t info;
+ static int which[] = {CTL_HW, HW_PHYSMEM64};
+#else
+ unsigned int info;
+ static int which[] = {CTL_HW, HW_PHYSMEM};
+#endif
+ size_t size = sizeof(info);
+
+ if (sysctl(which, 2, &info, &size, NULL, 0) < 0) {
+ return -1;
+ }
+
+ return static_cast<double>(info);
+}
+
+double Platform::GetUptime() {
+ time_t now;
+ struct timeval info;
+ size_t size = sizeof(info);
+ static int which[] = {CTL_KERN, KERN_BOOTTIME};
+
+ if (sysctl(which, 2, &info, &size, NULL, 0) < 0) {
+ return -1;
+ }
+ now = time(NULL);
+
+ return static_cast<double>(now - info.tv_sec);
+}
+
+int Platform::GetLoadAvg(Local<Array> *loads) {
+ struct loadavg info;
+ size_t size = sizeof(info);
+ static int which[] = {CTL_VM, VM_LOADAVG};
+
+ if (sysctl(which, 2, &info, &size, NULL, 0) < 0) {
+ return -1;
+ }
+ (*loads)->Set(0, Number::New(static_cast<double>(info.ldavg[0])
+ / static_cast<double>(info.fscale)));
+ (*loads)->Set(1, Number::New(static_cast<double>(info.ldavg[1])
+ / static_cast<double>(info.fscale)));
+ (*loads)->Set(2, Number::New(static_cast<double>(info.ldavg[2])
+ / static_cast<double>(info.fscale)));
+
+ return 0;
+}
+
+} // namespace node
diff --git a/src/platform_sunos.cc b/src/platform_sunos.cc
index 7723035a3b1..6d70d016809 100644
--- a/src/platform_sunos.cc
+++ b/src/platform_sunos.cc
@@ -23,24 +23,25 @@
namespace node {
+using namespace v8;
-char** OS::SetupArgs(int argc, char *argv[]) {
+char** Platform::SetupArgs(int argc, char *argv[]) {
return argv;
}
-void OS::SetProcessTitle(char *title) {
+void Platform::SetProcessTitle(char *title) {
;
}
-const char* OS::GetProcessTitle(int *len) {
+const char* Platform::GetProcessTitle(int *len) {
*len = 0;
return NULL;
}
-int OS::GetMemory(size_t *rss, size_t *vsize) {
+int Platform::GetMemory(size_t *rss, size_t *vsize) {
pid_t pid = getpid();
size_t page_size = getpagesize();
@@ -67,7 +68,7 @@ int OS::GetMemory(size_t *rss, size_t *vsize) {
}
-int OS::GetExecutablePath(char* buffer, size_t* size) {
+int Platform::GetExecutablePath(char* buffer, size_t* size) {
const char *execname = getexecname();
if (!execname) return -1;
if (execname[0] == '/') {
@@ -86,5 +87,35 @@ int OS::GetExecutablePath(char* buffer, size_t* size) {
}
+// TODO: libkstat provides all this info. Need to link it though.
+
+
+int Platform::GetCPUInfo(Local<Array> *cpus) {
+ // http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/psrinfo/psrinfo.pl
+ return 0;
+}
+
+
+double Platform::GetFreeMemory() {
+ return 0.0;
+}
+
+
+double Platform::GetTotalMemory() {
+ return 0.0;
+}
+
+
+double Platform::GetUptime() {
+ // http://munin-monitoring.org/attachment/ticket/419/uptime
+ return 0.0;
+}
+
+
+int Platform::GetLoadAvg(Local<Array> *loads) {
+ return 0;
+}
+
+
} // namespace node
diff --git a/test/simple/test-assert.js b/test/simple/test-assert.js
index 4c328402553..e2aa645d4a0 100644
--- a/test/simple/test-assert.js
+++ b/test/simple/test-assert.js
@@ -165,12 +165,26 @@ assert.throws(function() {assert.ifError(new Error('test error'))});
assert.doesNotThrow(function() {assert.ifError(null)});
assert.doesNotThrow(function() {assert.ifError()});
+// make sure that validating using constructor really works
+threw = false;
+try {
+ assert.throws(
+ function() {
+ throw {};
+ },
+ Array
+ );
+} catch(e) {
+ threw = true;
+}
+assert.ok(threw, "wrong constructor validation");
+
// use a RegExp to validate error message
a.throws(makeBlock(thrower, TypeError), /test/);
// use a fn to validate error object
a.throws(makeBlock(thrower, TypeError), function(err) {
- if (!(err instanceof TypeError) || !/test/.test(err)) {
- return false;
+ if ( (err instanceof TypeError) && /test/.test(err)) {
+ return true;
}
});
diff --git a/test/simple/test-buffer.js b/test/simple/test-buffer.js
index 818e98cc0ee..e8756a7db4f 100644
--- a/test/simple/test-buffer.js
+++ b/test/simple/test-buffer.js
@@ -8,8 +8,10 @@ var b = Buffer(1024); // safe constructor
console.log('b.length == ' + b.length);
assert.strictEqual(1024, b.length);
+b[0] = -1;
+assert.equal(b[0], 255);
+
for (var i = 0; i < 1024; i++) {
- assert.ok(b[i] >= 0);
b[i] = i % 256;
}
diff --git a/test/simple/test-os-hostname.js b/test/simple/test-os-hostname.js
deleted file mode 100644
index b323622717e..00000000000
--- a/test/simple/test-os-hostname.js
+++ /dev/null
@@ -1,5 +0,0 @@
-var common = require('../common');
-var assert = require('assert');
-var os = require('os');
-
-assert.ok(os.getHostname().length > 0);
diff --git a/test/simple/test-os.js b/test/simple/test-os.js
new file mode 100644
index 00000000000..25cabab3f91
--- /dev/null
+++ b/test/simple/test-os.js
@@ -0,0 +1,12 @@
+var common = require('../common');
+var assert = require('assert');
+var os = require('os');
+
+assert.ok(os.hostname().length > 0);
+assert.ok(os.loadavg().length > 0);
+assert.ok(os.uptime() > 0);
+assert.ok(os.freemem() > 0);
+assert.ok(os.totalmem() > 0);
+assert.ok(os.cpus().length > 0);
+assert.ok(os.type().length > 0);
+assert.ok(os.release().length > 0); \ No newline at end of file
diff --git a/test/simple/test-repl.js b/test/simple/test-repl.js
index 230907c859d..22b41add013 100644
--- a/test/simple/test-repl.js
+++ b/test/simple/test-repl.js
@@ -194,7 +194,9 @@ function unix_test() {
{ client: client_unix, send: 'invoke_me(987)\n',
expect: ('\'' + 'invoked 987' + '\'\n' + prompt_unix) },
{ client: client_unix, send: 'a = 12345\n',
- expect: ('12345' + '\n' + prompt_unix) }
+ expect: ('12345' + '\n' + prompt_unix) },
+ { client: client_unix, send: '{a:1}\n',
+ expect: ('{ a: 1 }' + '\n' + prompt_unix) },
]);
});
diff --git a/test/simple/test-tls-client-verify.js b/test/simple/test-tls-client-verify.js
index 78eb186f6c4..923153b4410 100644
--- a/test/simple/test-tls-client-verify.js
+++ b/test/simple/test-tls-client-verify.js
@@ -1,3 +1,9 @@
+if (!process.versions.openssl) {
+ console.error("Skipping because node compiled without OpenSSL.");
+ process.exit(0);
+}
+
+
var testCases =
[ { ca: ['ca1-cert'],
key: 'agent2-key',
diff --git a/test/simple/test-tls-junk-closes-server.js b/test/simple/test-tls-junk-closes-server.js
index 57f216fdeb2..f76a1573819 100644
--- a/test/simple/test-tls-junk-closes-server.js
+++ b/test/simple/test-tls-junk-closes-server.js
@@ -1,3 +1,8 @@
+if (!process.versions.openssl) {
+ console.error("Skipping because node compiled without OpenSSL.");
+ process.exit(0);
+}
+
var common = require('../common');
var tls = require('tls');
var fs = require('fs');
diff --git a/test/simple/test-tls-securepair-client.js b/test/simple/test-tls-securepair-client.js
index 9bcb7e75d52..2bd4b68c633 100644
--- a/test/simple/test-tls-securepair-client.js
+++ b/test/simple/test-tls-securepair-client.js
@@ -1,3 +1,13 @@
+// There is a bug with 'openssl s_server' which makes it not flush certain
+// important events to stdout when done over a pipe. Therefore we skip this
+// test for all openssl versions less than 1.0.0.
+if (!process.versions.openssl ||
+ parseInt(process.versions.openssl[0]) < 1) {
+ console.error("Skipping due to old OpenSSL version.");
+ process.exit(0);
+}
+
+
var common = require('../common');
var join = require('path').join;
var net = require('net');
diff --git a/test/simple/test-tls-securepair-server.js b/test/simple/test-tls-securepair-server.js
index b172b110010..0131b8c5174 100644
--- a/test/simple/test-tls-securepair-server.js
+++ b/test/simple/test-tls-securepair-server.js
@@ -1,3 +1,9 @@
+if (!process.versions.openssl) {
+ console.error("Skipping because node compiled without OpenSSL.");
+ process.exit(0);
+}
+
+
var common = require('../common');
var assert = require('assert');
diff --git a/test/simple/test-tls-server-verify.js b/test/simple/test-tls-server-verify.js
index 9d3c094bdaa..914c50f476d 100644
--- a/test/simple/test-tls-server-verify.js
+++ b/test/simple/test-tls-server-verify.js
@@ -1,3 +1,8 @@
+if (!process.versions.openssl) {
+ console.error("Skipping because node compiled without OpenSSL.");
+ process.exit(0);
+}
+
// This is a rather complex test which sets up various TLS servers with node
// and connects to them using the 'openssl s_client' command line utility
// with various keys. Depending on the certificate authority and other
diff --git a/wscript b/wscript
index 3b2d7487797..8a32ce25a76 100644
--- a/wscript
+++ b/wscript
@@ -200,7 +200,7 @@ def configure(conf):
conf.env.append_value("CCFLAGS", "-rdynamic")
conf.env.append_value("LINKFLAGS_DL", "-rdynamic")
- if sys.platform.startswith("freebsd"):
+ if sys.platform.startswith("freebsd") or sys.platform.startswith("openbsd"):
conf.check(lib='kvm', uselib_store='KVM')
#if Options.options.debug:
@@ -479,7 +479,10 @@ def v8_cmd(bld, variant):
, snapshot
, profile
)
-
+
+ if sys.platform.startswith("sunos"): cmd += ' toolchain=gcc'
+
+
return ("echo '%s' && " % cmd) + cmd