Browse Source

Merge remote branch 'origin/master'

Conflicts:
	src/node_net.cc
	src/node_os.cc
v0.7.4-release
Bert Belder 14 years ago
parent
commit
33118df8f9
  1. 6
      Makefile
  2. 5
      Makefile.cmake
  3. 12
      README.cmake
  4. 22
      cmake/codesourcery-arm-toolchain.cmake
  5. 10
      cmake/configure.cmake
  6. 7
      cmake/libs.cmake
  7. 20
      cmake/node_build.cmake
  8. 5
      cmake/v8_build.cmake
  9. 11
      deps/v8/ChangeLog
  10. 13
      deps/v8/SConstruct
  11. 15
      deps/v8/include/v8.h
  12. 3
      deps/v8/src/SConscript
  13. 29
      deps/v8/src/api.cc
  14. 105
      deps/v8/src/arm/code-stubs-arm.cc
  15. 9
      deps/v8/src/arm/lithium-arm.cc
  16. 15
      deps/v8/src/arm/lithium-codegen-arm.cc
  17. 38
      deps/v8/src/arm/macro-assembler-arm.cc
  18. 13
      deps/v8/src/arm/macro-assembler-arm.h
  19. 67
      deps/v8/src/array.js
  20. 23
      deps/v8/src/assembler.cc
  21. 2
      deps/v8/src/assembler.h
  22. 53
      deps/v8/src/builtins.cc
  23. 3
      deps/v8/src/code-stubs.h
  24. 11
      deps/v8/src/codegen.cc
  25. 3
      deps/v8/src/counters.h
  26. 33
      deps/v8/src/date.js
  27. 2
      deps/v8/src/debug.cc
  28. 2
      deps/v8/src/deoptimizer.cc
  29. 2
      deps/v8/src/deoptimizer.h
  30. 5
      deps/v8/src/flag-definitions.h
  31. 9
      deps/v8/src/full-codegen.cc
  32. 4
      deps/v8/src/heap-profiler.cc
  33. 95
      deps/v8/src/heap.cc
  34. 16
      deps/v8/src/heap.h
  35. 7
      deps/v8/src/hydrogen-instructions.cc
  36. 6
      deps/v8/src/hydrogen-instructions.h
  37. 12
      deps/v8/src/hydrogen.cc
  38. 2
      deps/v8/src/hydrogen.h
  39. 232
      deps/v8/src/ia32/code-stubs-ia32.cc
  40. 29
      deps/v8/src/ia32/code-stubs-ia32.h
  41. 9
      deps/v8/src/ia32/codegen-ia32.cc
  42. 9
      deps/v8/src/ia32/full-codegen-ia32.cc
  43. 28
      deps/v8/src/ia32/lithium-codegen-ia32.cc
  44. 2
      deps/v8/src/ia32/lithium-codegen-ia32.h
  45. 2
      deps/v8/src/ia32/lithium-ia32.cc
  46. 826
      deps/v8/src/objects-debug.cc
  47. 131
      deps/v8/src/objects.cc
  48. 343
      deps/v8/src/objects.h
  49. 4
      deps/v8/src/parser.cc
  50. 13
      deps/v8/src/platform-nullos.cc
  51. 27
      deps/v8/src/platform-posix.cc
  52. 14
      deps/v8/src/platform-win32.cc
  53. 4
      deps/v8/src/platform.h
  54. 8
      deps/v8/src/profile-generator.cc
  55. 62
      deps/v8/src/property.cc
  56. 8
      deps/v8/src/property.h
  57. 27
      deps/v8/src/regexp.js
  58. 2
      deps/v8/src/runtime.cc
  59. 53
      deps/v8/src/spaces.cc
  60. 9
      deps/v8/src/spaces.h
  61. 6
      deps/v8/src/string-stream.cc
  62. 3
      deps/v8/src/string-stream.h
  63. 67
      deps/v8/src/string.js
  64. 12
      deps/v8/src/utils.cc
  65. 2
      deps/v8/src/v8-counters.h
  66. 10
      deps/v8/src/v8utils.h
  67. 4
      deps/v8/src/version.cc
  68. 4
      deps/v8/src/x64/codegen-x64.cc
  69. 64
      deps/v8/test/cctest/test-heap.cc
  70. 13
      deps/v8/test/mjsunit/array-slice.js
  71. 17
      deps/v8/test/mjsunit/array-sort.js
  72. 43
      deps/v8/test/mjsunit/with-readonly.js
  73. 3
      deps/v8/tools/gyp/v8.gyp
  74. 3
      deps/v8/tools/v8.xcodeproj/project.pbxproj
  75. 2
      deps/v8/tools/visual_studio/debug.vsprops
  76. 4
      doc/api/addons.markdown
  77. 2
      doc/api/appendix_1.markdown
  78. 4
      doc/api/assert.markdown
  79. 97
      doc/api/os.markdown
  80. 17
      doc/api/process.markdown
  81. 4
      doc/api/repl.markdown
  82. 57
      doc/api/streams.markdown
  83. 8
      doc/index.html
  84. 9
      lib/assert.js
  85. 16
      lib/console.js
  86. 2
      lib/events.js
  87. 9
      lib/os.js
  88. 34
      lib/readline.js
  89. 83
      lib/repl.js
  90. 41
      lib/stream.js
  91. 33
      src/node.cc
  92. 31
      src/node.js
  93. 6
      src/node_crypto.cc
  94. 35
      src/node_net.cc
  95. 94
      src/node_os.cc
  96. 281
      src/node_script.cc
  97. 48
      src/node_script.h
  98. 9
      src/platform.h
  99. 124
      src/platform_cygwin.cc
  100. 131
      src/platform_darwin.cc

6
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

5
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)

12
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)

22
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 "")

10
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()

7
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)

20
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)

5
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}
)

11
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.

13
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',

15
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);
};

3
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']
}

29
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;

105
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);
// 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.
// 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 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);

9
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;

15
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();
}
}

38
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());

13
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
// ---------------------------------------------------------------------------

67
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) {
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;

23
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

2
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

53
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))) {
Object* elms_obj;
if (maybe_elms_obj != NULL && maybe_elms_obj->ToObject(&elms_obj)) {
if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
return CallJsBuiltin("ArraySlice", args);
}
FixedArray* elms = FixedArray::cast(elms_obj);
elms = FixedArray::cast(elms_obj);
JSArray* array = JSArray::cast(receiver);
ASSERT(array->HasFastElements());
int len = Smi::cast(array->length())->value();
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);

3
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) \

11
deps/v8/src/codegen.cc

@ -215,8 +215,17 @@ void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) {
}
PrintF("\n\n");
}
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->name()->ToCString());
}
code->Disassemble(*function->debug_name()->ToCString());
}
#endif // ENABLE_DISASSEMBLER
}

3
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 {

33
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() {

2
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;
}

2
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) {

2
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

5
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")

9
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);
}

4
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);

95
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_ =
space_iterator_ = filtering_ == kNoFiltering ? new SpaceIterator :
new SpaceIterator(MarkCompactCollector::SizeOfMarkedObject);
} else {
space_iterator_ = new SpaceIterator;
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;
}

16
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];

7
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());
}

6
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:

12
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,7 +3574,7 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
}
HInstruction* HGraphBuilder::BuildLoadNamedField(HValue* object,
HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
Property* expr,
Handle<Map> type,
LookupResult* lookup,
@ -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;

2
deps/v8/src/hydrogen.h

@ -786,7 +786,7 @@ class HGraphBuilder: public AstVisitor {
HValue* left,
HValue* right);
HInstruction* BuildIncrement(HValue* value, bool increment);
HInstruction* BuildLoadNamedField(HValue* object,
HLoadNamedField* BuildLoadNamedField(HValue* object,
Property* expr,
Handle<Map> type,
LookupResult* result,

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

@ -2472,12 +2472,25 @@ void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
// Input on stack:
// esp[4]: argument (should be number).
// TAGGED case:
// Input:
// esp[4]: tagged number input argument (should be number).
// esp[0]: return address.
// Test that eax is a number.
// 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;
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));
@ -2506,7 +2519,18 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
__ mov(ebx, FieldOperand(eax, HeapNumber::kMantissaOffset));
__ bind(&loaded);
// ST[0] == double value
} 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);
}
// 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));
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.
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));
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();
}
// 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

29
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);
};

9
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);
}

9
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);

28
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;

2
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);

2
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);

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

File diff suppressed because it is too large

131
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");
}
}
}

343
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

4
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,7 +3768,7 @@ void RegExpParser::Reset(int pos) {
void RegExpParser::Advance(int dist) {
for (int i = 0; i < dist; i++)
next_pos_ += dist - 1;
Advance();
}

13
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.

27
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,6 +190,8 @@ int OS::VSNPrintF(Vector<char> str,
va_list args) {
int n = vsnprintf(str.start(), str.length(), format, args);
if (n < 0 || n >= str.length()) {
// If the length is zero, the assignment fails.
if (str.length() > 0)
str[str.length() - 1] = '\0';
return -1;
} else {
@ -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(); }

14
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,6 +729,7 @@ 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()) {
if (str.length() > 0)
str[str.length() - 1] = '\0';
return -1;
} else {

4
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.

8
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()) {

62
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());
}

8
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() {

27
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.

2
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

53
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];
// -----------------------------------------------------------------------------

9
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,
static uintptr_t* AllocatedChunksFinder(uintptr_t* table,
uintptr_t address,
int bit_position,
CreateTables create_as_needed);
static void FreeChunkTables(AtomicWord* array, int length, int level);
static void FreeChunkTables(uintptr_t* array, int length, int level);
static int FineGrainedIndexForAddress(uintptr_t address) {
int index = ((address >> kChunkSizeLog2) &
((1 << kChunkTableBitsPerLevel) - 1));

6
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]);
}

3
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;

67
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);
}
}

12
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);
}

2
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 {

10
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

4
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

4
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.

64
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());
}
}

13
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));
})();

17
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);

43
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();

3
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': {

3
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;

2
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

4
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:

2
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

4
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"

97
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 } } ]

17
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');
});

4
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.

57
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,55 +85,17 @@ 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();
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.
process.stdin.pipe(process.stdout, { end: false });
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();
process.stdin.on("end", function() {
process.stdout.write("Goodbye\n");
});
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);
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.
## Writable Stream

8
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>

9
lib/assert.js

@ -246,13 +246,14 @@ function expectedException(actual, expected) {
}
if (expected instanceof RegExp) {
if (expected.test(actual)) {
return expected.test(actual);
} else if (actual instanceof expected) {
return true;
}
} else if (actual instanceof expected ||
expected.call({}, actual) !== false) {
} else if ( expected.call({}, actual) === true ) {
return true;
}
return false;
}
function _throws(shouldThrow, block, expected, message) {

16
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;
}

2
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) {

9
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;

34
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 */

83
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;

41
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);
}
});
}
function ondrain() {
if (source.readable) source.resume();

33
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);

31
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;
};

6
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

35
src/node_net.cc

@ -462,13 +462,16 @@ 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; \
if (addrlen == 0) { \
(info)->Set(address_symbol, String::Empty()); \
} else { \
switch ((address_storage).ss_family) { \
case AF_INET6: \
a6 = (struct sockaddr_in6*)&(address_storage); \
@ -485,22 +488,40 @@ do { \
(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; \
if (addrlen == 0) { \
(info)->Set(address_symbol, String::Empty()); \
} else { \
switch ((address_storage).ss_family) { \
case AF_INET6: \
a6 = (struct sockaddr_in6*)&(address_storage); \
@ -519,6 +540,7 @@ do { \
default: \
(info)->Set(address_symbol, String::Empty()); \
} \
} \
} while (0)
#endif // __MINGW32__
@ -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);
}

94
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,10 +34,98 @@ 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);
}

281
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() {
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);

48
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);

9
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);
};

124
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

131
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

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

Loading…
Cancel
Save