Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

upgrade v8 to 2.0.3

  • Loading branch information...
commit c8b6ef248e5fc32df62041ec83463923bc8bdc68 1 parent c5d8238
@ry ry authored
Showing with 4,250 additions and 1,460 deletions.
  1. +24 −1 deps/v8/ChangeLog
  2. +21 −3 deps/v8/SConstruct
  3. +17 −3 deps/v8/include/v8.h
  4. +4 −0 deps/v8/src/SConscript
  5. +52 −18 deps/v8/src/accessors.cc
  6. +6 −4 deps/v8/src/accessors.h
  7. +44 −2 deps/v8/src/api.cc
  8. +1 −0  deps/v8/src/arm/assembler-arm.h
  9. +121 −10 deps/v8/src/arm/codegen-arm.cc
  10. +3 −0  deps/v8/src/arm/codegen-arm.h
  11. +15 −12 deps/v8/src/arm/constants-arm.h
  12. +1 −1  deps/v8/src/arm/debug-arm.cc
  13. +227 −89 deps/v8/src/arm/fast-codegen-arm.cc
  14. +9 −4 deps/v8/src/arm/ic-arm.cc
  15. +44 −8 deps/v8/src/arm/macro-assembler-arm.cc
  16. +7 −0 deps/v8/src/arm/macro-assembler-arm.h
  17. +1 −4 deps/v8/src/arm/stub-cache-arm.cc
  18. +29 −7 deps/v8/src/array.js
  19. +1 −0  deps/v8/src/ast.h
  20. +16 −10 deps/v8/src/bootstrapper.cc
  21. +1 −0  deps/v8/src/code-stubs.h
  22. +1 −0  deps/v8/src/codegen.cc
  23. +33 −17 deps/v8/src/compiler.cc
  24. +6 −2 deps/v8/src/d8.cc
  25. +21 −0 deps/v8/src/debug-delay.js
  26. +0 −11 deps/v8/src/debug.h
  27. +5 −3 deps/v8/src/dtoa-config.c
  28. +2 −3 deps/v8/src/factory.cc
  29. +33 −4 deps/v8/src/fast-codegen.cc
  30. +10 −3 deps/v8/src/fast-codegen.h
  31. +5 −3 deps/v8/src/flag-definitions.h
  32. +20 −0 deps/v8/src/global-handles.cc
  33. +2 −0  deps/v8/src/global-handles.h
  34. +35 −13 deps/v8/src/handles.cc
  35. +2 −1  deps/v8/src/handles.h
  36. +2 −2 deps/v8/src/heap-inl.h
  37. +65 −128 deps/v8/src/heap.cc
  38. +48 −47 deps/v8/src/heap.h
  39. +2 −0  deps/v8/src/ia32/assembler-ia32.h
  40. +290 −22 deps/v8/src/ia32/codegen-ia32.cc
  41. +34 −0 deps/v8/src/ia32/codegen-ia32.h
  42. +4 −4 deps/v8/src/ia32/debug-ia32.cc
  43. +228 −91 deps/v8/src/ia32/fast-codegen-ia32.cc
  44. +12 −27 deps/v8/src/ia32/ic-ia32.cc
  45. +145 −0 deps/v8/src/ia32/macro-assembler-ia32.cc
  46. +38 −1 deps/v8/src/ia32/macro-assembler-ia32.h
  47. +3 −7 deps/v8/src/ia32/stub-cache-ia32.cc
  48. +56 −4 deps/v8/src/log.cc
  49. +9 −0 deps/v8/src/log.h
  50. +49 −16 deps/v8/src/messages.js
  51. +16 −8 deps/v8/src/mirror-delay.js
  52. +27 −38 deps/v8/src/objects-debug.cc
  53. +17 −135 deps/v8/src/objects-inl.h
  54. +66 −66 deps/v8/src/objects.cc
  55. +158 −348 deps/v8/src/objects.h
  56. +0 −5 deps/v8/src/platform-freebsd.cc
  57. +0 −5 deps/v8/src/platform-linux.cc
  58. +0 −5 deps/v8/src/platform-macos.cc
  59. +597 −0 deps/v8/src/platform-openbsd.cc
  60. +8 −1 deps/v8/src/platform-posix.cc
  61. +86 −38 deps/v8/src/runtime.cc
  62. +10 −1 deps/v8/src/runtime.h
  63. +5 −5 deps/v8/src/runtime.js
  64. +73 −14 deps/v8/src/serialize.cc
  65. +1 −1  deps/v8/src/string-stream.cc
  66. +6 −0 deps/v8/src/stub-cache.cc
  67. +2 −2 deps/v8/src/stub-cache.h
  68. +9 −0 deps/v8/src/utils.cc
  69. +3 −0  deps/v8/src/utils.h
  70. +3 −2 deps/v8/src/v8-counters.h
  71. +1 −1  deps/v8/src/version.cc
  72. +6 −0 deps/v8/src/x64/assembler-x64.h
  73. +105 −22 deps/v8/src/x64/codegen-x64.cc
  74. +3 −0  deps/v8/src/x64/codegen-x64.h
  75. +4 −3 deps/v8/src/x64/debug-x64.cc
  76. +229 −96 deps/v8/src/x64/fast-codegen-x64.cc
  77. +12 −27 deps/v8/src/x64/ic-x64.cc
  78. +34 −0 deps/v8/src/x64/macro-assembler-x64.cc
  79. +9 −0 deps/v8/src/x64/macro-assembler-x64.h
  80. +2 −6 deps/v8/src/x64/stub-cache-x64.cc
  81. +2 −2 deps/v8/test/cctest/test-alloc.cc
  82. +217 −14 deps/v8/test/cctest/test-api.cc
  83. +4 −4 deps/v8/test/cctest/test-debug.cc
  84. +1 −2  deps/v8/test/cctest/test-heap.cc
  85. +75 −0 deps/v8/test/cctest/test-log.cc
  86. +36 −1 deps/v8/test/cctest/test-serialize.cc
  87. +98 −19 deps/v8/test/cctest/test-strings.cc
  88. +164 −0 deps/v8/test/mjsunit/arguments-read-and-assignment.js
  89. +33 −0 deps/v8/test/mjsunit/compiler/jsnatives.js
  90. +57 −0 deps/v8/test/mjsunit/compiler/objectliterals.js
  91. +32 −0 deps/v8/test/mjsunit/regress/regress-526.js
  92. +77 −0 deps/v8/test/mjsunit/regress/regress-r3391.js
  93. +20 −0 deps/v8/test/mjsunit/string-add.js
  94. +40 −0 deps/v8/test/mjsunit/typeof.js
  95. +1 −1  deps/v8/tools/codemap.js
  96. +11 −0 deps/v8/tools/gyp/v8.gyp
  97. +68 −3 deps/v8/tools/presubmit.py
  98. +2 −0  deps/v8/tools/utils.py
  99. +16 −0 deps/v8/tools/v8.xcodeproj/project.pbxproj
View
25 deps/v8/ChangeLog
@@ -1,3 +1,26 @@
+2009-12-03: Version 2.0.3
+
+ Optimized handling and adding of strings, for-in and Array.join.
+
+ Heap serialization is now non-destructive.
+
+ Improved profiler support with information on time spend in C++
+ callbacks registered through the API.
+
+ Added commands to the debugger protocol for starting/stopping
+ profiling.
+
+ Enabled the non-optimizing compiler for top-level code.
+
+ Changed the API to only allow strings to be set as data objects on
+ Contexts and scripts to avoid potentially keeping global objects
+ around for too long (issue 528).
+
+ OpenBSD support patch by Peter Valchev <pvalchev@gmail.com>.
+
+ Fixed bugs.
+
+
2009-11-24: Version 2.0.2
Improved profiler support.
@@ -34,7 +57,7 @@
Reverted a change which caused crashes in RegExp replace.
- Reverted a change which caused Chromium ui_tests failure.
+ Reverted a change which caused Chromium ui_tests failure.
2009-10-28: Version 1.3.17
View
24 deps/v8/SConstruct
@@ -149,6 +149,11 @@ LIBRARY_FLAGS = {
'LIBPATH' : ['/usr/local/lib'],
'CCFLAGS': ['-ansi'],
},
+ 'os:openbsd': {
+ 'CPPPATH' : ['/usr/local/include'],
+ 'LIBPATH' : ['/usr/local/lib'],
+ 'CCFLAGS': ['-ansi'],
+ },
'os:win32': {
'CCFLAGS': ['-DWIN32'],
'CXXFLAGS': ['-DWIN32'],
@@ -298,6 +303,9 @@ MKSNAPSHOT_EXTRA_FLAGS = {
'os:freebsd': {
'LIBS': ['execinfo', 'pthread']
},
+ 'os:openbsd': {
+ 'LIBS': ['execinfo', 'pthread']
+ },
'os:win32': {
'LIBS': ['winmm', 'ws2_32'],
},
@@ -344,6 +352,9 @@ CCTEST_EXTRA_FLAGS = {
'os:freebsd': {
'LIBS': ['execinfo', 'pthread']
},
+ 'os:openbsd': {
+ 'LIBS': ['execinfo', 'pthread']
+ },
'os:win32': {
'LIBS': ['winmm', 'ws2_32']
},
@@ -397,7 +408,11 @@ SAMPLE_FLAGS = {
},
'os:freebsd': {
'LIBPATH' : ['/usr/local/lib'],
- 'LIBS': ['execinfo', 'pthread']
+ 'LIBS': ['execinfo', 'pthread']
+ },
+ 'os:openbsd': {
+ 'LIBPATH' : ['/usr/local/lib'],
+ 'LIBS': ['execinfo', 'pthread']
},
'os:win32': {
'LIBS': ['winmm', 'ws2_32']
@@ -504,6 +519,9 @@ D8_FLAGS = {
'os:freebsd': {
'LIBS': ['pthread'],
},
+ 'os:openbsd': {
+ 'LIBS': ['pthread'],
+ },
'os:android': {
'LIBPATH': [ANDROID_TOP + '/out/target/product/generic/obj/lib'],
'LINKFLAGS': ANDROID_LINKFLAGS,
@@ -544,7 +562,7 @@ def GuessToolchain(os):
OS_GUESS = utils.GuessOS()
TOOLCHAIN_GUESS = GuessToolchain(OS_GUESS)
-ARCH_GUESS = utils.GuessArchitecture() or ""
+ARCH_GUESS = utils.GuessArchitecture()
SIMPLE_OPTIONS = {
@@ -554,7 +572,7 @@ SIMPLE_OPTIONS = {
'help': 'the toolchain to use (' + TOOLCHAIN_GUESS + ')'
},
'os': {
- 'values': ['freebsd', 'linux', 'macos', 'win32', 'android'],
+ 'values': ['freebsd', 'linux', 'macos', 'win32', 'android', 'openbsd'],
'default': OS_GUESS,
'help': 'the os to build for (' + OS_GUESS + ')'
},
View
20 deps/v8/include/v8.h
@@ -598,7 +598,7 @@ class V8EXPORT Script {
* with the debugger as this data object is only available through the
* debugger API.
*/
- void SetData(Handle<Value> data);
+ void SetData(Handle<String> data);
};
@@ -2634,7 +2634,7 @@ class V8EXPORT Context {
* with the debugger to provide additional information on the context through
* the debugger API.
*/
- void SetData(Handle<Value> data);
+ void SetData(Handle<String> data);
Local<Value> GetData();
/**
@@ -2819,6 +2819,18 @@ template <> struct SmiConstants<8> {
const int kSmiShiftSize = SmiConstants<sizeof(void*)>::kSmiShiftSize;
const int kSmiValueSize = SmiConstants<sizeof(void*)>::kSmiValueSize;
+template <size_t ptr_size> struct InternalConstants;
+
+// Internal constants for 32-bit systems.
+template <> struct InternalConstants<4> {
+ static const int kStringResourceOffset = 3 * sizeof(void*);
+};
+
+// Internal constants for 64-bit systems.
+template <> struct InternalConstants<8> {
+ static const int kStringResourceOffset = 2 * sizeof(void*);
+};
+
/**
* This class exports constants and functionality from within v8 that
* is necessary to implement inline functions in the v8 api. Don't
@@ -2831,7 +2843,9 @@ class Internals {
// the implementation of v8.
static const int kHeapObjectMapOffset = 0;
static const int kMapInstanceTypeOffset = sizeof(void*) + sizeof(int);
- static const int kStringResourceOffset = 2 * sizeof(void*);
+ static const int kStringResourceOffset =
+ InternalConstants<sizeof(void*)>::kStringResourceOffset;
+
static const int kProxyProxyOffset = sizeof(void*);
static const int kJSObjectHeaderSize = 3 * sizeof(void*);
static const int kFullStringRepresentationMask = 0x07;
View
4 deps/v8/src/SConscript
@@ -159,6 +159,7 @@ SOURCES = {
"""),
'simulator:arm': ['arm/simulator-arm.cc'],
'os:freebsd': ['platform-freebsd.cc', 'platform-posix.cc'],
+ 'os:openbsd': ['platform-openbsd.cc', 'platform-posix.cc'],
'os:linux': ['platform-linux.cc', 'platform-posix.cc'],
'os:android': ['platform-linux.cc', 'platform-posix.cc'],
'os:macos': ['platform-macos.cc', 'platform-posix.cc'],
@@ -187,6 +188,9 @@ D8_FILES = {
'os:freebsd': [
'd8-posix.cc'
],
+ 'os:openbsd': [
+ 'd8-posix.cc'
+ ],
'os:win32': [
'd8-windows.cc'
],
View
70 deps/v8/src/accessors.cc
@@ -315,14 +315,11 @@ Object* Accessors::ScriptGetLineEnds(Object* object, void*) {
HandleScope scope;
Handle<Script> script(Script::cast(JSValue::cast(object)->value()));
InitScriptLineEnds(script);
- if (script->line_ends_js_array()->IsUndefined()) {
- Handle<FixedArray> line_ends_fixed_array(
- FixedArray::cast(script->line_ends_fixed_array()));
- Handle<FixedArray> copy = Factory::CopyFixedArray(line_ends_fixed_array);
- Handle<JSArray> js_array = Factory::NewJSArrayWithElements(copy);
- script->set_line_ends_js_array(*js_array);
- }
- return script->line_ends_js_array();
+ ASSERT(script->line_ends()->IsFixedArray());
+ Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
+ Handle<FixedArray> copy = Factory::CopyFixedArray(line_ends);
+ Handle<JSArray> js_array = Factory::NewJSArrayWithElements(copy);
+ return *js_array;
}
@@ -352,29 +349,38 @@ const AccessorDescriptor Accessors::ScriptContextData = {
//
-// Accessors::ScriptGetEvalFromFunction
+// Accessors::ScriptGetEvalFromScript
//
-Object* Accessors::ScriptGetEvalFromFunction(Object* object, void*) {
+Object* Accessors::ScriptGetEvalFromScript(Object* object, void*) {
Object* script = JSValue::cast(object)->value();
- return Script::cast(script)->eval_from_function();
+ if (!Script::cast(script)->eval_from_shared()->IsUndefined()) {
+ Handle<SharedFunctionInfo> eval_from_shared(
+ SharedFunctionInfo::cast(Script::cast(script)->eval_from_shared()));
+
+ if (eval_from_shared->script()->IsScript()) {
+ Handle<Script> eval_from_script(Script::cast(eval_from_shared->script()));
+ return *GetScriptWrapper(eval_from_script);
+ }
+ }
+ return Heap::undefined_value();
}
-const AccessorDescriptor Accessors::ScriptEvalFromFunction = {
- ScriptGetEvalFromFunction,
+const AccessorDescriptor Accessors::ScriptEvalFromScript = {
+ ScriptGetEvalFromScript,
IllegalSetter,
0
};
//
-// Accessors::ScriptGetEvalFromPosition
+// Accessors::ScriptGetEvalFromScriptPosition
//
-Object* Accessors::ScriptGetEvalFromPosition(Object* object, void*) {
+Object* Accessors::ScriptGetEvalFromScriptPosition(Object* object, void*) {
HandleScope scope;
Handle<Script> script(Script::cast(JSValue::cast(object)->value()));
@@ -386,14 +392,42 @@ Object* Accessors::ScriptGetEvalFromPosition(Object* object, void*) {
// Get the function from where eval was called and find the source position
// from the instruction offset.
- Handle<Code> code(JSFunction::cast(script->eval_from_function())->code());
+ Handle<Code> code(SharedFunctionInfo::cast(
+ script->eval_from_shared())->code());
return Smi::FromInt(code->SourcePosition(code->instruction_start() +
script->eval_from_instructions_offset()->value()));
}
-const AccessorDescriptor Accessors::ScriptEvalFromPosition = {
- ScriptGetEvalFromPosition,
+const AccessorDescriptor Accessors::ScriptEvalFromScriptPosition = {
+ ScriptGetEvalFromScriptPosition,
+ IllegalSetter,
+ 0
+};
+
+
+//
+// Accessors::ScriptGetEvalFromFunctionName
+//
+
+
+Object* Accessors::ScriptGetEvalFromFunctionName(Object* object, void*) {
+ Object* script = JSValue::cast(object)->value();
+ Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(
+ Script::cast(script)->eval_from_shared()));
+
+
+ // Find the name of the function calling eval.
+ if (!shared->name()->IsUndefined()) {
+ return shared->name();
+ } else {
+ return shared->inferred_name();
+ }
+}
+
+
+const AccessorDescriptor Accessors::ScriptEvalFromFunctionName = {
+ ScriptGetEvalFromFunctionName,
IllegalSetter,
0
};
View
10 deps/v8/src/accessors.h
@@ -51,8 +51,9 @@ namespace internal {
V(ScriptCompilationType) \
V(ScriptLineEnds) \
V(ScriptContextData) \
- V(ScriptEvalFromFunction) \
- V(ScriptEvalFromPosition) \
+ V(ScriptEvalFromScript) \
+ V(ScriptEvalFromScriptPosition) \
+ V(ScriptEvalFromFunctionName) \
V(ObjectPrototype)
// Accessors contains all predefined proxy accessors.
@@ -95,8 +96,9 @@ class Accessors : public AllStatic {
static Object* ScriptGetCompilationType(Object* object, void*);
static Object* ScriptGetLineEnds(Object* object, void*);
static Object* ScriptGetContextData(Object* object, void*);
- static Object* ScriptGetEvalFromFunction(Object* object, void*);
- static Object* ScriptGetEvalFromPosition(Object* object, void*);
+ static Object* ScriptGetEvalFromScript(Object* object, void*);
+ static Object* ScriptGetEvalFromScriptPosition(Object* object, void*);
+ static Object* ScriptGetEvalFromFunctionName(Object* object, void*);
static Object* ObjectGetPrototype(Object* receiver, void*);
static Object* ObjectSetPrototype(JSObject* receiver, Object* value, void*);
View
46 deps/v8/src/api.cc
@@ -126,6 +126,48 @@ static FatalErrorCallback& GetFatalErrorHandler() {
// When V8 cannot allocated memory FatalProcessOutOfMemory is called.
// The default fatal error handler is called and execution is stopped.
void i::V8::FatalProcessOutOfMemory(const char* location) {
+ i::HeapStats heap_stats;
+ int start_marker;
+ heap_stats.start_marker = &start_marker;
+ int new_space_size;
+ heap_stats.new_space_size = &new_space_size;
+ int new_space_capacity;
+ heap_stats.new_space_capacity = &new_space_capacity;
+ int old_pointer_space_size;
+ heap_stats.old_pointer_space_size = &old_pointer_space_size;
+ int old_pointer_space_capacity;
+ heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity;
+ int old_data_space_size;
+ heap_stats.old_data_space_size = &old_data_space_size;
+ int old_data_space_capacity;
+ heap_stats.old_data_space_capacity = &old_data_space_capacity;
+ int code_space_size;
+ heap_stats.code_space_size = &code_space_size;
+ int code_space_capacity;
+ heap_stats.code_space_capacity = &code_space_capacity;
+ int map_space_size;
+ heap_stats.map_space_size = &map_space_size;
+ int map_space_capacity;
+ heap_stats.map_space_capacity = &map_space_capacity;
+ int cell_space_size;
+ heap_stats.cell_space_size = &cell_space_size;
+ int cell_space_capacity;
+ heap_stats.cell_space_capacity = &cell_space_capacity;
+ int lo_space_size;
+ heap_stats.lo_space_size = &lo_space_size;
+ int global_handle_count;
+ heap_stats.global_handle_count = &global_handle_count;
+ int weak_global_handle_count;
+ heap_stats.weak_global_handle_count = &weak_global_handle_count;
+ int pending_global_handle_count;
+ heap_stats.pending_global_handle_count = &pending_global_handle_count;
+ int near_death_global_handle_count;
+ heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
+ int destroyed_global_handle_count;
+ heap_stats.destroyed_global_handle_count = &destroyed_global_handle_count;
+ int end_marker;
+ heap_stats.end_marker = &end_marker;
+ i::Heap::RecordStats(&heap_stats);
i::V8::SetFatalError();
FatalErrorCallback callback = GetFatalErrorHandler();
{
@@ -451,7 +493,7 @@ void Context::Exit() {
}
-void Context::SetData(v8::Handle<Value> data) {
+void Context::SetData(v8::Handle<String> data) {
if (IsDeadCheck("v8::Context::SetData()")) return;
ENTER_V8;
{
@@ -1175,7 +1217,7 @@ Local<Value> Script::Id() {
}
-void Script::SetData(v8::Handle<Value> data) {
+void Script::SetData(v8::Handle<String> data) {
ON_BAILOUT("v8::Script::SetData()", return);
LOG_API("Script::SetData");
{
View
1  deps/v8/src/arm/assembler-arm.h
@@ -566,6 +566,7 @@ class Assembler : public Malloced {
// register.
static const int kPcLoadDelta = 8;
+ static const int kJSReturnSequenceLength = 4;
// ---------------------------------------------------------------------------
// Code generation
View
131 deps/v8/src/arm/codegen-arm.cc
@@ -326,7 +326,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
// Calculate the exact length of the return sequence and make sure that
// the constant pool is not emitted inside of the return sequence.
int32_t sp_delta = (scope_->num_parameters() + 1) * kPointerSize;
- int return_sequence_length = Debug::kARMJSReturnSequenceLength;
+ int return_sequence_length = Assembler::kJSReturnSequenceLength;
if (!masm_->ImmediateFitsAddrMode1Instruction(sp_delta)) {
// Additional mov instruction generated.
return_sequence_length++;
@@ -1560,7 +1560,7 @@ void CodeGenerator::VisitDoWhileStatement(DoWhileStatement* node) {
CheckStack(); // TODO(1222600): ignore if body contains calls.
VisitAndSpill(node->body());
- // Compile the test.
+ // Compile the test.
switch (info) {
case ALWAYS_TRUE:
// If control can fall off the end of the body, jump back to the
@@ -1775,19 +1775,77 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
jsobject.Bind();
// Get the set of properties (as a FixedArray or Map).
- frame_->EmitPush(r0); // duplicate the object being enumerated
- frame_->EmitPush(r0);
+ // r0: value to be iterated over
+ frame_->EmitPush(r0); // Push the object being iterated over.
+
+ // Check cache validity in generated code. This is a fast case for
+ // the JSObject::IsSimpleEnum cache validity checks. If we cannot
+ // guarantee cache validity, call the runtime system to check cache
+ // validity or get the property names in a fixed array.
+ JumpTarget call_runtime;
+ JumpTarget loop(JumpTarget::BIDIRECTIONAL);
+ JumpTarget check_prototype;
+ JumpTarget use_cache;
+ __ mov(r1, Operand(r0));
+ loop.Bind();
+ // Check that there are no elements.
+ __ ldr(r2, FieldMemOperand(r1, JSObject::kElementsOffset));
+ __ LoadRoot(r4, Heap::kEmptyFixedArrayRootIndex);
+ __ cmp(r2, r4);
+ call_runtime.Branch(ne);
+ // Check that instance descriptors are not empty so that we can
+ // check for an enum cache. Leave the map in r3 for the subsequent
+ // prototype load.
+ __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
+ __ ldr(r2, FieldMemOperand(r3, Map::kInstanceDescriptorsOffset));
+ __ LoadRoot(ip, Heap::kEmptyDescriptorArrayRootIndex);
+ __ cmp(r2, ip);
+ call_runtime.Branch(eq);
+ // Check that there in an enum cache in the non-empty instance
+ // descriptors. This is the case if the next enumeration index
+ // field does not contain a smi.
+ __ ldr(r2, FieldMemOperand(r2, DescriptorArray::kEnumerationIndexOffset));
+ __ tst(r2, Operand(kSmiTagMask));
+ call_runtime.Branch(eq);
+ // For all objects but the receiver, check that the cache is empty.
+ // r4: empty fixed array root.
+ __ cmp(r1, r0);
+ check_prototype.Branch(eq);
+ __ ldr(r2, FieldMemOperand(r2, DescriptorArray::kEnumCacheBridgeCacheOffset));
+ __ cmp(r2, r4);
+ call_runtime.Branch(ne);
+ check_prototype.Bind();
+ // Load the prototype from the map and loop if non-null.
+ __ ldr(r1, FieldMemOperand(r3, Map::kPrototypeOffset));
+ __ LoadRoot(ip, Heap::kNullValueRootIndex);
+ __ cmp(r1, ip);
+ loop.Branch(ne);
+ // The enum cache is valid. Load the map of the object being
+ // iterated over and use the cache for the iteration.
+ __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
+ use_cache.Jump();
+
+ call_runtime.Bind();
+ // Call the runtime to get the property names for the object.
+ frame_->EmitPush(r0); // push the object (slot 4) for the runtime call
frame_->CallRuntime(Runtime::kGetPropertyNamesFast, 1);
- // If we got a Map, we can do a fast modification check.
- // Otherwise, we got a FixedArray, and we have to do a slow check.
+ // If we got a map from the runtime call, we can do a fast
+ // modification check. Otherwise, we got a fixed array, and we have
+ // to do a slow check.
+ // r0: map or fixed array (result from call to
+ // Runtime::kGetPropertyNamesFast)
__ mov(r2, Operand(r0));
__ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kMetaMapRootIndex);
__ cmp(r1, ip);
fixed_array.Branch(ne);
+ use_cache.Bind();
// Get enum cache
+ // r0: map (either the result from a call to
+ // Runtime::kGetPropertyNamesFast or has been fetched directly from
+ // the object)
__ mov(r1, Operand(r0));
__ ldr(r1, FieldMemOperand(r1, Map::kInstanceDescriptorsOffset));
__ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset));
@@ -3308,9 +3366,6 @@ void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
// Now r2 has the string type.
__ ldr(r3, FieldMemOperand(r1, String::kLengthOffset));
- __ and_(r4, r2, Operand(kStringSizeMask));
- __ add(r4, r4, Operand(String::kLongLengthShift));
- __ mov(r3, Operand(r3, LSR, r4));
// Now r3 has the length of the string. Compare with the index.
__ cmp(r3, Operand(r0, LSR, kSmiTagSize));
__ b(le, &slow);
@@ -3508,6 +3563,17 @@ void CodeGenerator::GenerateFastMathOp(MathOp op, ZoneList<Expression*>* args) {
}
+void CodeGenerator::GenerateStringAdd(ZoneList<Expression*>* args) {
+ ASSERT_EQ(2, args->length());
+
+ Load(args->at(0));
+ Load(args->at(1));
+
+ frame_->CallRuntime(Runtime::kStringAdd, 2);
+ frame_->EmitPush(r0);
+}
+
+
void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
VirtualFrame::SpilledScope spilled_scope;
ASSERT(args->length() == 2);
@@ -5149,8 +5215,53 @@ static void HandleBinaryOpSlowCases(MacroAssembler* masm,
// We jump to here if something goes wrong (one param is not a number of any
// sort or new-space allocation fails).
__ bind(&slow);
+
+ // Push arguments to the stack
__ push(r1);
__ push(r0);
+
+ if (Token::ADD == operation) {
+ // Test for string arguments before calling runtime.
+ // r1 : first argument
+ // r0 : second argument
+ // sp[0] : second argument
+ // sp[1] : first argument
+
+ Label not_strings, not_string1, string1;
+ __ tst(r1, Operand(kSmiTagMask));
+ __ b(eq, &not_string1);
+ __ CompareObjectType(r1, r2, r2, FIRST_NONSTRING_TYPE);
+ __ b(ge, &not_string1);
+
+ // First argument is a a string, test second.
+ __ tst(r0, Operand(kSmiTagMask));
+ __ b(eq, &string1);
+ __ CompareObjectType(r0, r2, r2, FIRST_NONSTRING_TYPE);
+ __ b(ge, &string1);
+
+ // First and second argument are strings.
+ __ TailCallRuntime(ExternalReference(Runtime::kStringAdd), 2, 1);
+
+ // Only first argument is a string.
+ __ bind(&string1);
+ __ mov(r0, Operand(2)); // Set number of arguments.
+ __ InvokeBuiltin(Builtins::STRING_ADD_LEFT, JUMP_JS);
+
+ // First argument was not a string, test second.
+ __ bind(&not_string1);
+ __ tst(r0, Operand(kSmiTagMask));
+ __ b(eq, &not_strings);
+ __ CompareObjectType(r0, r2, r2, FIRST_NONSTRING_TYPE);
+ __ b(ge, &not_strings);
+
+ // Only second argument is a string.
+ __ b(&not_strings);
+ __ mov(r0, Operand(2)); // Set number of arguments.
+ __ InvokeBuiltin(Builtins::STRING_ADD_RIGHT, JUMP_JS);
+
+ __ bind(&not_strings);
+ }
+
__ mov(r0, Operand(1)); // Set number of arguments.
__ InvokeBuiltin(builtin, JUMP_JS); // Tail call. No return.
@@ -6388,7 +6499,7 @@ void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
__ b(eq, &adaptor);
// Check index against formal parameters count limit passed in
- // through register eax. Use unsigned comparison to get negative
+ // through register r0. Use unsigned comparison to get negative
// check for free.
__ cmp(r1, r0);
__ b(cs, &slow);
View
3  deps/v8/src/arm/codegen-arm.h
@@ -366,6 +366,9 @@ class CodeGenerator: public AstVisitor {
inline void GenerateMathSin(ZoneList<Expression*>* args);
inline void GenerateMathCos(ZoneList<Expression*>* args);
+ // Fast support for StringAdd.
+ void GenerateStringAdd(ZoneList<Expression*>* args);
+
// Simple condition analysis.
enum ConditionAnalysis {
ALWAYS_TRUE,
View
27 deps/v8/src/arm/constants-arm.h
@@ -43,24 +43,27 @@
# define USE_THUMB_INTERWORK 1
#endif
-#if defined(__ARM_ARCH_5T__) || \
- defined(__ARM_ARCH_5TE__) || \
- defined(__ARM_ARCH_6__) || \
- defined(__ARM_ARCH_7A__) || \
+#if defined(__ARM_ARCH_7A__) || \
+ defined(__ARM_ARCH_7R__) || \
defined(__ARM_ARCH_7__)
-# define CAN_USE_ARMV5_INSTRUCTIONS 1
-# define CAN_USE_THUMB_INSTRUCTIONS 1
+# define CAN_USE_ARMV7_INSTRUCTIONS 1
#endif
-#if defined(__ARM_ARCH_6__) || \
- defined(__ARM_ARCH_7A__) || \
- defined(__ARM_ARCH_7__)
+#if defined(__ARM_ARCH_6__) || \
+ defined(__ARM_ARCH_6J__) || \
+ defined(__ARM_ARCH_6K__) || \
+ defined(__ARM_ARCH_6Z__) || \
+ defined(__ARM_ARCH_6ZK__) || \
+ defined(__ARM_ARCH_6T2__) || \
+ defined(CAN_USE_ARMV7_INSTRUCTIONS)
# define CAN_USE_ARMV6_INSTRUCTIONS 1
#endif
-#if defined(__ARM_ARCH_7A__) || \
- defined(__ARM_ARCH_7__)
-# define CAN_USE_ARMV7_INSTRUCTIONS 1
+#if defined(__ARM_ARCH_5T__) || \
+ defined(__ARM_ARCH_5TE__) || \
+ defined(CAN_USE_ARMV6_INSTRUCTIONS)
+# define CAN_USE_ARMV5_INSTRUCTIONS 1
+# define CAN_USE_THUMB_INSTRUCTIONS 1
#endif
// Simulator should support ARM5 instructions.
View
2  deps/v8/src/arm/debug-arm.cc
@@ -61,7 +61,7 @@ void BreakLocationIterator::SetDebugBreakAtReturn() {
// Restore the JS frame exit code.
void BreakLocationIterator::ClearDebugBreakAtReturn() {
rinfo()->PatchCode(original_rinfo()->pc(),
- Debug::kARMJSReturnSequenceLength);
+ Assembler::kJSReturnSequenceLength);
}
View
316 deps/v8/src/arm/fast-codegen-arm.cc
@@ -73,16 +73,46 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
bool function_in_register = true;
+ // Possibly allocate a local context.
+ if (fun->scope()->num_heap_slots() > 0) {
+ Comment cmnt(masm_, "[ Allocate local context");
+ // Argument to NewContext is the function, which is in r1.
+ __ push(r1);
+ __ CallRuntime(Runtime::kNewContext, 1);
+ function_in_register = false;
+ // Context is returned in both r0 and cp. It replaces the context
+ // passed to us. It's saved in the stack and kept live in cp.
+ __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+ // Copy any necessary parameters into the context.
+ int num_parameters = fun->scope()->num_parameters();
+ for (int i = 0; i < num_parameters; i++) {
+ Slot* slot = fun->scope()->parameter(i)->slot();
+ if (slot != NULL && slot->type() == Slot::CONTEXT) {
+ int parameter_offset = StandardFrameConstants::kCallerSPOffset +
+ (num_parameters - 1 - i) * kPointerSize;
+ // Load parameter from stack.
+ __ ldr(r0, MemOperand(fp, parameter_offset));
+ // Store it in the context
+ __ str(r0, MemOperand(cp, Context::SlotOffset(slot->index())));
+ }
+ }
+ }
+
Variable* arguments = fun->scope()->arguments()->AsVariable();
if (arguments != NULL) {
// Function uses arguments object.
Comment cmnt(masm_, "[ Allocate arguments object");
- __ mov(r3, r1);
+ if (!function_in_register) {
+ // Load this again, if it's used by the local context below.
+ __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ } else {
+ __ mov(r3, r1);
+ }
// Receiver is just before the parameters on the caller's stack.
__ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset +
fun->num_parameters() * kPointerSize));
__ mov(r1, Operand(Smi::FromInt(fun->num_parameters())));
- __ stm(db_w, sp, r1.bit() | r2.bit() | r3.bit());
+ __ stm(db_w, sp, r3.bit() | r2.bit() | r1.bit());
// Arguments to ArgumentsAccessStub:
// function, receiver address, parameter count.
@@ -90,33 +120,12 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
// stack frame was an arguments adapter frame.
ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
__ CallStub(&stub);
- __ str(r0, MemOperand(fp, SlotOffset(arguments->slot())));
+ // Duplicate the value; move-to-slot operation might clobber registers.
+ __ mov(r3, r0);
+ Move(arguments->slot(), r0, r1, r2);
Slot* dot_arguments_slot =
fun->scope()->arguments_shadow()->AsVariable()->slot();
- __ str(r0, MemOperand(fp, SlotOffset(dot_arguments_slot)));
- function_in_register = false;
- }
-
- // Possibly allocate a local context.
- if (fun->scope()->num_heap_slots() > 0) {
- Comment cmnt(masm_, "[ Allocate local context");
- if (!function_in_register) {
- // Load this again, if it's used by the local context below.
- __ ldr(r1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
- }
- // Argument to NewContext is the function, which is in r1.
- __ push(r1);
- __ CallRuntime(Runtime::kNewContext, 1);
- // Context is returned in both r0 and cp. It replaces the context
- // passed to us. It's saved in the stack and kept live in cp.
- __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
-#ifdef DEBUG
- // Assert we do not have to copy any parameters into the context.
- for (int i = 0, len = fun->scope()->num_parameters(); i < len; i++) {
- Slot* slot = fun->scope()->parameter(i)->slot();
- ASSERT(slot != NULL && slot->type() != Slot::CONTEXT);
- }
-#endif
+ Move(dot_arguments_slot, r3, r1, r2);
}
// Check the stack for overflow or break request.
@@ -179,7 +188,7 @@ void FastCodeGenerator::EmitReturnSequence(int position) {
// the constant pool is not emitted inside of the return sequence.
int num_parameters = function_->scope()->num_parameters();
int32_t sp_delta = (num_parameters + 1) * kPointerSize;
- int return_sequence_length = Debug::kARMJSReturnSequenceLength;
+ int return_sequence_length = Assembler::kJSReturnSequenceLength;
if (!masm_->ImmediateFitsAddrMode1Instruction(sp_delta)) {
// Additional mov instruction generated.
return_sequence_length++;
@@ -238,7 +247,42 @@ void FastCodeGenerator::Move(Expression::Context context, Register source) {
}
-void FastCodeGenerator::Move(Expression::Context context, Slot* source) {
+template <>
+MemOperand FastCodeGenerator::CreateSlotOperand<MemOperand>(
+ Slot* source,
+ Register scratch) {
+ switch (source->type()) {
+ case Slot::PARAMETER:
+ case Slot::LOCAL:
+ return MemOperand(fp, SlotOffset(source));
+ case Slot::CONTEXT: {
+ int context_chain_length =
+ function_->scope()->ContextChainLength(source->var()->scope());
+ __ LoadContext(scratch, context_chain_length);
+ return CodeGenerator::ContextOperand(scratch, source->index());
+ break;
+ }
+ case Slot::LOOKUP:
+ UNIMPLEMENTED();
+ // Fall-through.
+ default:
+ UNREACHABLE();
+ return MemOperand(r0, 0); // Dead code to make the compiler happy.
+ }
+}
+
+
+void FastCodeGenerator::Move(Register dst, Slot* source) {
+ // Use dst as scratch.
+ MemOperand location = CreateSlotOperand<MemOperand>(source, dst);
+ __ ldr(dst, location);
+}
+
+
+
+void FastCodeGenerator::Move(Expression::Context context,
+ Slot* source,
+ Register scratch) {
switch (context) {
case Expression::kUninitialized:
UNREACHABLE();
@@ -248,8 +292,8 @@ void FastCodeGenerator::Move(Expression::Context context, Slot* source) {
case Expression::kTest: // Fall through.
case Expression::kValueTest: // Fall through.
case Expression::kTestValue:
- __ ldr(ip, MemOperand(fp, SlotOffset(source)));
- Move(context, ip);
+ Move(scratch, source);
+ Move(context, scratch);
break;
}
}
@@ -272,24 +316,60 @@ void FastCodeGenerator::Move(Expression::Context context, Literal* expr) {
}
+void FastCodeGenerator::Move(Slot* dst,
+ Register src,
+ Register scratch1,
+ Register scratch2) {
+ switch (dst->type()) {
+ case Slot::PARAMETER:
+ case Slot::LOCAL:
+ __ str(src, MemOperand(fp, SlotOffset(dst)));
+ break;
+ case Slot::CONTEXT: {
+ int context_chain_length =
+ function_->scope()->ContextChainLength(dst->var()->scope());
+ __ LoadContext(scratch1, context_chain_length);
+ int index = Context::SlotOffset(dst->index());
+ __ mov(scratch2, Operand(index));
+ __ str(src, MemOperand(scratch1, index));
+ __ RecordWrite(scratch1, scratch2, src);
+ break;
+ }
+ case Slot::LOOKUP:
+ UNIMPLEMENTED();
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+
void FastCodeGenerator::DropAndMove(Expression::Context context,
- Register source) {
+ Register source,
+ int drop_count) {
+ ASSERT(drop_count > 0);
switch (context) {
case Expression::kUninitialized:
UNREACHABLE();
case Expression::kEffect:
- __ pop();
+ __ add(sp, sp, Operand(drop_count * kPointerSize));
break;
case Expression::kValue:
+ if (drop_count > 1) {
+ __ add(sp, sp, Operand((drop_count - 1) * kPointerSize));
+ }
__ str(source, MemOperand(sp));
break;
case Expression::kTest:
ASSERT(!source.is(sp));
- __ pop();
+ __ add(sp, sp, Operand(drop_count * kPointerSize));
TestAndBranch(source, true_label_, false_label_);
break;
case Expression::kValueTest: {
Label discard;
+ if (drop_count > 1) {
+ __ add(sp, sp, Operand((drop_count - 1) * kPointerSize));
+ }
__ str(source, MemOperand(sp));
TestAndBranch(source, true_label_, &discard);
__ bind(&discard);
@@ -299,6 +379,9 @@ void FastCodeGenerator::DropAndMove(Expression::Context context,
}
case Expression::kTestValue: {
Label discard;
+ if (drop_count > 1) {
+ __ add(sp, sp, Operand((drop_count - 1) * kPointerSize));
+ }
__ str(source, MemOperand(sp));
TestAndBranch(source, &discard, false_label_);
__ bind(&discard);
@@ -376,26 +459,26 @@ void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
__ mov(r0, Operand(Factory::the_hole_value()));
if (FLAG_debug_code) {
// Check if we have the correct context pointer.
- __ ldr(r1, CodeGenerator::ContextOperand(
- cp, Context::FCONTEXT_INDEX));
+ __ ldr(r1, CodeGenerator::ContextOperand(cp,
+ Context::FCONTEXT_INDEX));
__ cmp(r1, cp);
__ Check(eq, "Unexpected declaration in current context.");
}
__ str(r0, CodeGenerator::ContextOperand(cp, slot->index()));
// No write barrier since the_hole_value is in old space.
- ASSERT(Heap::InNewSpace(*Factory::the_hole_value()));
+ ASSERT(!Heap::InNewSpace(*Factory::the_hole_value()));
} else if (decl->fun() != NULL) {
Visit(decl->fun());
__ pop(r0);
if (FLAG_debug_code) {
// Check if we have the correct context pointer.
- __ ldr(r1, CodeGenerator::ContextOperand(
- cp, Context::FCONTEXT_INDEX));
+ __ ldr(r1, CodeGenerator::ContextOperand(cp,
+ Context::FCONTEXT_INDEX));
__ cmp(r1, cp);
__ Check(eq, "Unexpected declaration in current context.");
}
__ str(r0, CodeGenerator::ContextOperand(cp, slot->index()));
- int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
+ int offset = Context::SlotOffset(slot->index());
__ mov(r2, Operand(offset));
// We know that we have written a function, which is not a smi.
__ RecordWrite(cp, r2, r0);
@@ -467,53 +550,60 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
DropAndMove(expr->context(), r0);
} else if (rewrite->AsSlot() != NULL) {
Slot* slot = rewrite->AsSlot();
- ASSERT_NE(NULL, slot);
- switch (slot->type()) {
- case Slot::LOCAL:
- case Slot::PARAMETER: {
- Comment cmnt(masm_, "Stack slot");
- Move(expr->context(), rewrite->AsSlot());
- break;
- }
-
- case Slot::CONTEXT: {
- Comment cmnt(masm_, "Context slot");
- int chain_length =
- function_->scope()->ContextChainLength(slot->var()->scope());
- if (chain_length > 0) {
- // Move up the chain of contexts to the context containing the slot.
- __ ldr(r0, CodeGenerator::ContextOperand(cp, Context::CLOSURE_INDEX));
- // Load the function context (which is the incoming, outer context).
- __ ldr(r0, FieldMemOperand(r0, JSFunction::kContextOffset));
- for (int i = 1; i < chain_length; i++) {
- __ ldr(r0,
- CodeGenerator::ContextOperand(r0, Context::CLOSURE_INDEX));
- // Load the function context (which is the incoming, outer context).
- __ ldr(r0, FieldMemOperand(r0, JSFunction::kContextOffset));
- }
- // The context may be an intermediate context, not a function context.
- __ ldr(r0,
- CodeGenerator::ContextOperand(r0, Context::FCONTEXT_INDEX));
- } else { // Slot is in the current context.
- __ ldr(r0,
- CodeGenerator::ContextOperand(cp, Context::FCONTEXT_INDEX));
+ if (FLAG_debug_code) {
+ switch (slot->type()) {
+ case Slot::LOCAL:
+ case Slot::PARAMETER: {
+ Comment cmnt(masm_, "Stack slot");
+ break;
}
- __ ldr(r0, CodeGenerator::ContextOperand(r0, slot->index()));
- Move(expr->context(), r0);
- break;
+ case Slot::CONTEXT: {
+ Comment cmnt(masm_, "Context slot");
+ break;
+ }
+ case Slot::LOOKUP:
+ UNIMPLEMENTED();
+ break;
+ default:
+ UNREACHABLE();
}
-
- case Slot::LOOKUP:
- UNREACHABLE();
- break;
}
+ Move(expr->context(), slot, r0);
} else {
- // The parameter variable has been rewritten into an explict access to
- // the arguments object.
+ // A variable has been rewritten into an explicit access to
+ // an object property.
Property* property = rewrite->AsProperty();
ASSERT_NOT_NULL(property);
- ASSERT_EQ(expr->context(), property->context());
- Visit(property);
+
+ // Currently the only parameter expressions that can occur are
+ // on the form "slot[literal]".
+
+ // Check that the object is in a slot.
+ Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
+ ASSERT_NOT_NULL(object_var);
+ Slot* object_slot = object_var->slot();
+ ASSERT_NOT_NULL(object_slot);
+
+ // Load the object.
+ Move(r2, object_slot);
+
+ // Check that the key is a smi.
+ Literal* key_literal = property->key()->AsLiteral();
+ ASSERT_NOT_NULL(key_literal);
+ ASSERT(key_literal->handle()->IsSmi());
+
+ // Load the key.
+ __ mov(r1, Operand(key_literal->handle()));
+
+ // Push both as arguments to ic.
+ __ stm(db_w, sp, r2.bit() | r1.bit());
+
+ // Do a KEYED property load.
+ Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+ __ Call(ic, RelocInfo::CODE_TARGET);
+
+ // Drop key and object left on the stack by IC, and push the result.
+ DropAndMove(expr->context(), r0, 2);
}
}
@@ -575,8 +665,9 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ CallRuntime(Runtime::kCloneShallowLiteralBoilerplate, 1);
}
- // If result_saved == true: the result is saved on top of the stack.
- // If result_saved == false: the result is in r0.
+ // If result_saved == true: The result is saved on top of the
+ // stack and in r0.
+ // If result_saved == false: The result not on the stack, just in r0.
bool result_saved = false;
for (int i = 0; i < expr->properties()->length(); i++) {
@@ -604,6 +695,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET);
// StoreIC leaves the receiver on the stack.
+ __ ldr(r0, MemOperand(sp)); // Restore result into r0.
break;
}
// Fall through.
@@ -615,7 +707,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Visit(value);
ASSERT_EQ(Expression::kValue, value->context());
__ CallRuntime(Runtime::kSetProperty, 3);
- __ ldr(r0, MemOperand(sp)); // Restore result into r0
+ __ ldr(r0, MemOperand(sp)); // Restore result into r0.
break;
case ObjectLiteral::Property::GETTER: // Fall through.
@@ -785,7 +877,7 @@ void FastCodeGenerator::EmitVariableAssignment(Assignment* expr) {
// Overwrite the global object on the stack with the result if needed.
DropAndMove(expr->context(), r0);
- } else {
+ } else if (var->slot()) {
Slot* slot = var->slot();
ASSERT_NOT_NULL(slot); // Variables rewritten as properties not handled.
switch (slot->type()) {
@@ -884,6 +976,35 @@ void FastCodeGenerator::EmitVariableAssignment(Assignment* expr) {
UNREACHABLE();
break;
}
+ } else {
+ Property* property = var->rewrite()->AsProperty();
+ ASSERT_NOT_NULL(property);
+
+ // Load object and key onto the stack.
+ Slot* object_slot = property->obj()->AsSlot();
+ ASSERT_NOT_NULL(object_slot);
+ Move(Expression::kValue, object_slot, r0);
+
+ Literal* key_literal = property->key()->AsLiteral();
+ ASSERT_NOT_NULL(key_literal);
+ Move(Expression::kValue, key_literal);
+
+ // Value to store was pushed before object and key on the stack.
+ __ ldr(r0, MemOperand(sp, 2 * kPointerSize));
+
+ // Arguments to ic is value in r0, object and key on stack.
+ Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+ __ Call(ic, RelocInfo::CODE_TARGET);
+
+ if (expr->context() == Expression::kEffect) {
+ __ add(sp, sp, Operand(3 * kPointerSize));
+ } else if (expr->context() == Expression::kValue) {
+ // Value is still on the stack in esp[2 * kPointerSize]
+ __ add(sp, sp, Operand(2 * kPointerSize));
+ } else {
+ __ ldr(r0, MemOperand(sp, 2 * kPointerSize));
+ DropAndMove(expr->context(), r0, 3);
+ }
}
}
@@ -1134,9 +1255,14 @@ void FastCodeGenerator::VisitCallNew(CallNew* expr) {
void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
Comment cmnt(masm_, "[ CallRuntime");
ZoneList<Expression*>* args = expr->arguments();
- Runtime::Function* function = expr->function();
- ASSERT(function != NULL);
+ if (expr->is_jsruntime()) {
+ // Prepare for calling JS runtime function.
+ __ mov(r1, Operand(expr->name()));
+ __ ldr(r0, CodeGenerator::GlobalObject());
+ __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset));
+ __ stm(db_w, sp, r1.bit() | r0.bit());
+ }
// Push the arguments ("left-to-right").
int arg_count = args->length();
@@ -1145,8 +1271,20 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
ASSERT_EQ(Expression::kValue, args->at(i)->context());
}
- __ CallRuntime(function, arg_count);
- Move(expr->context(), r0);
+ if (expr->is_jsruntime()) {
+ // Call the JS runtime function.
+ Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
+ NOT_IN_LOOP);
+ __ Call(ic, RelocInfo::CODE_TARGET);
+ // Restore context register.
+ __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+ // Discard the function left on TOS.
+ DropAndMove(expr->context(), r0);
+ } else {
+ // Call the C runtime function.
+ __ CallRuntime(expr->function(), arg_count);
+ Move(expr->context(), r0);
+ }
}
View
13 deps/v8/src/arm/ic-arm.cc
@@ -107,12 +107,17 @@ static void GenerateDictionaryLoad(MacroAssembler* masm,
static const int kProbes = 4;
for (int i = 0; i < kProbes; i++) {
// Compute the masked index: (hash + i + i * i) & mask.
- __ ldr(t1, FieldMemOperand(r2, String::kLengthOffset));
- __ mov(t1, Operand(t1, LSR, String::kHashShift));
+ __ ldr(t1, FieldMemOperand(r2, String::kHashFieldOffset));
if (i > 0) {
- __ add(t1, t1, Operand(StringDictionary::GetProbeOffset(i)));
+ // Add the probe offset (i + i * i) left shifted to avoid right shifting
+ // the hash in a separate instruction. The value hash + i + i * i is right
+ // shifted in the following and instruction.
+ ASSERT(StringDictionary::GetProbeOffset(i) <
+ 1 << (32 - String::kHashFieldOffset));
+ __ add(t1, t1, Operand(
+ StringDictionary::GetProbeOffset(i) << String::kHashShift));
}
- __ and_(t1, t1, Operand(r3));
+ __ and_(t1, r3, Operand(t1, LSR, String::kHashShift));
// Scale the index by multiplying by the element size.
ASSERT(StringDictionary::kEntrySize == 3);
View
52 deps/v8/src/arm/macro-assembler-arm.cc
@@ -155,6 +155,15 @@ void MacroAssembler::Ret(Condition cond) {
}
+void MacroAssembler::StackLimitCheck(Label* on_stack_overflow) {
+ LoadRoot(ip, Heap::kStackLimitRootIndex);
+ cmp(sp, Operand(ip));
+ b(lo, on_stack_overflow);
+}
+
+
+
+
void MacroAssembler::SmiJumpTable(Register index, Vector<Label*> targets) {
// Empty the const pool.
CheckConstPool(true, true);
@@ -785,15 +794,13 @@ void MacroAssembler::AllocateInNewSpace(int object_size,
mov(scratch1, Operand(new_space_allocation_top));
if ((flags & RESULT_CONTAINS_TOP) == 0) {
ldr(result, MemOperand(scratch1));
- } else {
-#ifdef DEBUG
+ } else if (FLAG_debug_code) {
// Assert that result actually contains top on entry. scratch2 is used
// immediately below so this use of scratch2 does not cause difference with
// respect to register content between debug and release mode.
ldr(scratch2, MemOperand(scratch1));
cmp(result, scratch2);
Check(eq, "Unexpected allocation top");
-#endif
}
// Calculate new top and bail out if new space is exhausted. Use result
@@ -806,7 +813,11 @@ void MacroAssembler::AllocateInNewSpace(int object_size,
cmp(result, Operand(scratch2));
b(hi, gc_required);
- // Update allocation top. result temporarily holds the new top,
+ // Update allocation top. result temporarily holds the new top.
+ if (FLAG_debug_code) {
+ tst(result, Operand(kObjectAlignmentMask));
+ Check(eq, "Unaligned allocation in new space");
+ }
str(result, MemOperand(scratch1));
// Tag and adjust back to start of new object.
@@ -835,15 +846,13 @@ void MacroAssembler::AllocateInNewSpace(Register object_size,
mov(scratch1, Operand(new_space_allocation_top));
if ((flags & RESULT_CONTAINS_TOP) == 0) {
ldr(result, MemOperand(scratch1));
- } else {
-#ifdef DEBUG
+ } else if (FLAG_debug_code) {
// Assert that result actually contains top on entry. scratch2 is used
// immediately below so this use of scratch2 does not cause difference with
// respect to register content between debug and release mode.
ldr(scratch2, MemOperand(scratch1));
cmp(result, scratch2);
Check(eq, "Unexpected allocation top");
-#endif
}
// Calculate new top and bail out if new space is exhausted. Use result
@@ -857,7 +866,11 @@ void MacroAssembler::AllocateInNewSpace(Register object_size,
cmp(result, Operand(scratch2));
b(hi, gc_required);
- // Update allocation top. result temporarily holds the new top,
+ // Update allocation top. result temporarily holds the new top.
+ if (FLAG_debug_code) {
+ tst(result, Operand(kObjectAlignmentMask));
+ Check(eq, "Unaligned allocation in new space");
+ }
str(result, MemOperand(scratch1));
// Adjust back to start of new object.
@@ -1153,6 +1166,9 @@ void MacroAssembler::Abort(const char* msg) {
RecordComment(msg);
}
#endif
+ // Disable stub call restrictions to always allow calls to abort.
+ set_allow_stub_calls(true);
+
mov(r0, Operand(p0));
push(r0);
mov(r0, Operand(Smi::FromInt(p1 - p0)));
@@ -1162,6 +1178,26 @@ void MacroAssembler::Abort(const char* msg) {
}
+void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
+ if (context_chain_length > 0) {
+ // Move up the chain of contexts to the context containing the slot.
+ ldr(dst, MemOperand(cp, Context::SlotOffset(Context::CLOSURE_INDEX)));
+ // Load the function context (which is the incoming, outer context).
+ ldr(dst, FieldMemOperand(dst, JSFunction::kContextOffset));
+ for (int i = 1; i < context_chain_length; i++) {
+ ldr(dst, MemOperand(dst, Context::SlotOffset(Context::CLOSURE_INDEX)));
+ ldr(dst, FieldMemOperand(dst, JSFunction::kContextOffset));
+ }
+ // The context may be an intermediate context, not a function context.
+ ldr(dst, MemOperand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX)));
+ } else { // Slot is in the current function context.
+ // The context may be an intermediate context, not a function context.
+ ldr(dst, MemOperand(cp, Context::SlotOffset(Context::FCONTEXT_INDEX)));
+ }
+}
+
+
+
#ifdef ENABLE_DEBUGGER_SUPPORT
CodePatcher::CodePatcher(byte* address, int instructions)
: address_(address),
View
7 deps/v8/src/arm/macro-assembler-arm.h
@@ -79,6 +79,11 @@ class MacroAssembler: public Assembler {
void RecordWrite(Register object, Register offset, Register scratch);
// ---------------------------------------------------------------------------
+ // Stack limit support
+
+ void StackLimitCheck(Label* on_stack_limit_hit);
+
+ // ---------------------------------------------------------------------------
// Activation frames
void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }
@@ -99,6 +104,8 @@ class MacroAssembler: public Assembler {
// Align the stack by optionally pushing a Smi zero.
void AlignStack(int offset);
+ void LoadContext(Register dst, int context_chain_length);
+
// ---------------------------------------------------------------------------
// JavaScript invokes
View
5 deps/v8/src/arm/stub-cache-arm.cc
@@ -105,7 +105,7 @@ void StubCache::GenerateProbe(MacroAssembler* masm,
__ b(eq, &miss);
// Get the map of the receiver and compute the hash.
- __ ldr(scratch, FieldMemOperand(name, String::kLengthOffset));
+ __ ldr(scratch, FieldMemOperand(name, String::kHashFieldOffset));
__ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset));
__ add(scratch, scratch, Operand(ip));
__ eor(scratch, scratch, Operand(flags));
@@ -229,10 +229,7 @@ void StubCompiler::GenerateLoadStringLength2(MacroAssembler* masm,
miss, &check_wrapper);
// Load length directly from the string.
- __ and_(scratch1, scratch1, Operand(kStringSizeMask));
- __ add(scratch1, scratch1, Operand(String::kHashShift));
__ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset));
- __ mov(r0, Operand(r0, LSR, scratch1));
__ mov(r0, Operand(r0, LSL, kSmiTagSize));
__ Ret();
View
36 deps/v8/src/array.js
@@ -77,7 +77,8 @@ function SparseJoin(array, len, convert) {
var key = keys[i];
if (key != last_key) {
var e = array[key];
- builder.add(convert(e));
+ if (typeof(e) !== 'string') e = convert(e);
+ builder.add(e);
last_key = key;
}
}
@@ -114,17 +115,36 @@ function Join(array, length, separator, convert) {
if (length == 1) {
var e = array[0];
if (!IS_UNDEFINED(e) || (0 in array)) {
+ if (typeof(e) === 'string') return e;
return convert(e);
}
}
var builder = new StringBuilder();
- for (var i = 0; i < length; i++) {
- var e = array[i];
- if (i != 0) builder.add(separator);
- if (!IS_UNDEFINED(e) || (i in array)) {
- builder.add(convert(e));
+ // We pull the empty separator check outside the loop for speed!
+ if (separator.length == 0) {
+ for (var i = 0; i < length; i++) {
+ var e = array[i];
+ if (!IS_UNDEFINED(e) || (i in array)) {
+ if (typeof(e) !== 'string') e = convert(e);
+ if (e.length > 0) {
+ var elements = builder.elements;
+ elements[elements.length] = e;
+ }
+ }
+ }
+ } else {
+ for (var i = 0; i < length; i++) {
+ var e = array[i];
+ if (i != 0) builder.add(separator);
+ if (!IS_UNDEFINED(e) || (i in array)) {
+ if (typeof(e) !== 'string') e = convert(e);
+ if (e.length > 0) {
+ var elements = builder.elements;
+ elements[elements.length] = e;
+ }
+ }
}
}
return builder.generate();
@@ -136,12 +156,14 @@ function Join(array, length, separator, convert) {
function ConvertToString(e) {
+ if (typeof(e) === 'string') return e;
if (e == null) return '';
else return ToString(e);
}
function ConvertToLocaleString(e) {
+ if (typeof(e) === 'string') return e;
if (e == null) return '';
else {
// e_obj's toLocaleString might be overwritten, check if it is a function.
@@ -149,7 +171,7 @@ function ConvertToLocaleString(e) {
// See issue 877615.
var e_obj = ToObject(e);
if (IS_FUNCTION(e_obj.toLocaleString))
- return e_obj.toLocaleString();
+ return ToString(e_obj.toLocaleString());
else
return ToString(e);
}
View
1  deps/v8/src/ast.h
@@ -1080,6 +1080,7 @@ class CallRuntime: public Expression {
Handle<String> name() const { return name_; }
Runtime::Function* function() const { return function_; }
ZoneList<Expression*>* arguments() const { return arguments_; }
+ bool is_jsruntime() const { return function_ == NULL; }
private:
Handle<String> name_;
View
26 deps/v8/src/bootstrapper.cc
@@ -1111,21 +1111,29 @@ bool Genesis::InstallNatives() {
Factory::LookupAsciiSymbol("context_data"),
proxy_context_data,
common_attributes);
- Handle<Proxy> proxy_eval_from_function =
- Factory::NewProxy(&Accessors::ScriptEvalFromFunction);
+ Handle<Proxy> proxy_eval_from_script =
+ Factory::NewProxy(&Accessors::ScriptEvalFromScript);
script_descriptors =
Factory::CopyAppendProxyDescriptor(
script_descriptors,
- Factory::LookupAsciiSymbol("eval_from_function"),
- proxy_eval_from_function,
+ Factory::LookupAsciiSymbol("eval_from_script"),
+ proxy_eval_from_script,
common_attributes);
- Handle<Proxy> proxy_eval_from_position =
- Factory::NewProxy(&Accessors::ScriptEvalFromPosition);
+ Handle<Proxy> proxy_eval_from_script_position =
+ Factory::NewProxy(&Accessors::ScriptEvalFromScriptPosition);
script_descriptors =
Factory::CopyAppendProxyDescriptor(
script_descriptors,
- Factory::LookupAsciiSymbol("eval_from_position"),
- proxy_eval_from_position,
+ Factory::LookupAsciiSymbol("eval_from_script_position"),
+ proxy_eval_from_script_position,
+ common_attributes);
+ Handle<Proxy> proxy_eval_from_function_name =
+ Factory::NewProxy(&Accessors::ScriptEvalFromFunctionName);
+ script_descriptors =
+ Factory::CopyAppendProxyDescriptor(
+ script_descriptors,
+ Factory::LookupAsciiSymbol("eval_from_function_name"),
+ proxy_eval_from_function_name,
common_attributes);
Handle<Map> script_map = Handle<Map>(script_fun->initial_map());
@@ -1338,8 +1346,6 @@ bool Genesis::InstallExtension(v8::RegisteredExtension* current) {
ASSERT(Top::has_pending_exception() != result);
if (!result) {
Top::clear_pending_exception();
- v8::Utils::ReportApiFailure(
- "v8::Context::New()", "Error installing extension");
}
current->set_state(v8::INSTALLED);
return result;
View
1  deps/v8/src/code-stubs.h
@@ -36,6 +36,7 @@ namespace internal {
#define CODE_STUB_LIST_ALL_PLATFORMS(V) \
V(CallFunction) \
V(GenericBinaryOp) \
+ V(StringAdd) \
V(SmiOp) \
V(Compare) \
V(RecordWrite) \
View
1  deps/v8/src/codegen.cc
@@ -346,6 +346,7 @@ CodeGenerator::InlineRuntimeLUT CodeGenerator::kInlineRuntimeLUT[] = {
{&CodeGenerator::GenerateMathCos, "_Math_cos"},
{&CodeGenerator::GenerateIsObject, "_IsObject"},
{&CodeGenerator::GenerateIsFunction, "_IsFunction"},
+ {&CodeGenerator::GenerateStringAdd, "_StringAdd"},
};
View
50 deps/v8/src/compiler.cc
@@ -124,9 +124,12 @@ static Handle<Code> MakeCode(FunctionLiteral* literal,
// If there is no shared function info, try the fast code
// generator for code in the global scope. Otherwise obey the
// explicit hint in the shared function info.
- if (shared.is_null() && !literal->scope()->is_global_scope()) {
+ // If always_fast_compiler is true, always try the fast compiler.
+ if (shared.is_null() && !literal->scope()->is_global_scope() &&
+ !FLAG_always_fast_compiler) {
if (FLAG_trace_bailout) PrintF("Non-global scope\n");
- } else if (!shared.is_null() && !shared->try_fast_codegen()) {
+ } else if (!shared.is_null() && !shared->try_fast_codegen() &&
+ !FLAG_always_fast_compiler) {
if (FLAG_trace_bailout) PrintF("No hint to try fast\n");
} else {
CodeGenSelector selector;
@@ -176,7 +179,8 @@ static Handle<JSFunction> MakeFunction(bool is_global,
// called.
if (is_eval) {
JavaScriptFrameIterator it;
- script->set_eval_from_function(it.frame()->function());
+ script->set_eval_from_shared(
+ JSFunction::cast(it.frame()->function())->shared());
int offset = static_cast<int>(
it.frame()->pc() - it.frame()->code()->instruction_start());
script->set_eval_from_instructions_offset(Smi::FromInt(offset));
@@ -599,11 +603,6 @@ CodeGenSelector::CodeGenTag CodeGenSelector::Select(FunctionLiteral* fun) {
}
}
- if (scope->arguments() != NULL) {
- if (FLAG_trace_bailout) PrintF("function uses 'arguments'\n");
- return NORMAL;
- }
-
has_supported_syntax_ = true;
VisitDeclarations(scope->declarations());
if (!has_supported_syntax_) return NORMAL;
@@ -802,7 +801,17 @@ void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) {
BAILOUT("Lookup slot");
}
} else {
- BAILOUT("access to arguments object");
+#ifdef DEBUG
+ // Only remaining possibility is a property where the object is
+ // a slotted variable and the key is a smi.
+ Property* property = rewrite->AsProperty();
+ ASSERT_NOT_NULL(property);
+ Variable* object = property->obj()->AsVariableProxy()->AsVariable();
+ ASSERT_NOT_NULL(object);
+ ASSERT_NOT_NULL(object->slot());
+ ASSERT_NOT_NULL(property->key()->AsLiteral());
+ ASSERT(property->key()->AsLiteral()->handle()->IsSmi());
+#endif
}
}
}
@@ -886,12 +895,21 @@ void CodeGenSelector::VisitAssignment(Assignment* expr) {
// All global variables are supported.
if (!var->is_global()) {
if (var->slot() == NULL) {
- // This is a parameter that has rewritten to an arguments access.
- BAILOUT("non-global/non-slot assignment");
- }
- Slot::Type type = var->slot()->type();
- if (type == Slot::LOOKUP) {
- BAILOUT("Lookup slot");
+ Property* property = var->AsProperty();
+ if (property == NULL) {
+ BAILOUT("non-global/non-slot/non-property assignment");
+ }
+ if (property->obj()->AsSlot() == NULL) {
+ BAILOUT("variable rewritten to property non slot object assignment");
+ }
+ if (property->key()->AsLiteral() == NULL) {
+ BAILOUT("variable rewritten to property non literal key assignment");
+ }
+ } else {
+ Slot::Type type = var->slot()->type();
+ if (type == Slot::LOOKUP) {
+ BAILOUT("Lookup slot");
+ }
}
}
} else if (prop != NULL) {
@@ -979,8 +997,6 @@ void CodeGenSelector::VisitCallNew(CallNew* expr) {
void CodeGenSelector::VisitCallRuntime(CallRuntime* expr) {
- // In case of JS runtime function bail out.
- if (expr->function() == NULL) BAILOUT("call JS runtime function");
// Check for inline runtime call
if (expr->name()->Get(0) == '_' &&
CodeGenerator::FindInlineRuntimeLUT(expr->name()) != NULL) {
View
8 deps/v8/src/d8.cc
@@ -159,7 +159,11 @@ Handle<Value> Shell::Write(const Arguments& args) {
printf(" ");
}
v8::String::Utf8Value str(args[i]);
- fwrite(*str, sizeof(**str), str.length(), stdout);
+ int n = fwrite(*str, sizeof(**str), str.length(), stdout);
+ if (n != str.length()) {
+ printf("Error in fwrite\n");
+ exit(1);
+ }
}
return Undefined();
}
@@ -203,7 +207,7 @@ Handle<Value> Shell::Load(const Arguments& args) {
return ThrowException(String::New("Error loading file"));
}
if (!ExecuteString(source, String::New(*file), false, false)) {
- return ThrowException(String::New("Error executing file"));
+ return ThrowException(String::New("Error executing file"));
}
}
return Undefined();
View
21 deps/v8/src/debug-delay.js
@@ -1245,6 +1245,8 @@ DebugCommandProcessor.prototype.processDebugJSONRequest = function(json_request)
this.suspendRequest_(request, response);
} else if (request.command == 'version') {
this.versionRequest_(request, response);
+ } else if (request.command == 'profile') {
+ this.profileRequest_(request, response);
} else {
throw new Error('Unknown command "' + request.command + '" in request');
}
@@ -1924,6 +1926,25 @@ DebugCommandProcessor.prototype.versionRequest_ = function(request, response) {
};
+DebugCommandProcessor.prototype.profileRequest_ = function(request, response) {
+ if (!request.arguments) {
+ return response.failed('Missing arguments');
+ }
+ var modules = parseInt(request.arguments.modules);
+ if (isNaN(modules)) {
+ return response.failed('Modules is not an integer');
+ }
+ if (request.arguments.command == 'resume') {
+ %ProfilerResume(modules);
+ } else if (request.arguments.command == 'pause') {
+ %ProfilerPause(modules);
+ } else {
+ return response.failed('Unknown command');
+ }
+ response.body = {};
+};
+
+
// Check whether the previously processed command caused the VM to become
// running.
DebugCommandProcessor.prototype.isRunning = function() {
View
11 deps/v8/src/debug.h
@@ -370,17 +370,6 @@ class Debug {
// Garbage collection notifications.
static void AfterGarbageCollection();
- // Code generation assumptions.
- static const int kIa32CallInstructionLength = 5;
- static const int kIa32JSReturnSequenceLength = 6;
-
- // The x64 JS return sequence is padded with int3 to make it large
- // enough to hold a call instruction when the debugger patches it.
- static const int kX64CallInstructionLength = 13;
- static const int kX64JSReturnSequenceLength = 13;
-
- static const int kARMJSReturnSequenceLength = 4;
-
// Code generator routines.
static void GenerateLoadICDebugBreak(MacroAssembler* masm);
static void GenerateStoreICDebugBreak(MacroAssembler* masm);
View
8 deps/v8/src/dtoa-config.c
@@ -38,7 +38,7 @@
*/
#if !(defined(__APPLE__) && defined(__MACH__)) && \
- !defined(WIN32) && !defined(__FreeBSD__)
+ !defined(WIN32) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
#include <endian.h>
#endif
#include <math.h>
@@ -47,14 +47,16 @@
/* The floating point word order on ARM is big endian when floating point
* emulation is used, even if the byte order is little endian */
#if !(defined(__APPLE__) && defined(__MACH__)) && !defined(WIN32) && \
- !defined(__FreeBSD__) && __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ !defined(__FreeBSD__) && !defined(__OpenBSD__) && \
+ __FLOAT_WORD_ORDER == __BIG_ENDIAN
#define IEEE_MC68k
#else
#define IEEE_8087
#endif
#define __MATH_H__
-#if defined(__APPLE__) && defined(__MACH__) || defined(__FreeBSD__)
+#if defined(__APPLE__) && defined(__MACH__) || defined(__FreeBSD__) || \
+ defined(__OpenBSD__)
/* stdlib.h on FreeBSD and Apple's 10.5 and later SDKs will mangle the
* name of strtod. If it's included after strtod is redefined as
* gay_strtod, it will mangle the name of gay_strtod, which is
View
5 deps/v8/src/factory.cc
@@ -188,9 +188,8 @@ Handle<Script> Factory::NewScript(Handle<String> source) {
script->set_type(Smi::FromInt(Script::TYPE_NORMAL));
script->set_compilation_type(Smi::FromInt(Script::COMPILATION_TYPE_HOST));
script->set_wrapper(*wrapper);
- script->set_line_ends_fixed_array(Heap::undefined_value());
- script->set_line_ends_js_array(Heap::undefined_value());
- script->set_eval_from_function(Heap::undefined_value());
+ script->set_line_ends(Heap::undefined_value());
+ script->set_eval_from_shared(Heap::undefined_value());
script->set_eval_from_instructions_offset(Smi::FromInt(0));
return script;
View
37 deps/v8/src/fast-codegen.cc
@@ -305,12 +305,15 @@ void FastCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
void FastCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
Comment cmnt(masm_, "[ DoWhileStatement");
increment_loop_depth();
- Label body, exit;
+ Label body, exit, stack_limit_hit, stack_check_success;
- // Emit the test at the bottom of the loop.
__ bind(&body);
Visit(stmt->body());
+ // Check stack before looping.
+ __ StackLimitCheck(&stack_limit_hit);
+ __ bind(&stack_check_success);
+
// We are not in an expression context because we have been compiling
// statements. Set up a test expression context for the condition.
ASSERT_EQ(NULL, true_label_);
@@ -322,6 +325,11 @@ void FastCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
true_label_ = NULL;
false_label_ = NULL;
+ __ bind(&stack_limit_hit);
+ StackCheckStub stack_stub;
+ __ CallStub(&stack_stub);
+ __ jmp(&stack_check_success);
+
__ bind(&exit);
decrement_loop_depth();
@@ -331,7 +339,7 @@ void FastCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
Comment cmnt(masm_, "[ WhileStatement");
increment_loop_depth();
- Label test, body, exit;
+ Label test, body, exit, stack_limit_hit, stack_check_success;
// Emit the test at the bottom of the loop.
__ jmp(&test);
@@ -340,6 +348,10 @@ void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
Visit(stmt->body());
__ bind(&test);
+ // Check stack before looping.
+ __ StackLimitCheck(&stack_limit_hit);
+ __ bind(&stack_check_success);
+
// We are not in an expression context because we have been compiling
// statements. Set up a test expression context for the condition.
ASSERT_EQ(NULL, true_label_);
@@ -351,6 +363,11 @@ void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
true_label_ = NULL;
false_label_ = NULL;
+ __ bind(&stack_limit_hit);
+ StackCheckStub stack_stub;
+ __ CallStub(&stack_stub);
+ __ jmp(&stack_check_success);
+
__ bind(&exit);
decrement_loop_depth();
@@ -359,7 +376,7 @@ void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
void FastCodeGenerator::VisitForStatement(ForStatement* stmt) {
Comment cmnt(masm_, "[ ForStatement");
- Label test, body, exit;
+ Label test, body, exit, stack_limit_hit, stack_check_success;
if (stmt->init() != NULL) Visit(stmt->init());
increment_loop_depth();
@@ -367,9 +384,15 @@ void FastCodeGenerator::VisitForStatement(ForStatement* stmt) {
__ jmp(&test);
__ bind(&body);
Visit(stmt->body());
+
+ // Check stack before looping.
+ __ StackLimitCheck(&stack_limit_hit);
+ __ bind(&stack_check_success);
+
if (stmt->next() != NULL) Visit(stmt->next());
__ bind(&test);
+
if (stmt->cond() == NULL) {
// For an empty test jump to the top of the loop.
__ jmp(&body);
@@ -378,6 +401,7 @@ void FastCodeGenerator::VisitForStatement(ForStatement* stmt) {
// statements. Set up a test expression context for the condition.
ASSERT_EQ(NULL, true_label_);
ASSERT_EQ(NULL, false_label_);
+
true_label_ = &body;
false_label_ = &exit;
ASSERT(stmt->cond()->context() == Expression::kTest);
@@ -386,6 +410,11 @@ void FastCodeGenerator::VisitForStatement(ForStatement* stmt) {
false_label_ = NULL;
}
+ __ bind(&stack_limit_hit);
+ StackCheckStub stack_stub;
+ __ CallStub(&stack_stub);
+ __ jmp(&stack_check_success);
+
__ bind(&exit);
decrement_loop_depth();
}
View
13 deps/v8/src/fast-codegen.h
@@ -56,14 +56,21 @@ class FastCodeGenerator: public AstVisitor {
private:
int SlotOffset(Slot* slot);
-
void Move(Expression::Context destination, Register source);
- void Move(Expression::Context destination, Slot* source);
+ void Move(Expression::Context destination, Slot* source, Register scratch);
void Move(Expression::Context destination, Literal* source);
+ void Move(Slot* dst, Register source, Register scratch1, Register scratch2);
+ void Move(Register dst, Slot* source);
+
+ // Templated to allow for Operand on intel and MemOperand on ARM.
+ template <typename MemoryLocation>
+ MemoryLocation CreateSlotOperand(Slot* slot, Register scratch);
// Drop the TOS, and store source to destination.
// If destination is TOS, just overwrite TOS with source.
- void DropAndMove(Expression::Context destination, Register source);
+ void DropAndMove(Expression::Context destination,
+ Register source,
+ int drop_count = 1);
// Test the JavaScript value in source as if in a test context, compile
// control flow to a pair of labels.
View
8 deps/v8/src/flag-definitions.h
@@ -143,10 +143,12 @@ DEFINE_bool(debug_info, true, "add debug information to compiled functions")
DEFINE_bool(strict, false, "strict error checking")
DEFINE_int(min_preparse_length, 1024,
"minimum length for automatic enable preparsing")
-DEFINE_bool(fast_compiler, false,
+DEFINE_bool(fast_compiler, true,
"use the fast-mode compiler for some top-level code")
DEFINE_bool(trace_bailout, false,
"print reasons for failing to use fast compilation")
+DEFINE_bool(always_fast_compiler, false,
+ "always try using the fast compiler")
// compilation-cache.cc
DEFINE_bool(compilation_cache, true, "enable compilation cache")
@@ -154,9 +156,9 @@ DEFINE_bool(compilation_cache, true, "enable compilation cache")
// debug.cc
DEFINE_bool(remote_debugging, false, "enable remote debugging")
DEFINE_bool(trace_debug_json, false, "trace debugging JSON request/response")
-DEFINE_bool(debugger_auto_break, false,
+DEFINE_bool(debugger_auto_break, true,
"automatically set the debug break flag when debugger commands are "
- "in the queue (experimental)")
+ "in the queue")
// frames.cc
DEFINE_int(max_stack_trace_source_length, 300,
View
20 deps/v8/src/global-handles.cc
@@ -429,6 +429,26 @@ GlobalHandles::Node* GlobalHandles::head_ = NULL;
GlobalHandles::Node* GlobalHandles::first_free_ = NULL;
GlobalHandles::Node* GlobalHandles::first_deallocated_ = NULL;
+void GlobalHandles::RecordStats(HeapStats* stats) {
+ *stats->global_handle_count = 0;
+ *stats->weak_global_handle_count = 0;
+ *stats->pending_global_handle_count = 0;
+ *stats->near_death_global_handle_count = 0;
+ *stats->destroyed_global_handle_count = 0;
+ for (Node* current = head_; current != NULL; current = current->next()) {
+ *stats->global_handle_count++;
+ if (current->state_ == Node::WEAK) {
+ *stats->weak_global_handle_count++;
+ } else if (current->state_ == Node::PENDING) {
+ *stats->pending_global_handle_count++;
+ } else if (current->state_ == Node::NEAR_DEATH) {
+ *stats->near_death_global_handle_count++;
+ } else if (current->state_ == Node::DESTROYED) {
+ *stats->destroyed_global_handle_count++;
+ }
+ }
+}
+
#ifdef DEBUG
void GlobalHandles::PrintStats() {
View
2  deps/v8/src/global-handles.h
@@ -78,6 +78,8 @@ class GlobalHandles : public AllStatic {
// Returns the current number of weak handles.
static int NumberOfWeakHandles() { return number_of_weak_handles_; }
+ static void RecordStats(HeapStats* stats);
+
// Returns the current number of weak handles to global objects.
// These handles are also included in NumberOfWeakHandles().
static int NumberOfGlobalObjectWeakHandles() {
View
48 deps/v8/src/handles.cc
@@ -429,12 +429,12 @@ Handle<JSValue> GetScriptWrapper(Handle<Script> script) {
// Init line_ends array with code positions of line ends inside script
// source.
void InitScriptLineEnds(Handle<Script> script) {
- if (!script->line_ends_fixed_array()->IsUndefined()) return;
+ if (!script->line_ends()->IsUndefined()) return;
if (!script->source()->IsString()) {
ASSERT(script->source()->IsUndefined());
- script->set_line_ends_fixed_array(*(Factory::NewFixedArray(0)));
- ASSERT(script->line_ends_fixed_array()->IsFixedArray());
+ script->set_line_ends(*(Factory::NewFixedArray(0)));
+ ASSERT(script->line_ends()->IsFixedArray());
return;
}
@@ -467,8 +467,8 @@ void InitScriptLineEnds(Handle<Script> script) {
}
ASSERT(array_index == line_count);
- script->set_line_ends_fixed_array(*array);
- ASSERT(script->line_ends_fixed_array()->IsFixedArray());
+ script->set_line_ends(*array);
+ ASSERT(script->line_ends()->IsFixedArray());
}
@@ -477,7 +477,7 @@ int GetScriptLineNumber(Handle<Script> script, int code_pos) {
InitScriptLineEnds(script);
AssertNoAllocation no_allocation;
FixedArray* line_ends_array =