summaryrefslogtreecommitdiff
path: root/deps/v8/test
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test')
-rw-r--r--deps/v8/test/cctest/SConscript4
-rw-r--r--deps/v8/test/cctest/test-api.cc162
-rw-r--r--deps/v8/test/cctest/test-assembler-x64.cc54
-rw-r--r--deps/v8/test/cctest/test-debug.cc138
-rw-r--r--deps/v8/test/cctest/test-disasm-ia32.cc24
-rw-r--r--deps/v8/test/cctest/test-heap.cc13
-rwxr-xr-xdeps/v8/test/cctest/test-macro-assembler-x64.cc2096
-rw-r--r--deps/v8/test/mjsunit/compiler/literals-assignment.js71
-rw-r--r--deps/v8/test/mjsunit/compiler/literals.js35
-rw-r--r--deps/v8/test/mjsunit/debug-backtrace.js22
-rw-r--r--deps/v8/test/mjsunit/debug-changebreakpoint.js2
-rw-r--r--deps/v8/test/mjsunit/debug-clearbreakpoint.js2
-rw-r--r--deps/v8/test/mjsunit/debug-clearbreakpointgroup.js2
-rw-r--r--deps/v8/test/mjsunit/debug-continue.js31
-rw-r--r--deps/v8/test/mjsunit/debug-evaluate-bool-constructor.js80
-rw-r--r--deps/v8/test/mjsunit/debug-evaluate-recursive.js28
-rw-r--r--deps/v8/test/mjsunit/debug-evaluate.js7
-rw-r--r--deps/v8/test/mjsunit/debug-handle.js49
-rw-r--r--deps/v8/test/mjsunit/debug-mirror-cache.js10
-rw-r--r--deps/v8/test/mjsunit/debug-references.js4
-rw-r--r--deps/v8/test/mjsunit/debug-scopes.js4
-rw-r--r--deps/v8/test/mjsunit/debug-scripts-request.js2
-rw-r--r--deps/v8/test/mjsunit/debug-setbreakpoint.js2
-rw-r--r--deps/v8/test/mjsunit/debug-suspend.js96
-rw-r--r--deps/v8/test/mjsunit/for-in.js44
-rw-r--r--deps/v8/test/mjsunit/regress/regress-1081309.js4
-rw-r--r--deps/v8/test/mjsunit/regress/regress-1199401.js78
-rw-r--r--deps/v8/test/mjsunit/smi-negative-zero.js84
-rw-r--r--deps/v8/test/mjsunit/testcfg.py3
-rw-r--r--deps/v8/test/mjsunit/third_party/array-isarray.js48
-rw-r--r--deps/v8/test/mjsunit/third_party/string-trim.js107
31 files changed, 3076 insertions, 230 deletions
diff --git a/deps/v8/test/cctest/SConscript b/deps/v8/test/cctest/SConscript
index 91034034a1..f041041c11 100644
--- a/deps/v8/test/cctest/SConscript
+++ b/deps/v8/test/cctest/SConscript
@@ -67,7 +67,9 @@ SOURCES = {
'test-disasm-ia32.cc',
'test-log-stack-tracer.cc'
],
- 'arch:x64': ['test-assembler-x64.cc', 'test-log-stack-tracer.cc'],
+ 'arch:x64': ['test-assembler-x64.cc',
+ 'test-macro-assembler-x64.cc',
+ 'test-log-stack-tracer.cc'],
'os:linux': ['test-platform-linux.cc'],
'os:macos': ['test-platform-macos.cc'],
'os:nullos': ['test-platform-nullos.cc'],
diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc
index 2282c2d9b9..c63ba31652 100644
--- a/deps/v8/test/cctest/test-api.cc
+++ b/deps/v8/test/cctest/test-api.cc
@@ -25,8 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include <stdlib.h>
-
#include "v8.h"
#include "api.h"
@@ -574,6 +572,44 @@ THREADED_TEST(UsingExternalAsciiString) {
}
+THREADED_TEST(StringConcat) {
+ {
+ v8::HandleScope scope;
+ LocalContext env;
+ const char* one_byte_string_1 = "function a_times_t";
+ const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
+ const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
+ const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
+ const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
+ const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
+ const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
+ Local<String> left = v8_str(one_byte_string_1);
+ Local<String> right = String::New(AsciiToTwoByteString(two_byte_string_1));
+ Local<String> source = String::Concat(left, right);
+ right = String::NewExternal(
+ new TestAsciiResource(i::StrDup(one_byte_extern_1)));
+ source = String::Concat(source, right);
+ right = String::NewExternal(
+ new TestResource(AsciiToTwoByteString(two_byte_extern_1)));
+ source = String::Concat(source, right);
+ right = v8_str(one_byte_string_2);
+ source = String::Concat(source, right);
+ right = String::New(AsciiToTwoByteString(two_byte_string_2));
+ source = String::Concat(source, right);
+ right = String::NewExternal(
+ new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
+ source = String::Concat(source, right);
+ Local<Script> script = Script::Compile(source);
+ Local<Value> value = script->Run();
+ CHECK(value->IsNumber());
+ CHECK_EQ(68, value->Int32Value());
+ }
+ v8::internal::CompilationCache::Clear();
+ i::Heap::CollectAllGarbage(false);
+ i::Heap::CollectAllGarbage(false);
+}
+
+
THREADED_TEST(GlobalProperties) {
v8::HandleScope scope;
LocalContext env;
@@ -702,6 +738,88 @@ THREADED_TEST(PropertyHandler) {
}
+THREADED_TEST(TinyInteger) {
+ v8::HandleScope scope;
+ LocalContext env;
+ int32_t value = 239;
+ Local<v8::Integer> value_obj = v8::Integer::New(value);
+ CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
+}
+
+
+THREADED_TEST(BigSmiInteger) {
+ v8::HandleScope scope;
+ LocalContext env;
+ int32_t value = i::Smi::kMaxValue;
+ // We cannot add one to a Smi::kMaxValue without wrapping.
+ if (i::kSmiValueSize < 32) {
+ CHECK(i::Smi::IsValid(value));
+ CHECK(!i::Smi::IsValid(value + 1));
+ Local<v8::Integer> value_obj = v8::Integer::New(value);
+ CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
+ }
+}
+
+
+THREADED_TEST(BigInteger) {
+ v8::HandleScope scope;
+ LocalContext env;
+ // We cannot add one to a Smi::kMaxValue without wrapping.
+ if (i::kSmiValueSize < 32) {
+ // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
+ // The code will not be run in that case, due to the "if" guard.
+ int32_t value =
+ static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
+ CHECK(value > i::Smi::kMaxValue);
+ CHECK(!i::Smi::IsValid(value));
+ Local<v8::Integer> value_obj = v8::Integer::New(value);
+ CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
+ }
+}
+
+
+THREADED_TEST(TinyUnsignedInteger) {
+ v8::HandleScope scope;
+ LocalContext env;
+ uint32_t value = 239;
+ Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
+ CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
+}
+
+
+THREADED_TEST(BigUnsignedSmiInteger) {
+ v8::HandleScope scope;
+ LocalContext env;
+ uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
+ CHECK(i::Smi::IsValid(value));
+ CHECK(!i::Smi::IsValid(value + 1));
+ Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
+ CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
+}
+
+
+THREADED_TEST(BigUnsignedInteger) {
+ v8::HandleScope scope;
+ LocalContext env;
+ uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
+ CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
+ CHECK(!i::Smi::IsValid(value));
+ Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
+ CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
+}
+
+
+THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
+ v8::HandleScope scope;
+ LocalContext env;
+ uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
+ uint32_t value = INT32_MAX_AS_UINT + 1;
+ CHECK(value > INT32_MAX_AS_UINT); // No overflow.
+ Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
+ CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
+}
+
+
THREADED_TEST(Number) {
v8::HandleScope scope;
LocalContext env;
@@ -1346,6 +1464,44 @@ THREADED_TEST(InternalFieldsNativePointers) {
}
+THREADED_TEST(InternalFieldsNativePointersAndExternal) {
+ v8::HandleScope scope;
+ LocalContext env;
+
+ Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+ Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
+ instance_templ->SetInternalFieldCount(1);
+ Local<v8::Object> obj = templ->GetFunction()->NewInstance();
+ CHECK_EQ(1, obj->InternalFieldCount());
+ CHECK(obj->GetPointerFromInternalField(0) == NULL);
+
+ char* data = new char[100];
+
+ void* aligned = data;
+ CHECK_EQ(0, reinterpret_cast<uintptr_t>(aligned) & 0x1);
+ void* unaligned = data + 1;
+ CHECK_EQ(1, reinterpret_cast<uintptr_t>(unaligned) & 0x1);
+
+ obj->SetPointerInInternalField(0, aligned);
+ i::Heap::CollectAllGarbage(false);
+ CHECK_EQ(aligned, v8::External::Unwrap(obj->GetInternalField(0)));
+
+ obj->SetPointerInInternalField(0, unaligned);
+ i::Heap::CollectAllGarbage(false);
+ CHECK_EQ(unaligned, v8::External::Unwrap(obj->GetInternalField(0)));
+
+ obj->SetInternalField(0, v8::External::Wrap(aligned));
+ i::Heap::CollectAllGarbage(false);
+ CHECK_EQ(aligned, obj->GetPointerFromInternalField(0));
+
+ obj->SetInternalField(0, v8::External::Wrap(unaligned));
+ i::Heap::CollectAllGarbage(false);
+ CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0));
+
+ delete[] data;
+}
+
+
THREADED_TEST(IdentityHash) {
v8::HandleScope scope;
LocalContext env;
@@ -1810,7 +1966,7 @@ TEST(HugeConsStringOutOfMemory) {
// Build huge string. This should fail with out of memory exception.
Local<Value> result = CompileRun(
"var str = Array.prototype.join.call({length: 513}, \"A\").toUpperCase();"
- "for (var i = 0; i < 21; i++) { str = str + str; }");
+ "for (var i = 0; i < 22; i++) { str = str + str; }");
// Check for out of memory state.
CHECK(result.IsEmpty());
diff --git a/deps/v8/test/cctest/test-assembler-x64.cc b/deps/v8/test/cctest/test-assembler-x64.cc
index cd750c5dfa..81aa973db4 100644
--- a/deps/v8/test/cctest/test-assembler-x64.cc
+++ b/deps/v8/test/cctest/test-assembler-x64.cc
@@ -44,6 +44,7 @@ using v8::internal::Label;
using v8::internal::rax;
using v8::internal::rsi;
using v8::internal::rdi;
+using v8::internal::rcx;
using v8::internal::rdx;
using v8::internal::rbp;
using v8::internal::rsp;
@@ -53,20 +54,28 @@ using v8::internal::less_equal;
using v8::internal::not_equal;
using v8::internal::greater;
-
// Test the x64 assembler by compiling some simple functions into
// a buffer and executing them. These tests do not initialize the
// V8 library, create a context, or use any V8 objects.
-// The AMD64 calling convention is used, with the first five arguments
-// in RSI, RDI, RDX, RCX, R8, and R9, and floating point arguments in
+// The AMD64 calling convention is used, with the first six arguments
+// in RDI, RSI, RDX, RCX, R8, and R9, and floating point arguments in
// the XMM registers. The return value is in RAX.
// This calling convention is used on Linux, with GCC, and on Mac OS,
-// with GCC. A different convention is used on 64-bit windows.
+// with GCC. A different convention is used on 64-bit windows,
+// where the first four integer arguments are passed in RCX, RDX, R8 and R9.
typedef int (*F0)();
typedef int (*F1)(int64_t x);
typedef int (*F2)(int64_t x, int64_t y);
+#ifdef _WIN64
+static const v8::internal::Register arg1 = rcx;
+static const v8::internal::Register arg2 = rdx;
+#else
+static const v8::internal::Register arg1 = rdi;
+static const v8::internal::Register arg2 = rsi;
+#endif
+
#define __ assm.
@@ -80,7 +89,7 @@ TEST(AssemblerX64ReturnOperation) {
Assembler assm(buffer, actual_size);
// Assemble a simple function that copies argument 2 and returns it.
- __ movq(rax, rsi);
+ __ movq(rax, arg2);
__ nop();
__ ret(0);
@@ -105,9 +114,9 @@ TEST(AssemblerX64StackOperations) {
// incorrect stack frames when debugging this function (which has them).
__ push(rbp);
__ movq(rbp, rsp);
- __ push(rsi); // Value at (rbp - 8)
- __ push(rsi); // Value at (rbp - 16)
- __ push(rdi); // Value at (rbp - 24)
+ __ push(arg2); // Value at (rbp - 8)
+ __ push(arg2); // Value at (rbp - 16)
+ __ push(arg1); // Value at (rbp - 24)
__ pop(rax);
__ pop(rax);
__ pop(rax);
@@ -132,8 +141,8 @@ TEST(AssemblerX64ArithmeticOperations) {
Assembler assm(buffer, actual_size);
// Assemble a simple function that adds arguments returning the sum.
- __ movq(rax, rsi);
- __ addq(rax, rdi);
+ __ movq(rax, arg2);
+ __ addq(rax, arg1);
__ ret(0);
CodeDesc desc;
@@ -154,8 +163,8 @@ TEST(AssemblerX64ImulOperation) {
// Assemble a simple function that multiplies arguments returning the high
// word.
- __ movq(rax, rsi);
- __ imul(rdi);
+ __ movq(rax, arg2);
+ __ imul(arg1);
__ movq(rax, rdx);
__ ret(0);
@@ -182,14 +191,16 @@ TEST(AssemblerX64MemoryOperands) {
// Assemble a simple function that copies argument 2 and returns it.
__ push(rbp);
__ movq(rbp, rsp);
- __ push(rsi); // Value at (rbp - 8)
- __ push(rsi); // Value at (rbp - 16)
- __ push(rdi); // Value at (rbp - 24)
+
+ __ push(arg2); // Value at (rbp - 8)
+ __ push(arg2); // Value at (rbp - 16)
+ __ push(arg1); // Value at (rbp - 24)
+
const int kStackElementSize = 8;
__ movq(rax, Operand(rbp, -3 * kStackElementSize));
- __ pop(rsi);
- __ pop(rsi);
- __ pop(rsi);
+ __ pop(arg2);
+ __ pop(arg2);
+ __ pop(arg2);
__ pop(rbp);
__ nop();
__ ret(0);
@@ -210,13 +221,14 @@ TEST(AssemblerX64ControlFlow) {
CHECK(buffer);
Assembler assm(buffer, actual_size);
- // Assemble a simple function that copies argument 2 and returns it.
+ // Assemble a simple function that copies argument 1 and returns it.
__ push(rbp);
+
__ movq(rbp, rsp);
- __ movq(rax, rdi);
+ __ movq(rax, arg1);
Label target;
__ jmp(&target);
- __ movq(rax, rsi);
+ __ movq(rax, arg2);
__ bind(&target);
__ pop(rbp);
__ ret(0);
diff --git a/deps/v8/test/cctest/test-debug.cc b/deps/v8/test/cctest/test-debug.cc
index 1da363c2ae..4ffcee3dbf 100644
--- a/deps/v8/test/cctest/test-debug.cc
+++ b/deps/v8/test/cctest/test-debug.cc
@@ -3539,6 +3539,52 @@ bool IsBreakEventMessage(char *message) {
}
+// We match parts of the message to decide if it is a exception message.
+bool IsExceptionEventMessage(char *message) {
+ const char* type_event = "\"type\":\"event\"";
+ const char* event_exception = "\"event\":\"exception\"";
+ // Does the message contain both type:event and event:exception?
+ return strstr(message, type_event) != NULL &&
+ strstr(message, event_exception) != NULL;
+}
+
+
+// We match the message wether it is an evaluate response message.
+bool IsEvaluateResponseMessage(char* message) {
+ const char* type_response = "\"type\":\"response\"";
+ const char* command_evaluate = "\"command\":\"evaluate\"";
+ // Does the message contain both type:response and command:evaluate?
+ return strstr(message, type_response) != NULL &&
+ strstr(message, command_evaluate) != NULL;
+}
+
+
+// We match parts of the message to get evaluate result int value.
+int GetEvaluateIntResult(char *message) {
+ const char* value = "\"value\":";
+ char* pos = strstr(message, value);
+ if (pos == NULL) {
+ return -1;
+ }
+ int res = -1;
+ res = atoi(pos + strlen(value));
+ return res;
+}
+
+
+// We match parts of the message to get hit breakpoint id.
+int GetBreakpointIdFromBreakEventMessage(char *message) {
+ const char* breakpoints = "\"breakpoints\":[";
+ char* pos = strstr(message, breakpoints);
+ if (pos == NULL) {
+ return -1;
+ }
+ int res = -1;
+ res = atoi(pos + strlen(breakpoints));
+ return res;
+}
+
+
/* Test MessageQueues */
/* Tests the message queues that hold debugger commands and
* response messages to the debugger. Fills queues and makes
@@ -3566,8 +3612,6 @@ static void MessageHandler(const uint16_t* message, int length,
// Allow message handler to block on a semaphore, to test queueing of
// messages while blocked.
message_queue_barriers.semaphore_1->Wait();
- printf("%s\n", print_buffer);
- fflush(stdout);
}
void MessageQueueDebuggerThread::Run() {
@@ -3822,8 +3866,6 @@ static void ThreadedMessageHandler(const v8::Debug::Message& message) {
if (IsBreakEventMessage(print_buffer)) {
threaded_debugging_barriers.barrier_2.Wait();
}
- printf("%s\n", print_buffer);
- fflush(stdout);
}
@@ -3911,16 +3953,20 @@ class BreakpointsDebuggerThread : public v8::internal::Thread {
Barriers* breakpoints_barriers;
+int break_event_breakpoint_id;
+int evaluate_int_result;
static void BreakpointsMessageHandler(const v8::Debug::Message& message) {
static char print_buffer[1000];
v8::String::Value json(message.GetJSON());
Utf16ToAscii(*json, json.length(), print_buffer);
- printf("%s\n", print_buffer);
- fflush(stdout);
- // Is break_template a prefix of the message?
if (IsBreakEventMessage(print_buffer)) {
+ break_event_breakpoint_id =
+ GetBreakpointIdFromBreakEventMessage(print_buffer);
+ breakpoints_barriers->semaphore_1->Signal();
+ } else if (IsEvaluateResponseMessage(print_buffer)) {
+ evaluate_int_result = GetEvaluateIntResult(print_buffer);
breakpoints_barriers->semaphore_1->Signal();
}
}
@@ -3930,9 +3976,9 @@ void BreakpointsV8Thread::Run() {
const char* source_1 = "var y_global = 3;\n"
"function cat( new_value ) {\n"
" var x = new_value;\n"
- " y_global = 4;\n"
+ " y_global = y_global + 4;\n"
" x = 3 * x + 1;\n"
- " y_global = 5;\n"
+ " y_global = y_global + 5;\n"
" return x;\n"
"}\n"
"\n"
@@ -3970,59 +4016,76 @@ void BreakpointsDebuggerThread::Run() {
"\"type\":\"request\","
"\"command\":\"setbreakpoint\","
"\"arguments\":{\"type\":\"function\",\"target\":\"dog\",\"line\":3}}";
- const char* command_3 = "{\"seq\":104,"
+ const char* command_3 = "{\"seq\":103,"
"\"type\":\"request\","
"\"command\":\"evaluate\","
"\"arguments\":{\"expression\":\"dog()\",\"disable_break\":false}}";
- const char* command_4 = "{\"seq\":105,"
+ const char* command_4 = "{\"seq\":104,"
"\"type\":\"request\","
"\"command\":\"evaluate\","
- "\"arguments\":{\"expression\":\"x\",\"disable_break\":true}}";
- const char* command_5 = "{\"seq\":106,"
+ "\"arguments\":{\"expression\":\"x + 1\",\"disable_break\":true}}";
+ const char* command_5 = "{\"seq\":105,"
"\"type\":\"request\","
"\"command\":\"continue\"}";
- const char* command_6 = "{\"seq\":107,"
+ const char* command_6 = "{\"seq\":106,"
"\"type\":\"request\","
"\"command\":\"continue\"}";
- const char* command_7 = "{\"seq\":108,"
+ const char* command_7 = "{\"seq\":107,"
"\"type\":\"request\","
"\"command\":\"evaluate\","
"\"arguments\":{\"expression\":\"dog()\",\"disable_break\":true}}";
- const char* command_8 = "{\"seq\":109,"
+ const char* command_8 = "{\"seq\":108,"
"\"type\":\"request\","
"\"command\":\"continue\"}";
// v8 thread initializes, runs source_1
breakpoints_barriers->barrier_1.Wait();
- // 1:Set breakpoint in cat().
+ // 1:Set breakpoint in cat() (will get id 1).
v8::Debug::SendCommand(buffer, AsciiToUtf16(command_1, buffer));
- // 2:Set breakpoint in dog()
+ // 2:Set breakpoint in dog() (will get id 2).
v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer));
breakpoints_barriers->barrier_2.Wait();
- // v8 thread starts compiling source_2.
+ // V8 thread starts compiling source_2.
// Automatic break happens, to run queued commands
// breakpoints_barriers->semaphore_1->Wait();
// Commands 1 through 3 run, thread continues.
// v8 thread runs source_2 to breakpoint in cat().
// message callback receives break event.
breakpoints_barriers->semaphore_1->Wait();
+ // Must have hit breakpoint #1.
+ CHECK_EQ(1, break_event_breakpoint_id);
// 4:Evaluate dog() (which has a breakpoint).
v8::Debug::SendCommand(buffer, AsciiToUtf16(command_3, buffer));
- // v8 thread hits breakpoint in dog()
+ // V8 thread hits breakpoint in dog().
breakpoints_barriers->semaphore_1->Wait(); // wait for break event
- // 5:Evaluate x
+ // Must have hit breakpoint #2.
+ CHECK_EQ(2, break_event_breakpoint_id);
+ // 5:Evaluate (x + 1).
v8::Debug::SendCommand(buffer, AsciiToUtf16(command_4, buffer));
- // 6:Continue evaluation of dog()
+ // Evaluate (x + 1) finishes.
+ breakpoints_barriers->semaphore_1->Wait();
+ // Must have result 108.
+ CHECK_EQ(108, evaluate_int_result);
+ // 6:Continue evaluation of dog().
v8::Debug::SendCommand(buffer, AsciiToUtf16(command_5, buffer));
- // dog() finishes.
+ // Evaluate dog() finishes.
+ breakpoints_barriers->semaphore_1->Wait();
+ // Must have result 107.
+ CHECK_EQ(107, evaluate_int_result);
// 7:Continue evaluation of source_2, finish cat(17), hit breakpoint
// in cat(19).
v8::Debug::SendCommand(buffer, AsciiToUtf16(command_6, buffer));
- // message callback gets break event
+ // Message callback gets break event.
breakpoints_barriers->semaphore_1->Wait(); // wait for break event
- // 8: Evaluate dog() with breaks disabled
+ // Must have hit breakpoint #1.
+ CHECK_EQ(1, break_event_breakpoint_id);
+ // 8: Evaluate dog() with breaks disabled.
v8::Debug::SendCommand(buffer, AsciiToUtf16(command_7, buffer));
+ // Evaluate dog() finishes.
+ breakpoints_barriers->semaphore_1->Wait();
+ // Must have result 116.
+ CHECK_EQ(116, evaluate_int_result);
// 9: Continue evaluation of source2, reach end.
v8::Debug::SendCommand(buffer, AsciiToUtf16(command_8, buffer));
}
@@ -4325,7 +4388,13 @@ static int message_handler_hit_count = 0;
static void MessageHandlerHitCount(const v8::Debug::Message& message) {
message_handler_hit_count++;
- SendContinueCommand();
+ static char print_buffer[1000];
+ v8::String::Value json(message.GetJSON());
+ Utf16ToAscii(*json, json.length(), print_buffer);
+ if (IsExceptionEventMessage(print_buffer)) {
+ // Send a continue command for exception events.
+ SendContinueCommand();
+ }
}
@@ -4415,8 +4484,6 @@ static void HostDispatchMessageHandler(const v8::Debug::Message& message) {
static char print_buffer[1000];
v8::String::Value json(message.GetJSON());
Utf16ToAscii(*json, json.length(), print_buffer);
- printf("%s\n", print_buffer);
- fflush(stdout);
}
@@ -4776,8 +4843,12 @@ static void ContextCheckMessageHandler(const v8::Debug::Message& message) {
expected_context_data));
message_handler_hit_count++;
+ static char print_buffer[1000];
+ v8::String::Value json(message.GetJSON());
+ Utf16ToAscii(*json, json.length(), print_buffer);
+
// Send a continue command for break events.
- if (message.GetEvent() == v8::Break) {
+ if (IsBreakEventMessage(print_buffer)) {
SendContinueCommand();
}
}
@@ -5016,7 +5087,11 @@ static void DebugEvalContextCheckMessageHandler(
expected_context_data));
message_handler_hit_count++;
- if (message.IsEvent() && message.GetEvent() == v8::Break) {
+ static char print_buffer[1000];
+ v8::String::Value json(message.GetJSON());
+ Utf16ToAscii(*json, json.length(), print_buffer);
+
+ if (IsBreakEventMessage(print_buffer)) {
break_count++;
if (!sent_eval) {
sent_eval = true;
@@ -5038,7 +5113,8 @@ static void DebugEvalContextCheckMessageHandler(
SendContinueCommand();
continue_command_send_count++;
}
- } else if (message.IsResponse() && continue_command_send_count < 2) {
+ } else if (IsEvaluateResponseMessage(print_buffer) &&
+ continue_command_send_count < 2) {
// Response to the evaluation request. We're still on the breakpoint so
// send continue.
SendContinueCommand();
diff --git a/deps/v8/test/cctest/test-disasm-ia32.cc b/deps/v8/test/cctest/test-disasm-ia32.cc
index af9fb97e5b..74db23463a 100644
--- a/deps/v8/test/cctest/test-disasm-ia32.cc
+++ b/deps/v8/test/cctest/test-disasm-ia32.cc
@@ -363,7 +363,31 @@ TEST(DisasmIa320) {
__ divsd(xmm1, xmm0);
__ movdbl(xmm1, Operand(ebx, ecx, times_4, 10000));
__ movdbl(Operand(ebx, ecx, times_4, 10000), xmm1);
+ __ comisd(xmm0, xmm1);
}
+
+ // cmov.
+ {
+ CHECK(CpuFeatures::IsSupported(CpuFeatures::CMOV));
+ CpuFeatures::Scope use_cmov(CpuFeatures::CMOV);
+ __ cmov(overflow, eax, Operand(eax, 0));
+ __ cmov(no_overflow, eax, Operand(eax, 1));
+ __ cmov(below, eax, Operand(eax, 2));
+ __ cmov(above_equal, eax, Operand(eax, 3));
+ __ cmov(equal, eax, Operand(ebx, 0));
+ __ cmov(not_equal, eax, Operand(ebx, 1));
+ __ cmov(below_equal, eax, Operand(ebx, 2));
+ __ cmov(above, eax, Operand(ebx, 3));
+ __ cmov(sign, eax, Operand(ecx, 0));
+ __ cmov(not_sign, eax, Operand(ecx, 1));
+ __ cmov(parity_even, eax, Operand(ecx, 2));
+ __ cmov(parity_odd, eax, Operand(ecx, 3));
+ __ cmov(less, eax, Operand(edx, 0));
+ __ cmov(greater_equal, eax, Operand(edx, 1));
+ __ cmov(less_equal, eax, Operand(edx, 2));
+ __ cmov(greater, eax, Operand(edx, 3));
+ }
+
__ ret(0);
CodeDesc desc;
diff --git a/deps/v8/test/cctest/test-heap.cc b/deps/v8/test/cctest/test-heap.cc
index eb32b6539e..9911ce42bc 100644
--- a/deps/v8/test/cctest/test-heap.cc
+++ b/deps/v8/test/cctest/test-heap.cc
@@ -132,15 +132,19 @@ TEST(HeapObjects) {
CHECK(value->IsNumber());
CHECK_EQ(Smi::kMaxValue, Smi::cast(value)->value());
+#ifndef V8_TARGET_ARCH_X64
+ // TODO(lrn): We need a NumberFromIntptr function in order to test this.
value = Heap::NumberFromInt32(Smi::kMinValue - 1);
CHECK(value->IsHeapNumber());
CHECK(value->IsNumber());
CHECK_EQ(static_cast<double>(Smi::kMinValue - 1), value->Number());
+#endif
- value = Heap::NumberFromInt32(Smi::kMaxValue + 1);
+ value = Heap::NumberFromUint32(static_cast<uint32_t>(Smi::kMaxValue) + 1);
CHECK(value->IsHeapNumber());
CHECK(value->IsNumber());
- CHECK_EQ(static_cast<double>(Smi::kMaxValue + 1), value->Number());
+ CHECK_EQ(static_cast<double>(static_cast<uint32_t>(Smi::kMaxValue) + 1),
+ value->Number());
// nan oddball checks
CHECK(Heap::nan_value()->IsNumber());
@@ -640,8 +644,9 @@ TEST(JSArray) {
CHECK_EQ(Smi::FromInt(1), array->length());
CHECK_EQ(array->GetElement(0), name);
- // Set array length with larger than smi value.
- Object* length = Heap::NumberFromInt32(Smi::kMaxValue + 1);
+// Set array length with larger than smi value.
+ Object* length =
+ Heap::NumberFromUint32(static_cast<uint32_t>(Smi::kMaxValue) + 1);
array->SetElementsLength(length);
uint32_t int_length = 0;
diff --git a/deps/v8/test/cctest/test-macro-assembler-x64.cc b/deps/v8/test/cctest/test-macro-assembler-x64.cc
new file mode 100755
index 0000000000..9c1197ffd8
--- /dev/null
+++ b/deps/v8/test/cctest/test-macro-assembler-x64.cc
@@ -0,0 +1,2096 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "macro-assembler.h"
+#include "factory.h"
+#include "platform.h"
+#include "serialize.h"
+#include "cctest.h"
+
+using v8::internal::byte;
+using v8::internal::OS;
+using v8::internal::Assembler;
+using v8::internal::Condition;
+using v8::internal::MacroAssembler;
+using v8::internal::HandleScope;
+using v8::internal::Operand;
+using v8::internal::Immediate;
+using v8::internal::SmiIndex;
+using v8::internal::Label;
+using v8::internal::RelocInfo;
+using v8::internal::rax;
+using v8::internal::rbx;
+using v8::internal::rsi;
+using v8::internal::rdi;
+using v8::internal::rcx;
+using v8::internal::rdx;
+using v8::internal::rbp;
+using v8::internal::rsp;
+using v8::internal::r8;
+using v8::internal::r9;
+using v8::internal::r11;
+using v8::internal::r12;
+using v8::internal::r13;
+using v8::internal::r14;
+using v8::internal::r15;
+using v8::internal::FUNCTION_CAST;
+using v8::internal::CodeDesc;
+using v8::internal::less_equal;
+using v8::internal::not_equal;
+using v8::internal::not_zero;
+using v8::internal::greater;
+using v8::internal::greater_equal;
+using v8::internal::carry;
+using v8::internal::not_carry;
+using v8::internal::negative;
+using v8::internal::positive;
+using v8::internal::Smi;
+using v8::internal::kSmiTagMask;
+using v8::internal::kSmiValueSize;
+
+// Test the x64 assembler by compiling some simple functions into
+// a buffer and executing them. These tests do not initialize the
+// V8 library, create a context, or use any V8 objects.
+// The AMD64 calling convention is used, with the first five arguments
+// in RSI, RDI, RDX, RCX, R8, and R9, and floating point arguments in
+// the XMM registers. The return value is in RAX.
+// This calling convention is used on Linux, with GCC, and on Mac OS,
+// with GCC. A different convention is used on 64-bit windows.
+
+typedef int (*F0)();
+
+#define __ masm->
+
+TEST(Smi) {
+ // Check that C++ Smi operations work as expected.
+ intptr_t test_numbers[] = {
+ 0, 1, -1, 127, 128, -128, -129, 255, 256, -256, -257,
+ Smi::kMaxValue, static_cast<intptr_t>(Smi::kMaxValue) + 1,
+ Smi::kMinValue, static_cast<intptr_t>(Smi::kMinValue) - 1
+ };
+ int test_number_count = 15;
+ for (int i = 0; i < test_number_count; i++) {
+ intptr_t number = test_numbers[i];
+ bool is_valid = Smi::IsValid(number);
+ bool is_in_range = number >= Smi::kMinValue && number <= Smi::kMaxValue;
+ CHECK_EQ(is_in_range, is_valid);
+ if (is_valid) {
+ Smi* smi_from_intptr = Smi::FromIntptr(number);
+ if (static_cast<int>(number) == number) { // Is a 32-bit int.
+ Smi* smi_from_int = Smi::FromInt(static_cast<int32_t>(number));
+ CHECK_EQ(smi_from_int, smi_from_intptr);
+ }
+ int smi_value = smi_from_intptr->value();
+ CHECK_EQ(number, static_cast<intptr_t>(smi_value));
+ }
+ }
+}
+
+
+static void TestMoveSmi(MacroAssembler* masm, Label* exit, int id, Smi* value) {
+ __ movl(rax, Immediate(id));
+ __ Move(rcx, Smi::FromInt(0));
+ __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
+ __ cmpq(rcx, rdx);
+ __ j(not_equal, exit);
+}
+
+
+// Test that we can move a Smi value literally into a register.
+TEST(SmiMove) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+ MacroAssembler* masm = &assembler; // Create a pointer for the __ macro.
+ masm->set_allow_stub_calls(false);
+ Label exit;
+
+ TestMoveSmi(masm, &exit, 1, Smi::FromInt(0));
+ TestMoveSmi(masm, &exit, 2, Smi::FromInt(127));
+ TestMoveSmi(masm, &exit, 3, Smi::FromInt(128));
+ TestMoveSmi(masm, &exit, 4, Smi::FromInt(255));
+ TestMoveSmi(masm, &exit, 5, Smi::FromInt(256));
+ TestMoveSmi(masm, &exit, 6, Smi::FromInt(Smi::kMaxValue));
+ TestMoveSmi(masm, &exit, 7, Smi::FromInt(-1));
+ TestMoveSmi(masm, &exit, 8, Smi::FromInt(-128));
+ TestMoveSmi(masm, &exit, 9, Smi::FromInt(-129));
+ TestMoveSmi(masm, &exit, 10, Smi::FromInt(-256));
+ TestMoveSmi(masm, &exit, 11, Smi::FromInt(-257));
+ TestMoveSmi(masm, &exit, 12, Smi::FromInt(Smi::kMinValue));
+
+ __ xor_(rax, rax); // Success.
+ __ bind(&exit);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+void TestSmiCompare(MacroAssembler* masm, Label* exit, int id, int x, int y) {
+ __ Move(rcx, Smi::FromInt(x));
+ __ movq(r8, rcx);
+ __ Move(rdx, Smi::FromInt(y));
+ __ movq(r9, rdx);
+ __ SmiCompare(rcx, rdx);
+ if (x < y) {
+ __ movl(rax, Immediate(id + 1));
+ __ j(greater_equal, exit);
+ } else if (x > y) {
+ __ movl(rax, Immediate(id + 2));
+ __ j(less_equal, exit);
+ } else {
+ ASSERT_EQ(x, y);
+ __ movl(rax, Immediate(id + 3));
+ __ j(not_equal, exit);
+ }
+ __ movl(rax, Immediate(id + 4));
+ __ cmpq(rcx, r8);
+ __ j(not_equal, exit);
+ __ incq(rax);
+ __ cmpq(rdx, r9);
+ __ j(not_equal, exit);
+
+ if (x != y) {
+ __ SmiCompare(rdx, rcx);
+ if (y < x) {
+ __ movl(rax, Immediate(id + 9));
+ __ j(greater_equal, exit);
+ } else {
+ ASSERT(y > x);
+ __ movl(rax, Immediate(id + 10));
+ __ j(less_equal, exit);
+ }
+ } else {
+ __ SmiCompare(rcx, rcx);
+ __ movl(rax, Immediate(id + 11));
+ __ j(not_equal, exit);
+ __ incq(rax);
+ __ cmpq(rcx, r8);
+ __ j(not_equal, exit);
+ }
+}
+
+
+// Test that we can compare smis for equality (and more).
+TEST(SmiCompare) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer =
+ static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+
+ MacroAssembler* masm = &assembler;
+ masm->set_allow_stub_calls(false);
+ Label exit;
+
+ TestSmiCompare(masm, &exit, 0x10, 0, 0);
+ TestSmiCompare(masm, &exit, 0x20, 0, 1);
+ TestSmiCompare(masm, &exit, 0x30, 1, 0);
+ TestSmiCompare(masm, &exit, 0x40, 1, 1);
+ TestSmiCompare(masm, &exit, 0x50, 0, -1);
+ TestSmiCompare(masm, &exit, 0x60, -1, 0);
+ TestSmiCompare(masm, &exit, 0x70, -1, -1);
+ TestSmiCompare(masm, &exit, 0x80, 0, Smi::kMinValue);
+ TestSmiCompare(masm, &exit, 0x90, Smi::kMinValue, 0);
+ TestSmiCompare(masm, &exit, 0xA0, 0, Smi::kMaxValue);
+ TestSmiCompare(masm, &exit, 0xB0, Smi::kMaxValue, 0);
+ TestSmiCompare(masm, &exit, 0xC0, -1, Smi::kMinValue);
+ TestSmiCompare(masm, &exit, 0xD0, Smi::kMinValue, -1);
+ TestSmiCompare(masm, &exit, 0xE0, -1, Smi::kMaxValue);
+ TestSmiCompare(masm, &exit, 0xF0, Smi::kMaxValue, -1);
+ TestSmiCompare(masm, &exit, 0x100, Smi::kMinValue, Smi::kMinValue);
+ TestSmiCompare(masm, &exit, 0x110, Smi::kMinValue, Smi::kMaxValue);
+ TestSmiCompare(masm, &exit, 0x120, Smi::kMaxValue, Smi::kMinValue);
+ TestSmiCompare(masm, &exit, 0x130, Smi::kMaxValue, Smi::kMaxValue);
+
+ __ xor_(rax, rax); // Success.
+ __ bind(&exit);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+
+TEST(Integer32ToSmi) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+
+ MacroAssembler* masm = &assembler;
+ masm->set_allow_stub_calls(false);
+ Label exit;
+
+ __ movq(rax, Immediate(1)); // Test number.
+ __ movl(rcx, Immediate(0));
+ __ Integer32ToSmi(rcx, rcx);
+ __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
+ __ SmiCompare(rcx, rdx);
+ __ j(not_equal, &exit);
+
+ __ movq(rax, Immediate(2)); // Test number.
+ __ movl(rcx, Immediate(1024));
+ __ Integer32ToSmi(rcx, rcx);
+ __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(1024)));
+ __ SmiCompare(rcx, rdx);
+ __ j(not_equal, &exit);
+
+ __ movq(rax, Immediate(3)); // Test number.
+ __ movl(rcx, Immediate(-1));
+ __ Integer32ToSmi(rcx, rcx);
+ __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(-1)));
+ __ SmiCompare(rcx, rdx);
+ __ j(not_equal, &exit);
+
+ __ movq(rax, Immediate(4)); // Test number.
+ __ movl(rcx, Immediate(Smi::kMaxValue));
+ __ Integer32ToSmi(rcx, rcx);
+ __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMaxValue)));
+ __ SmiCompare(rcx, rdx);
+ __ j(not_equal, &exit);
+
+ __ movq(rax, Immediate(5)); // Test number.
+ __ movl(rcx, Immediate(Smi::kMinValue));
+ __ Integer32ToSmi(rcx, rcx);
+ __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMinValue)));
+ __ SmiCompare(rcx, rdx);
+ __ j(not_equal, &exit);
+
+ // Different target register.
+
+ __ movq(rax, Immediate(6)); // Test number.
+ __ movl(rcx, Immediate(0));
+ __ Integer32ToSmi(r8, rcx);
+ __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
+ __ SmiCompare(r8, rdx);
+ __ j(not_equal, &exit);
+
+ __ movq(rax, Immediate(7)); // Test number.
+ __ movl(rcx, Immediate(1024));
+ __ Integer32ToSmi(r8, rcx);
+ __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(1024)));
+ __ SmiCompare(r8, rdx);
+ __ j(not_equal, &exit);
+
+ __ movq(rax, Immediate(8)); // Test number.
+ __ movl(rcx, Immediate(-1));
+ __ Integer32ToSmi(r8, rcx);
+ __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(-1)));
+ __ SmiCompare(r8, rdx);
+ __ j(not_equal, &exit);
+
+ __ movq(rax, Immediate(9)); // Test number.
+ __ movl(rcx, Immediate(Smi::kMaxValue));
+ __ Integer32ToSmi(r8, rcx);
+ __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMaxValue)));
+ __ SmiCompare(r8, rdx);
+ __ j(not_equal, &exit);
+
+ __ movq(rax, Immediate(10)); // Test number.
+ __ movl(rcx, Immediate(Smi::kMinValue));
+ __ Integer32ToSmi(r8, rcx);
+ __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMinValue)));
+ __ SmiCompare(r8, rdx);
+ __ j(not_equal, &exit);
+
+
+ __ xor_(rax, rax); // Success.
+ __ bind(&exit);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+void TestI64PlusConstantToSmi(MacroAssembler* masm,
+ Label* exit,
+ int id,
+ int64_t x,
+ int y) {
+ int64_t result = x + y;
+ ASSERT(Smi::IsValid(result));
+ __ movl(rax, Immediate(id));
+ __ Move(r8, Smi::FromInt(result));
+ __ movq(rcx, x, RelocInfo::NONE);
+ __ movq(r11, rcx);
+ __ Integer64PlusConstantToSmi(rdx, rcx, y);
+ __ SmiCompare(rdx, r8);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiCompare(r11, rcx);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ Integer64PlusConstantToSmi(rcx, rcx, y);
+ __ SmiCompare(rcx, r8);
+ __ j(not_equal, exit);
+}
+
+
+TEST(Integer64PlusConstantToSmi) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+
+ MacroAssembler* masm = &assembler;
+ masm->set_allow_stub_calls(false);
+ Label exit;
+
+ int64_t twice_max = static_cast<int64_t>(Smi::kMaxValue) * 2;
+
+ TestI64PlusConstantToSmi(masm, &exit, 0x10, 0, 0);
+ TestI64PlusConstantToSmi(masm, &exit, 0x20, 0, 1);
+ TestI64PlusConstantToSmi(masm, &exit, 0x30, 1, 0);
+ TestI64PlusConstantToSmi(masm, &exit, 0x40, Smi::kMaxValue - 5, 5);
+ TestI64PlusConstantToSmi(masm, &exit, 0x50, Smi::kMinValue + 5, 5);
+ TestI64PlusConstantToSmi(masm, &exit, 0x60, twice_max, -Smi::kMaxValue);
+ TestI64PlusConstantToSmi(masm, &exit, 0x70, -twice_max, Smi::kMaxValue);
+ TestI64PlusConstantToSmi(masm, &exit, 0x80, 0, Smi::kMinValue);
+ TestI64PlusConstantToSmi(masm, &exit, 0x90, 0, Smi::kMaxValue);
+ TestI64PlusConstantToSmi(masm, &exit, 0xA0, Smi::kMinValue, 0);
+ TestI64PlusConstantToSmi(masm, &exit, 0xB0, Smi::kMaxValue, 0);
+ TestI64PlusConstantToSmi(masm, &exit, 0xC0, twice_max, Smi::kMinValue);
+
+ __ xor_(rax, rax); // Success.
+ __ bind(&exit);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+TEST(SmiCheck) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+
+ MacroAssembler* masm = &assembler;
+ masm->set_allow_stub_calls(false);
+ Label exit;
+ Condition cond;
+
+ __ movl(rax, Immediate(1)); // Test number.
+
+ // CheckSmi
+
+ __ movl(rcx, Immediate(0));
+ __ Integer32ToSmi(rcx, rcx);
+ cond = masm->CheckSmi(rcx);
+ __ j(NegateCondition(cond), &exit);
+
+ __ incq(rax);
+ __ xor_(rcx, Immediate(kSmiTagMask));
+ cond = masm->CheckSmi(rcx);
+ __ j(cond, &exit);
+
+ __ incq(rax);
+ __ movl(rcx, Immediate(-1));
+ __ Integer32ToSmi(rcx, rcx);
+ cond = masm->CheckSmi(rcx);
+ __ j(NegateCondition(cond), &exit);
+
+ __ incq(rax);
+ __ xor_(rcx, Immediate(kSmiTagMask));
+ cond = masm->CheckSmi(rcx);
+ __ j(cond, &exit);
+
+ __ incq(rax);
+ __ movl(rcx, Immediate(Smi::kMaxValue));
+ __ Integer32ToSmi(rcx, rcx);
+ cond = masm->CheckSmi(rcx);
+ __ j(NegateCondition(cond), &exit);
+
+ __ incq(rax);
+ __ xor_(rcx, Immediate(kSmiTagMask));
+ cond = masm->CheckSmi(rcx);
+ __ j(cond, &exit);
+
+ __ incq(rax);
+ __ movl(rcx, Immediate(Smi::kMinValue));
+ __ Integer32ToSmi(rcx, rcx);
+ cond = masm->CheckSmi(rcx);
+ __ j(NegateCondition(cond), &exit);
+
+ __ incq(rax);
+ __ xor_(rcx, Immediate(kSmiTagMask));
+ cond = masm->CheckSmi(rcx);
+ __ j(cond, &exit);
+
+ // CheckPositiveSmi
+
+ __ incq(rax);
+ __ movl(rcx, Immediate(0));
+ __ Integer32ToSmi(rcx, rcx);
+ cond = masm->CheckPositiveSmi(rcx); // Zero counts as positive.
+ __ j(NegateCondition(cond), &exit);
+
+ __ incq(rax);
+ __ xor_(rcx, Immediate(kSmiTagMask));
+ cond = masm->CheckPositiveSmi(rcx); // "zero" non-smi.
+ __ j(cond, &exit);
+
+ __ incq(rax);
+ __ movq(rcx, Immediate(-1));
+ __ Integer32ToSmi(rcx, rcx);
+ cond = masm->CheckPositiveSmi(rcx); // Negative smis are not positive.
+ __ j(cond, &exit);
+
+ __ incq(rax);
+ __ movq(rcx, Immediate(Smi::kMinValue));
+ __ Integer32ToSmi(rcx, rcx);
+ cond = masm->CheckPositiveSmi(rcx); // Most negative smi is not positive.
+ __ j(cond, &exit);
+
+ __ incq(rax);
+ __ xor_(rcx, Immediate(kSmiTagMask));
+ cond = masm->CheckPositiveSmi(rcx); // "Negative" non-smi.
+ __ j(cond, &exit);
+
+ __ incq(rax);
+ __ movq(rcx, Immediate(Smi::kMaxValue));
+ __ Integer32ToSmi(rcx, rcx);
+ cond = masm->CheckPositiveSmi(rcx); // Most positive smi is positive.
+ __ j(NegateCondition(cond), &exit);
+
+ __ incq(rax);
+ __ xor_(rcx, Immediate(kSmiTagMask));
+ cond = masm->CheckPositiveSmi(rcx); // "Positive" non-smi.
+ __ j(cond, &exit);
+
+ // CheckIsMinSmi
+
+ __ incq(rax);
+ __ movq(rcx, Immediate(Smi::kMaxValue));
+ __ Integer32ToSmi(rcx, rcx);
+ cond = masm->CheckIsMinSmi(rcx);
+ __ j(cond, &exit);
+
+ __ incq(rax);
+ __ movq(rcx, Immediate(0));
+ __ Integer32ToSmi(rcx, rcx);
+ cond = masm->CheckIsMinSmi(rcx);
+ __ j(cond, &exit);
+
+ __ incq(rax);
+ __ movq(rcx, Immediate(Smi::kMinValue));
+ __ Integer32ToSmi(rcx, rcx);
+ cond = masm->CheckIsMinSmi(rcx);
+ __ j(NegateCondition(cond), &exit);
+
+ __ incq(rax);
+ __ movq(rcx, Immediate(Smi::kMinValue + 1));
+ __ Integer32ToSmi(rcx, rcx);
+ cond = masm->CheckIsMinSmi(rcx);
+ __ j(cond, &exit);
+
+ // CheckBothSmi
+
+ __ incq(rax);
+ __ movq(rcx, Immediate(Smi::kMaxValue));
+ __ Integer32ToSmi(rcx, rcx);
+ __ movq(rdx, Immediate(Smi::kMinValue));
+ __ Integer32ToSmi(rdx, rdx);
+ cond = masm->CheckBothSmi(rcx, rdx);
+ __ j(NegateCondition(cond), &exit);
+
+ __ incq(rax);
+ __ xor_(rcx, Immediate(kSmiTagMask));
+ cond = masm->CheckBothSmi(rcx, rdx);
+ __ j(cond, &exit);
+
+ __ incq(rax);
+ __ xor_(rdx, Immediate(kSmiTagMask));
+ cond = masm->CheckBothSmi(rcx, rdx);
+ __ j(cond, &exit);
+
+ __ incq(rax);
+ __ xor_(rcx, Immediate(kSmiTagMask));
+ cond = masm->CheckBothSmi(rcx, rdx);
+ __ j(cond, &exit);
+
+ __ incq(rax);
+ cond = masm->CheckBothSmi(rcx, rcx);
+ __ j(NegateCondition(cond), &exit);
+
+ __ incq(rax);
+ cond = masm->CheckBothSmi(rdx, rdx);
+ __ j(cond, &exit);
+
+ // CheckInteger32ValidSmiValue
+ __ incq(rax);
+ __ movq(rcx, Immediate(0));
+ cond = masm->CheckInteger32ValidSmiValue(rax);
+ __ j(NegateCondition(cond), &exit);
+
+ __ incq(rax);
+ __ movq(rcx, Immediate(-1));
+ cond = masm->CheckInteger32ValidSmiValue(rax);
+ __ j(NegateCondition(cond), &exit);
+
+ __ incq(rax);
+ __ movq(rcx, Immediate(Smi::kMaxValue));
+ cond = masm->CheckInteger32ValidSmiValue(rax);
+ __ j(NegateCondition(cond), &exit);
+
+ __ incq(rax);
+ __ movq(rcx, Immediate(Smi::kMinValue));
+ cond = masm->CheckInteger32ValidSmiValue(rax);
+ __ j(NegateCondition(cond), &exit);
+
+ // Success
+ __ xor_(rax, rax);
+
+ __ bind(&exit);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+
+void TestSmiNeg(MacroAssembler* masm, Label* exit, int id, int x) {
+ __ Move(rcx, Smi::FromInt(x));
+ __ movq(r11, rcx);
+ if (x == Smi::kMinValue || x == 0) {
+ // Negation fails.
+ __ movl(rax, Immediate(id + 8));
+ __ SmiNeg(r9, rcx, exit);
+
+ __ incq(rax);
+ __ SmiCompare(r11, rcx);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiNeg(rcx, rcx, exit);
+
+ __ incq(rax);
+ __ SmiCompare(r11, rcx);
+ __ j(not_equal, exit);
+ } else {
+ Label smi_ok, smi_ok2;
+ int result = -x;
+ __ movl(rax, Immediate(id));
+ __ Move(r8, Smi::FromInt(result));
+
+ __ SmiNeg(r9, rcx, &smi_ok);
+ __ jmp(exit);
+ __ bind(&smi_ok);
+ __ incq(rax);
+ __ SmiCompare(r9, r8);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiCompare(r11, rcx);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiNeg(rcx, rcx, &smi_ok2);
+ __ jmp(exit);
+ __ bind(&smi_ok2);
+ __ incq(rax);
+ __ SmiCompare(rcx, r8);
+ __ j(not_equal, exit);
+ }
+}
+
+
+TEST(SmiNeg) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer =
+ static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+
+ MacroAssembler* masm = &assembler;
+ masm->set_allow_stub_calls(false);
+ Label exit;
+
+ TestSmiNeg(masm, &exit, 0x10, 0);
+ TestSmiNeg(masm, &exit, 0x20, 1);
+ TestSmiNeg(masm, &exit, 0x30, -1);
+ TestSmiNeg(masm, &exit, 0x40, 127);
+ TestSmiNeg(masm, &exit, 0x50, 65535);
+ TestSmiNeg(masm, &exit, 0x60, Smi::kMinValue);
+ TestSmiNeg(masm, &exit, 0x70, Smi::kMaxValue);
+ TestSmiNeg(masm, &exit, 0x80, -Smi::kMaxValue);
+
+ __ xor_(rax, rax); // Success.
+ __ bind(&exit);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+
+
+static void SmiAddTest(MacroAssembler* masm,
+ Label* exit,
+ int id,
+ int first,
+ int second) {
+ __ movl(rcx, Immediate(first));
+ __ Integer32ToSmi(rcx, rcx);
+ __ movl(rdx, Immediate(second));
+ __ Integer32ToSmi(rdx, rdx);
+ __ movl(r8, Immediate(first + second));
+ __ Integer32ToSmi(r8, r8);
+
+ __ movl(rax, Immediate(id)); // Test number.
+ __ SmiAdd(r9, rcx, rdx, exit);
+ __ SmiCompare(r9, r8);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiAdd(rcx, rcx, rdx, exit); \
+ __ SmiCompare(rcx, r8);
+ __ j(not_equal, exit);
+
+ __ movl(rcx, Immediate(first));
+ __ Integer32ToSmi(rcx, rcx);
+
+ __ incq(rax);
+ __ SmiAddConstant(r9, rcx, Smi::FromInt(second));
+ __ SmiCompare(r9, r8);
+ __ j(not_equal, exit);
+
+ __ SmiAddConstant(rcx, rcx, Smi::FromInt(second));
+ __ SmiCompare(rcx, r8);
+ __ j(not_equal, exit);
+
+ __ movl(rcx, Immediate(first));
+ __ Integer32ToSmi(rcx, rcx);
+
+ __ incq(rax);
+ __ SmiAddConstant(r9, rcx, Smi::FromInt(second), exit);
+ __ SmiCompare(r9, r8);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiAddConstant(rcx, rcx, Smi::FromInt(second), exit);
+ __ SmiCompare(rcx, r8);
+ __ j(not_equal, exit);
+}
+
+TEST(SmiAdd) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+
+ MacroAssembler* masm = &assembler;
+ masm->set_allow_stub_calls(false);
+ Label exit;
+
+ // No-overflow tests.
+ SmiAddTest(masm, &exit, 0x10, 1, 2);
+ SmiAddTest(masm, &exit, 0x20, 1, -2);
+ SmiAddTest(masm, &exit, 0x30, -1, 2);
+ SmiAddTest(masm, &exit, 0x40, -1, -2);
+ SmiAddTest(masm, &exit, 0x50, 0x1000, 0x2000);
+ SmiAddTest(masm, &exit, 0x60, Smi::kMinValue, 5);
+ SmiAddTest(masm, &exit, 0x70, Smi::kMaxValue, -5);
+ SmiAddTest(masm, &exit, 0x80, Smi::kMaxValue, Smi::kMinValue);
+
+ __ xor_(rax, rax); // Success.
+ __ bind(&exit);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+static void SmiSubTest(MacroAssembler* masm,
+ Label* exit,
+ int id,
+ int first,
+ int second) {
+ __ Move(rcx, Smi::FromInt(first));
+ __ Move(rdx, Smi::FromInt(second));
+ __ Move(r8, Smi::FromInt(first - second));
+
+ __ movl(rax, Immediate(id)); // Test 0.
+ __ SmiSub(r9, rcx, rdx, exit);
+ __ SmiCompare(r9, r8);
+ __ j(not_equal, exit);
+
+ __ incq(rax); // Test 1.
+ __ SmiSub(rcx, rcx, rdx, exit);
+ __ SmiCompare(rcx, r8);
+ __ j(not_equal, exit);
+
+ __ Move(rcx, Smi::FromInt(first));
+
+ __ incq(rax); // Test 2.
+ __ SmiSubConstant(r9, rcx, Smi::FromInt(second));
+ __ SmiCompare(r9, r8);
+ __ j(not_equal, exit);
+
+ __ incq(rax); // Test 3.
+ __ SmiSubConstant(rcx, rcx, Smi::FromInt(second));
+ __ SmiCompare(rcx, r8);
+ __ j(not_equal, exit);
+
+ __ Move(rcx, Smi::FromInt(first));
+
+ __ incq(rax); // Test 4.
+ __ SmiSubConstant(r9, rcx, Smi::FromInt(second), exit);
+ __ SmiCompare(r9, r8);
+ __ j(not_equal, exit);
+
+ __ incq(rax); // Test 5.
+ __ SmiSubConstant(rcx, rcx, Smi::FromInt(second), exit);
+ __ SmiCompare(rcx, r8);
+ __ j(not_equal, exit);
+}
+
+static void SmiSubOverflowTest(MacroAssembler* masm,
+ Label* exit,
+ int id,
+ int x) {
+ // Subtracts a Smi from x so that the subtraction overflows.
+ ASSERT(x != -1); // Can't overflow by subtracting a Smi.
+ int y_max = (x < 0) ? (Smi::kMaxValue + 0) : (Smi::kMinValue + 0);
+ int y_min = (x < 0) ? (Smi::kMaxValue + x + 2) : (Smi::kMinValue + x);
+
+ __ movl(rax, Immediate(id));
+ __ Move(rcx, Smi::FromInt(x));
+ __ movq(r11, rcx); // Store original Smi value of x in r11.
+ __ Move(rdx, Smi::FromInt(y_min));
+ {
+ Label overflow_ok;
+ __ SmiSub(r9, rcx, rdx, &overflow_ok);
+ __ jmp(exit);
+ __ bind(&overflow_ok);
+ __ incq(rax);
+ __ SmiCompare(rcx, r11);
+ __ j(not_equal, exit);
+ }
+
+ {
+ Label overflow_ok;
+ __ incq(rax);
+ __ SmiSub(rcx, rcx, rdx, &overflow_ok);
+ __ jmp(exit);
+ __ bind(&overflow_ok);
+ __ incq(rax);
+ __ SmiCompare(rcx, r11);
+ __ j(not_equal, exit);
+ }
+
+ __ movq(rcx, r11);
+ {
+ Label overflow_ok;
+ __ incq(rax);
+ __ SmiSubConstant(r9, rcx, Smi::FromInt(y_min), &overflow_ok);
+ __ jmp(exit);
+ __ bind(&overflow_ok);
+ __ incq(rax);
+ __ SmiCompare(rcx, r11);
+ __ j(not_equal, exit);
+ }
+
+ {
+ Label overflow_ok;
+ __ incq(rax);
+ __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_min), &overflow_ok);
+ __ jmp(exit);
+ __ bind(&overflow_ok);
+ __ incq(rax);
+ __ SmiCompare(rcx, r11);
+ __ j(not_equal, exit);
+ }
+
+ __ Move(rdx, Smi::FromInt(y_max));
+
+ {
+ Label overflow_ok;
+ __ incq(rax);
+ __ SmiSub(r9, rcx, rdx, &overflow_ok);
+ __ jmp(exit);
+ __ bind(&overflow_ok);
+ __ incq(rax);
+ __ SmiCompare(rcx, r11);
+ __ j(not_equal, exit);
+ }
+
+ {
+ Label overflow_ok;
+ __ incq(rax);
+ __ SmiSub(rcx, rcx, rdx, &overflow_ok);
+ __ jmp(exit);
+ __ bind(&overflow_ok);
+ __ incq(rax);
+ __ SmiCompare(rcx, r11);
+ __ j(not_equal, exit);
+ }
+
+ __ movq(rcx, r11);
+ {
+ Label overflow_ok;
+ __ incq(rax);
+ __ SmiSubConstant(r9, rcx, Smi::FromInt(y_max), &overflow_ok);
+ __ jmp(exit);
+ __ bind(&overflow_ok);
+ __ incq(rax);
+ __ SmiCompare(rcx, r11);
+ __ j(not_equal, exit);
+ }
+
+ {
+ Label overflow_ok;
+ __ incq(rax);
+ __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_max), &overflow_ok);
+ __ jmp(exit);
+ __ bind(&overflow_ok);
+ __ incq(rax);
+ __ SmiCompare(rcx, r11);
+ __ j(not_equal, exit);
+ }
+}
+
+
+TEST(SmiSub) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer =
+ static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+
+ MacroAssembler* masm = &assembler;
+ masm->set_allow_stub_calls(false);
+ Label exit;
+
+ SmiSubTest(masm, &exit, 0x10, 1, 2);
+ SmiSubTest(masm, &exit, 0x20, 1, -2);
+ SmiSubTest(masm, &exit, 0x30, -1, 2);
+ SmiSubTest(masm, &exit, 0x40, -1, -2);
+ SmiSubTest(masm, &exit, 0x50, 0x1000, 0x2000);
+ SmiSubTest(masm, &exit, 0x60, Smi::kMinValue, -5);
+ SmiSubTest(masm, &exit, 0x70, Smi::kMaxValue, 5);
+ SmiSubTest(masm, &exit, 0x80, -Smi::kMaxValue, Smi::kMinValue);
+ SmiSubTest(masm, &exit, 0x90, 0, Smi::kMaxValue);
+
+ SmiSubOverflowTest(masm, &exit, 0xA0, 1);
+ SmiSubOverflowTest(masm, &exit, 0xB0, 1024);
+ SmiSubOverflowTest(masm, &exit, 0xC0, Smi::kMaxValue);
+ SmiSubOverflowTest(masm, &exit, 0xD0, -2);
+ SmiSubOverflowTest(masm, &exit, 0xE0, -42000);
+ SmiSubOverflowTest(masm, &exit, 0xF0, Smi::kMinValue);
+ SmiSubOverflowTest(masm, &exit, 0x100, 0);
+
+ __ xor_(rax, rax); // Success.
+ __ bind(&exit);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+
+void TestSmiMul(MacroAssembler* masm, Label* exit, int id, int x, int y) {
+ int64_t result = static_cast<int64_t>(x) * static_cast<int64_t>(y);
+ bool negative_zero = (result == 0) && (x < 0 || y < 0);
+ __ Move(rcx, Smi::FromInt(x));
+ __ movq(r11, rcx);
+ __ Move(rdx, Smi::FromInt(y));
+ if (Smi::IsValid(result) && !negative_zero) {
+ __ movl(rax, Immediate(id));
+ __ Move(r8, Smi::FromIntptr(result));
+ __ SmiMul(r9, rcx, rdx, exit);
+ __ incq(rax);
+ __ SmiCompare(r11, rcx);
+ __ j(not_equal, exit);
+ __ incq(rax);
+ __ SmiCompare(r9, r8);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiMul(rcx, rcx, rdx, exit);
+ __ SmiCompare(rcx, r8);
+ __ j(not_equal, exit);
+ } else {
+ __ movl(rax, Immediate(id + 8));
+ Label overflow_ok, overflow_ok2;
+ __ SmiMul(r9, rcx, rdx, &overflow_ok);
+ __ jmp(exit);
+ __ bind(&overflow_ok);
+ __ incq(rax);
+ __ SmiCompare(r11, rcx);
+ __ j(not_equal, exit);
+ __ incq(rax);
+ __ SmiMul(rcx, rcx, rdx, &overflow_ok2);
+ __ jmp(exit);
+ __ bind(&overflow_ok2);
+ // 31-bit version doesn't preserve rcx on failure.
+ // __ incq(rax);
+ // __ SmiCompare(r11, rcx);
+ // __ j(not_equal, exit);
+ }
+}
+
+
+TEST(SmiMul) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+
+ MacroAssembler* masm = &assembler;
+ masm->set_allow_stub_calls(false);
+ Label exit;
+
+ TestSmiMul(masm, &exit, 0x10, 0, 0);
+ TestSmiMul(masm, &exit, 0x20, -1, 0);
+ TestSmiMul(masm, &exit, 0x30, 0, -1);
+ TestSmiMul(masm, &exit, 0x40, -1, -1);
+ TestSmiMul(masm, &exit, 0x50, 0x10000, 0x10000);
+ TestSmiMul(masm, &exit, 0x60, 0x10000, 0xffff);
+ TestSmiMul(masm, &exit, 0x70, 0x10000, 0xffff);
+ TestSmiMul(masm, &exit, 0x80, Smi::kMaxValue, -1);
+ TestSmiMul(masm, &exit, 0x90, Smi::kMaxValue, -2);
+ TestSmiMul(masm, &exit, 0xa0, Smi::kMaxValue, 2);
+ TestSmiMul(masm, &exit, 0xb0, (Smi::kMaxValue / 2), 2);
+ TestSmiMul(masm, &exit, 0xc0, (Smi::kMaxValue / 2) + 1, 2);
+ TestSmiMul(masm, &exit, 0xd0, (Smi::kMinValue / 2), 2);
+ TestSmiMul(masm, &exit, 0xe0, (Smi::kMinValue / 2) - 1, 2);
+
+ __ xor_(rax, rax); // Success.
+ __ bind(&exit);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+void TestSmiDiv(MacroAssembler* masm, Label* exit, int id, int x, int y) {
+ bool division_by_zero = (y == 0);
+ bool negative_zero = (x == 0 && y < 0);
+#ifdef V8_TARGET_ARCH_X64
+ bool overflow = (x == Smi::kMinValue && y < 0); // Safe approx. used.
+#else
+ bool overflow = (x == Smi::kMinValue && y == -1);
+#endif
+ bool fraction = !division_by_zero && !overflow && (x % y != 0);
+ __ Move(r11, Smi::FromInt(x));
+ __ Move(r12, Smi::FromInt(y));
+ if (!fraction && !overflow && !negative_zero && !division_by_zero) {
+ // Division succeeds
+ __ movq(rcx, r11);
+ __ movq(r15, Immediate(id));
+ int result = x / y;
+ __ Move(r8, Smi::FromInt(result));
+ __ SmiDiv(r9, rcx, r12, exit);
+ // Might have destroyed rcx and r12.
+ __ incq(r15);
+ __ SmiCompare(r9, r8);
+ __ j(not_equal, exit);
+
+ __ incq(r15);
+ __ movq(rcx, r11);
+ __ Move(r12, Smi::FromInt(y));
+ __ SmiCompare(rcx, r11);
+ __ j(not_equal, exit);
+
+ __ incq(r15);
+ __ SmiDiv(rcx, rcx, r12, exit);
+
+ __ incq(r15);
+ __ SmiCompare(rcx, r8);
+ __ j(not_equal, exit);
+ } else {
+ // Division fails.
+ __ movq(r15, Immediate(id + 8));
+
+ Label fail_ok, fail_ok2;
+ __ movq(rcx, r11);
+ __ SmiDiv(r9, rcx, r12, &fail_ok);
+ __ jmp(exit);
+ __ bind(&fail_ok);
+
+ __ incq(r15);
+ __ SmiCompare(rcx, r11);
+ __ j(not_equal, exit);
+
+ __ incq(r15);
+ __ SmiDiv(rcx, rcx, r12, &fail_ok2);
+ __ jmp(exit);
+ __ bind(&fail_ok2);
+
+ __ incq(r15);
+ __ SmiCompare(rcx, r11);
+ __ j(not_equal, exit);
+ }
+}
+
+
+TEST(SmiDiv) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer =
+ static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+
+ MacroAssembler* masm = &assembler;
+ masm->set_allow_stub_calls(false);
+ Label exit;
+
+ TestSmiDiv(masm, &exit, 0x10, 1, 1);
+ TestSmiDiv(masm, &exit, 0x20, 1, 0);
+ TestSmiDiv(masm, &exit, 0x30, -1, 0);
+ TestSmiDiv(masm, &exit, 0x40, 0, 1);
+ TestSmiDiv(masm, &exit, 0x50, 0, -1);
+ TestSmiDiv(masm, &exit, 0x60, 4, 2);
+ TestSmiDiv(masm, &exit, 0x70, -4, 2);
+ TestSmiDiv(masm, &exit, 0x80, 4, -2);
+ TestSmiDiv(masm, &exit, 0x90, -4, -2);
+ TestSmiDiv(masm, &exit, 0xa0, 3, 2);
+ TestSmiDiv(masm, &exit, 0xb0, 3, 4);
+ TestSmiDiv(masm, &exit, 0xc0, 1, Smi::kMaxValue);
+ TestSmiDiv(masm, &exit, 0xd0, -1, Smi::kMaxValue);
+ TestSmiDiv(masm, &exit, 0xe0, Smi::kMaxValue, 1);
+ TestSmiDiv(masm, &exit, 0xf0, Smi::kMaxValue, Smi::kMaxValue);
+ TestSmiDiv(masm, &exit, 0x100, Smi::kMaxValue, -Smi::kMaxValue);
+ TestSmiDiv(masm, &exit, 0x110, Smi::kMaxValue, -1);
+ TestSmiDiv(masm, &exit, 0x120, Smi::kMinValue, 1);
+ TestSmiDiv(masm, &exit, 0x130, Smi::kMinValue, Smi::kMinValue);
+ TestSmiDiv(masm, &exit, 0x140, Smi::kMinValue, -1);
+
+ __ xor_(r15, r15); // Success.
+ __ bind(&exit);
+ __ movq(rax, r15);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+void TestSmiMod(MacroAssembler* masm, Label* exit, int id, int x, int y) {
+ bool division_by_zero = (y == 0);
+ bool division_overflow = (x == Smi::kMinValue) && (y == -1);
+ bool fraction = !division_by_zero && !division_overflow && ((x % y) != 0);
+ bool negative_zero = (!fraction && x < 0);
+ __ Move(rcx, Smi::FromInt(x));
+ __ movq(r11, rcx);
+ __ Move(r12, Smi::FromInt(y));
+ if (!division_overflow && !negative_zero && !division_by_zero) {
+ // Modulo succeeds
+ __ movq(r15, Immediate(id));
+ int result = x % y;
+ __ Move(r8, Smi::FromInt(result));
+ __ SmiMod(r9, rcx, r12, exit);
+
+ __ incq(r15);
+ __ SmiCompare(r9, r8);
+ __ j(not_equal, exit);
+
+ __ incq(r15);
+ __ SmiCompare(rcx, r11);
+ __ j(not_equal, exit);
+
+ __ incq(r15);
+ __ SmiMod(rcx, rcx, r12, exit);
+
+ __ incq(r15);
+ __ SmiCompare(rcx, r8);
+ __ j(not_equal, exit);
+ } else {
+ // Modulo fails.
+ __ movq(r15, Immediate(id + 8));
+
+ Label fail_ok, fail_ok2;
+ __ SmiMod(r9, rcx, r12, &fail_ok);
+ __ jmp(exit);
+ __ bind(&fail_ok);
+
+ __ incq(r15);
+ __ SmiCompare(rcx, r11);
+ __ j(not_equal, exit);
+
+ __ incq(r15);
+ __ SmiMod(rcx, rcx, r12, &fail_ok2);
+ __ jmp(exit);
+ __ bind(&fail_ok2);
+
+ __ incq(r15);
+ __ SmiCompare(rcx, r11);
+ __ j(not_equal, exit);
+ }
+}
+
+
+TEST(SmiMod) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer =
+ static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+
+ MacroAssembler* masm = &assembler;
+ masm->set_allow_stub_calls(false);
+ Label exit;
+
+ TestSmiMod(masm, &exit, 0x10, 1, 1);
+ TestSmiMod(masm, &exit, 0x20, 1, 0);
+ TestSmiMod(masm, &exit, 0x30, -1, 0);
+ TestSmiMod(masm, &exit, 0x40, 0, 1);
+ TestSmiMod(masm, &exit, 0x50, 0, -1);
+ TestSmiMod(masm, &exit, 0x60, 4, 2);
+ TestSmiMod(masm, &exit, 0x70, -4, 2);
+ TestSmiMod(masm, &exit, 0x80, 4, -2);
+ TestSmiMod(masm, &exit, 0x90, -4, -2);
+ TestSmiMod(masm, &exit, 0xa0, 3, 2);
+ TestSmiMod(masm, &exit, 0xb0, 3, 4);
+ TestSmiMod(masm, &exit, 0xc0, 1, Smi::kMaxValue);
+ TestSmiMod(masm, &exit, 0xd0, -1, Smi::kMaxValue);
+ TestSmiMod(masm, &exit, 0xe0, Smi::kMaxValue, 1);
+ TestSmiMod(masm, &exit, 0xf0, Smi::kMaxValue, Smi::kMaxValue);
+ TestSmiMod(masm, &exit, 0x100, Smi::kMaxValue, -Smi::kMaxValue);
+ TestSmiMod(masm, &exit, 0x110, Smi::kMaxValue, -1);
+ TestSmiMod(masm, &exit, 0x120, Smi::kMinValue, 1);
+ TestSmiMod(masm, &exit, 0x130, Smi::kMinValue, Smi::kMinValue);
+ TestSmiMod(masm, &exit, 0x140, Smi::kMinValue, -1);
+
+ __ xor_(r15, r15); // Success.
+ __ bind(&exit);
+ __ movq(rax, r15);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+void TestSmiIndex(MacroAssembler* masm, Label* exit, int id, int x) {
+ __ movl(rax, Immediate(id));
+
+ for (int i = 0; i < 8; i++) {
+ __ Move(rcx, Smi::FromInt(x));
+ SmiIndex index = masm->SmiToIndex(rdx, rcx, i);
+ ASSERT(index.reg.is(rcx) || index.reg.is(rdx));
+ __ shl(index.reg, Immediate(index.scale));
+ __ Set(r8, static_cast<intptr_t>(x) << i);
+ __ SmiCompare(index.reg, r8);
+ __ j(not_equal, exit);
+ __ incq(rax);
+ __ Move(rcx, Smi::FromInt(x));
+ index = masm->SmiToIndex(rcx, rcx, i);
+ ASSERT(index.reg.is(rcx));
+ __ shl(rcx, Immediate(index.scale));
+ __ Set(r8, static_cast<intptr_t>(x) << i);
+ __ SmiCompare(rcx, r8);
+ __ j(not_equal, exit);
+ __ incq(rax);
+
+ __ Move(rcx, Smi::FromInt(x));
+ index = masm->SmiToNegativeIndex(rdx, rcx, i);
+ ASSERT(index.reg.is(rcx) || index.reg.is(rdx));
+ __ shl(index.reg, Immediate(index.scale));
+ __ Set(r8, static_cast<intptr_t>(-x) << i);
+ __ SmiCompare(index.reg, r8);
+ __ j(not_equal, exit);
+ __ incq(rax);
+ __ Move(rcx, Smi::FromInt(x));
+ index = masm->SmiToNegativeIndex(rcx, rcx, i);
+ ASSERT(index.reg.is(rcx));
+ __ shl(rcx, Immediate(index.scale));
+ __ Set(r8, static_cast<intptr_t>(-x) << i);
+ __ SmiCompare(rcx, r8);
+ __ j(not_equal, exit);
+ __ incq(rax);
+ }
+}
+
+TEST(SmiIndex) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer =
+ static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+
+ MacroAssembler* masm = &assembler;
+ masm->set_allow_stub_calls(false);
+ Label exit;
+
+ TestSmiIndex(masm, &exit, 0x10, 0);
+ TestSmiIndex(masm, &exit, 0x20, 1);
+ TestSmiIndex(masm, &exit, 0x30, 100);
+ TestSmiIndex(masm, &exit, 0x40, 1000);
+ TestSmiIndex(masm, &exit, 0x50, Smi::kMaxValue);
+
+ __ xor_(rax, rax); // Success.
+ __ bind(&exit);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+void TestSelectNonSmi(MacroAssembler* masm, Label* exit, int id, int x, int y) {
+ __ movl(rax, Immediate(id));
+ __ Move(rcx, Smi::FromInt(x));
+ __ Move(rdx, Smi::FromInt(y));
+ __ xor_(rdx, Immediate(kSmiTagMask));
+ __ SelectNonSmi(r9, rcx, rdx, exit);
+
+ __ incq(rax);
+ __ SmiCompare(r9, rdx);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ Move(rcx, Smi::FromInt(x));
+ __ Move(rdx, Smi::FromInt(y));
+ __ xor_(rcx, Immediate(kSmiTagMask));
+ __ SelectNonSmi(r9, rcx, rdx, exit);
+
+ __ incq(rax);
+ __ SmiCompare(r9, rcx);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ Label fail_ok;
+ __ Move(rcx, Smi::FromInt(x));
+ __ Move(rdx, Smi::FromInt(y));
+ __ xor_(rcx, Immediate(kSmiTagMask));
+ __ xor_(rdx, Immediate(kSmiTagMask));
+ __ SelectNonSmi(r9, rcx, rdx, &fail_ok);
+ __ jmp(exit);
+ __ bind(&fail_ok);
+}
+
+
+TEST(SmiSelectNonSmi) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer =
+ static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+
+ MacroAssembler* masm = &assembler;
+ masm->set_allow_stub_calls(false); // Avoid inline checks.
+ Label exit;
+
+ TestSelectNonSmi(masm, &exit, 0x10, 0, 0);
+ TestSelectNonSmi(masm, &exit, 0x20, 0, 1);
+ TestSelectNonSmi(masm, &exit, 0x30, 1, 0);
+ TestSelectNonSmi(masm, &exit, 0x40, 0, -1);
+ TestSelectNonSmi(masm, &exit, 0x50, -1, 0);
+ TestSelectNonSmi(masm, &exit, 0x60, -1, -1);
+ TestSelectNonSmi(masm, &exit, 0x70, 1, 1);
+ TestSelectNonSmi(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
+ TestSelectNonSmi(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
+
+ __ xor_(rax, rax); // Success.
+ __ bind(&exit);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+void TestSmiAnd(MacroAssembler* masm, Label* exit, int id, int x, int y) {
+ int result = x & y;
+
+ __ movl(rax, Immediate(id));
+
+ __ Move(rcx, Smi::FromInt(x));
+ __ movq(r11, rcx);
+ __ Move(rdx, Smi::FromInt(y));
+ __ Move(r8, Smi::FromInt(result));
+ __ SmiAnd(r9, rcx, rdx);
+ __ SmiCompare(r8, r9);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiCompare(r11, rcx);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiAnd(rcx, rcx, rdx);
+ __ SmiCompare(r8, rcx);
+ __ j(not_equal, exit);
+
+ __ movq(rcx, r11);
+ __ incq(rax);
+ __ SmiAndConstant(r9, rcx, Smi::FromInt(y));
+ __ SmiCompare(r8, r9);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiCompare(r11, rcx);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiAndConstant(rcx, rcx, Smi::FromInt(y));
+ __ SmiCompare(r8, rcx);
+ __ j(not_equal, exit);
+}
+
+
+TEST(SmiAnd) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer =
+ static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+
+ MacroAssembler* masm = &assembler;
+ masm->set_allow_stub_calls(false);
+ Label exit;
+
+ TestSmiAnd(masm, &exit, 0x10, 0, 0);
+ TestSmiAnd(masm, &exit, 0x20, 0, 1);
+ TestSmiAnd(masm, &exit, 0x30, 1, 0);
+ TestSmiAnd(masm, &exit, 0x40, 0, -1);
+ TestSmiAnd(masm, &exit, 0x50, -1, 0);
+ TestSmiAnd(masm, &exit, 0x60, -1, -1);
+ TestSmiAnd(masm, &exit, 0x70, 1, 1);
+ TestSmiAnd(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
+ TestSmiAnd(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
+ TestSmiAnd(masm, &exit, 0xA0, Smi::kMinValue, -1);
+ TestSmiAnd(masm, &exit, 0xB0, Smi::kMinValue, -1);
+
+ __ xor_(rax, rax); // Success.
+ __ bind(&exit);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+void TestSmiOr(MacroAssembler* masm, Label* exit, int id, int x, int y) {
+ int result = x | y;
+
+ __ movl(rax, Immediate(id));
+
+ __ Move(rcx, Smi::FromInt(x));
+ __ movq(r11, rcx);
+ __ Move(rdx, Smi::FromInt(y));
+ __ Move(r8, Smi::FromInt(result));
+ __ SmiOr(r9, rcx, rdx);
+ __ SmiCompare(r8, r9);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiCompare(r11, rcx);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiOr(rcx, rcx, rdx);
+ __ SmiCompare(r8, rcx);
+ __ j(not_equal, exit);
+
+ __ movq(rcx, r11);
+ __ incq(rax);
+ __ SmiOrConstant(r9, rcx, Smi::FromInt(y));
+ __ SmiCompare(r8, r9);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiCompare(r11, rcx);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiOrConstant(rcx, rcx, Smi::FromInt(y));
+ __ SmiCompare(r8, rcx);
+ __ j(not_equal, exit);
+}
+
+
+TEST(SmiOr) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer =
+ static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+
+ MacroAssembler* masm = &assembler;
+ masm->set_allow_stub_calls(false);
+ Label exit;
+
+ TestSmiOr(masm, &exit, 0x10, 0, 0);
+ TestSmiOr(masm, &exit, 0x20, 0, 1);
+ TestSmiOr(masm, &exit, 0x30, 1, 0);
+ TestSmiOr(masm, &exit, 0x40, 0, -1);
+ TestSmiOr(masm, &exit, 0x50, -1, 0);
+ TestSmiOr(masm, &exit, 0x60, -1, -1);
+ TestSmiOr(masm, &exit, 0x70, 1, 1);
+ TestSmiOr(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
+ TestSmiOr(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
+ TestSmiOr(masm, &exit, 0xA0, Smi::kMinValue, -1);
+ TestSmiOr(masm, &exit, 0xB0, 0x05555555, 0x01234567);
+ TestSmiOr(masm, &exit, 0xC0, 0x05555555, 0x0fedcba9);
+ TestSmiOr(masm, &exit, 0xD0, Smi::kMinValue, -1);
+
+ __ xor_(rax, rax); // Success.
+ __ bind(&exit);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+void TestSmiXor(MacroAssembler* masm, Label* exit, int id, int x, int y) {
+ int result = x ^ y;
+
+ __ movl(rax, Immediate(id));
+
+ __ Move(rcx, Smi::FromInt(x));
+ __ movq(r11, rcx);
+ __ Move(rdx, Smi::FromInt(y));
+ __ Move(r8, Smi::FromInt(result));
+ __ SmiXor(r9, rcx, rdx);
+ __ SmiCompare(r8, r9);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiCompare(r11, rcx);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiXor(rcx, rcx, rdx);
+ __ SmiCompare(r8, rcx);
+ __ j(not_equal, exit);
+
+ __ movq(rcx, r11);
+ __ incq(rax);
+ __ SmiXorConstant(r9, rcx, Smi::FromInt(y));
+ __ SmiCompare(r8, r9);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiCompare(r11, rcx);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiXorConstant(rcx, rcx, Smi::FromInt(y));
+ __ SmiCompare(r8, rcx);
+ __ j(not_equal, exit);
+}
+
+
+TEST(SmiXor) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer =
+ static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+
+ MacroAssembler* masm = &assembler;
+ masm->set_allow_stub_calls(false);
+ Label exit;
+
+ TestSmiXor(masm, &exit, 0x10, 0, 0);
+ TestSmiXor(masm, &exit, 0x20, 0, 1);
+ TestSmiXor(masm, &exit, 0x30, 1, 0);
+ TestSmiXor(masm, &exit, 0x40, 0, -1);
+ TestSmiXor(masm, &exit, 0x50, -1, 0);
+ TestSmiXor(masm, &exit, 0x60, -1, -1);
+ TestSmiXor(masm, &exit, 0x70, 1, 1);
+ TestSmiXor(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
+ TestSmiXor(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
+ TestSmiXor(masm, &exit, 0xA0, Smi::kMinValue, -1);
+ TestSmiXor(masm, &exit, 0xB0, 0x5555555, 0x01234567);
+ TestSmiXor(masm, &exit, 0xC0, 0x5555555, 0x0fedcba9);
+ TestSmiXor(masm, &exit, 0xD0, Smi::kMinValue, -1);
+
+ __ xor_(rax, rax); // Success.
+ __ bind(&exit);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+void TestSmiNot(MacroAssembler* masm, Label* exit, int id, int x) {
+ int result = ~x;
+ __ movl(rax, Immediate(id));
+
+ __ Move(r8, Smi::FromInt(result));
+ __ Move(rcx, Smi::FromInt(x));
+ __ movq(r11, rcx);
+
+ __ SmiNot(r9, rcx);
+ __ SmiCompare(r9, r8);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiCompare(r11, rcx);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ SmiNot(rcx, rcx);
+ __ SmiCompare(rcx, r8);
+ __ j(not_equal, exit);
+}
+
+
+TEST(SmiNot) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer =
+ static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+
+ MacroAssembler* masm = &assembler;
+ masm->set_allow_stub_calls(false);
+ Label exit;
+
+ TestSmiNot(masm, &exit, 0x10, 0);
+ TestSmiNot(masm, &exit, 0x20, 1);
+ TestSmiNot(masm, &exit, 0x30, -1);
+ TestSmiNot(masm, &exit, 0x40, 127);
+ TestSmiNot(masm, &exit, 0x50, 65535);
+ TestSmiNot(masm, &exit, 0x60, Smi::kMinValue);
+ TestSmiNot(masm, &exit, 0x70, Smi::kMaxValue);
+ TestSmiNot(masm, &exit, 0x80, 0x05555555);
+
+ __ xor_(rax, rax); // Success.
+ __ bind(&exit);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+void TestSmiShiftLeft(MacroAssembler* masm, Label* exit, int id, int x) {
+ const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
+ const int kNumShifts = 5;
+ __ movl(rax, Immediate(id));
+ for (int i = 0; i < kNumShifts; i++) {
+ // rax == id + i * 10.
+ int shift = shifts[i];
+ int result = x << shift;
+ if (Smi::IsValid(result)) {
+ __ Move(r8, Smi::FromInt(result));
+ __ Move(rcx, Smi::FromInt(x));
+ __ SmiShiftLeftConstant(r9, rcx, shift, exit);
+
+ __ incq(rax);
+ __ SmiCompare(r9, r8);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ Move(rcx, Smi::FromInt(x));
+ __ SmiShiftLeftConstant(rcx, rcx, shift, exit);
+
+ __ incq(rax);
+ __ SmiCompare(rcx, r8);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ Move(rdx, Smi::FromInt(x));
+ __ Move(rcx, Smi::FromInt(shift));
+ __ SmiShiftLeft(r9, rdx, rcx, exit);
+
+ __ incq(rax);
+ __ SmiCompare(r9, r8);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ Move(rdx, Smi::FromInt(x));
+ __ Move(r11, Smi::FromInt(shift));
+ __ SmiShiftLeft(r9, rdx, r11, exit);
+
+ __ incq(rax);
+ __ SmiCompare(r9, r8);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ Move(rdx, Smi::FromInt(x));
+ __ Move(r11, Smi::FromInt(shift));
+ __ SmiShiftLeft(rdx, rdx, r11, exit);
+
+ __ incq(rax);
+ __ SmiCompare(rdx, r8);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ } else {
+ // Cannot happen with long smis.
+ Label fail_ok;
+ __ Move(rcx, Smi::FromInt(x));
+ __ movq(r11, rcx);
+ __ SmiShiftLeftConstant(r9, rcx, shift, &fail_ok);
+ __ jmp(exit);
+ __ bind(&fail_ok);
+
+ __ incq(rax);
+ __ SmiCompare(rcx, r11);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ Label fail_ok2;
+ __ SmiShiftLeftConstant(rcx, rcx, shift, &fail_ok2);
+ __ jmp(exit);
+ __ bind(&fail_ok2);
+
+ __ incq(rax);
+ __ SmiCompare(rcx, r11);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ Move(r8, Smi::FromInt(shift));
+ Label fail_ok3;
+ __ SmiShiftLeft(r9, rcx, r8, &fail_ok3);
+ __ jmp(exit);
+ __ bind(&fail_ok3);
+
+ __ incq(rax);
+ __ SmiCompare(rcx, r11);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ Move(r8, Smi::FromInt(shift));
+ __ movq(rdx, r11);
+ Label fail_ok4;
+ __ SmiShiftLeft(rdx, rdx, r8, &fail_ok4);
+ __ jmp(exit);
+ __ bind(&fail_ok4);
+
+ __ incq(rax);
+ __ SmiCompare(rdx, r11);
+ __ j(not_equal, exit);
+
+ __ addq(rax, Immediate(3));
+ }
+ }
+}
+
+
+TEST(SmiShiftLeft) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer =
+ static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 3,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+
+ MacroAssembler* masm = &assembler;
+ masm->set_allow_stub_calls(false);
+ Label exit;
+
+ TestSmiShiftLeft(masm, &exit, 0x10, 0);
+ TestSmiShiftLeft(masm, &exit, 0x50, 1);
+ TestSmiShiftLeft(masm, &exit, 0x90, 127);
+ TestSmiShiftLeft(masm, &exit, 0xD0, 65535);
+ TestSmiShiftLeft(masm, &exit, 0x110, Smi::kMaxValue);
+ TestSmiShiftLeft(masm, &exit, 0x150, Smi::kMinValue);
+ TestSmiShiftLeft(masm, &exit, 0x190, -1);
+
+ __ xor_(rax, rax); // Success.
+ __ bind(&exit);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+void TestSmiShiftLogicalRight(MacroAssembler* masm,
+ Label* exit,
+ int id,
+ int x) {
+ const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
+ const int kNumShifts = 5;
+ __ movl(rax, Immediate(id));
+ for (int i = 0; i < kNumShifts; i++) {
+ int shift = shifts[i];
+ intptr_t result = static_cast<unsigned int>(x) >> shift;
+ if (Smi::IsValid(result)) {
+ __ Move(r8, Smi::FromInt(result));
+ __ Move(rcx, Smi::FromInt(x));
+ __ SmiShiftLogicalRightConstant(r9, rcx, shift, exit);
+
+ __ incq(rax);
+ __ SmiCompare(r9, r8);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ Move(rdx, Smi::FromInt(x));
+ __ Move(rcx, Smi::FromInt(shift));
+ __ SmiShiftLogicalRight(r9, rdx, rcx, exit);
+
+ __ incq(rax);
+ __ SmiCompare(r9, r8);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ Move(rdx, Smi::FromInt(x));
+ __ Move(r11, Smi::FromInt(shift));
+ __ SmiShiftLogicalRight(r9, rdx, r11, exit);
+
+ __ incq(rax);
+ __ SmiCompare(r9, r8);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ } else {
+ // Cannot happen with long smis.
+ Label fail_ok;
+ __ Move(rcx, Smi::FromInt(x));
+ __ movq(r11, rcx);
+ __ SmiShiftLogicalRightConstant(r9, rcx, shift, &fail_ok);
+ __ jmp(exit);
+ __ bind(&fail_ok);
+
+ __ incq(rax);
+ __ SmiCompare(rcx, r11);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ Move(r8, Smi::FromInt(shift));
+ Label fail_ok3;
+ __ SmiShiftLogicalRight(r9, rcx, r8, &fail_ok3);
+ __ jmp(exit);
+ __ bind(&fail_ok3);
+
+ __ incq(rax);
+ __ SmiCompare(rcx, r11);
+ __ j(not_equal, exit);
+
+ __ addq(rax, Immediate(3));
+ }
+ }
+}
+
+
+TEST(SmiShiftLogicalRight) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer =
+ static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+
+ MacroAssembler* masm = &assembler;
+ masm->set_allow_stub_calls(false);
+ Label exit;
+
+ TestSmiShiftLogicalRight(masm, &exit, 0x10, 0);
+ TestSmiShiftLogicalRight(masm, &exit, 0x30, 1);
+ TestSmiShiftLogicalRight(masm, &exit, 0x50, 127);
+ TestSmiShiftLogicalRight(masm, &exit, 0x70, 65535);
+ TestSmiShiftLogicalRight(masm, &exit, 0x90, Smi::kMaxValue);
+ TestSmiShiftLogicalRight(masm, &exit, 0xB0, Smi::kMinValue);
+ TestSmiShiftLogicalRight(masm, &exit, 0xD0, -1);
+
+ __ xor_(rax, rax); // Success.
+ __ bind(&exit);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+void TestSmiShiftArithmeticRight(MacroAssembler* masm,
+ Label* exit,
+ int id,
+ int x) {
+ const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
+ const int kNumShifts = 5;
+ __ movl(rax, Immediate(id));
+ for (int i = 0; i < kNumShifts; i++) {
+ int shift = shifts[i];
+ // Guaranteed arithmetic shift.
+ int result = (x < 0) ? ~((~x) >> shift) : (x >> shift);
+ __ Move(r8, Smi::FromInt(result));
+ __ Move(rcx, Smi::FromInt(x));
+ __ SmiShiftArithmeticRightConstant(rcx, rcx, shift);
+
+ __ SmiCompare(rcx, r8);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ __ Move(rdx, Smi::FromInt(x));
+ __ Move(r11, Smi::FromInt(shift));
+ __ SmiShiftArithmeticRight(rdx, rdx, r11);
+
+ __ SmiCompare(rdx, r8);
+ __ j(not_equal, exit);
+
+ __ incq(rax);
+ }
+}
+
+
+TEST(SmiShiftArithmeticRight) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer =
+ static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+
+ MacroAssembler* masm = &assembler;
+ masm->set_allow_stub_calls(false);
+ Label exit;
+
+ TestSmiShiftArithmeticRight(masm, &exit, 0x10, 0);
+ TestSmiShiftArithmeticRight(masm, &exit, 0x20, 1);
+ TestSmiShiftArithmeticRight(masm, &exit, 0x30, 127);
+ TestSmiShiftArithmeticRight(masm, &exit, 0x40, 65535);
+ TestSmiShiftArithmeticRight(masm, &exit, 0x50, Smi::kMaxValue);
+ TestSmiShiftArithmeticRight(masm, &exit, 0x60, Smi::kMinValue);
+ TestSmiShiftArithmeticRight(masm, &exit, 0x70, -1);
+
+ __ xor_(rax, rax); // Success.
+ __ bind(&exit);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+void TestPositiveSmiPowerUp(MacroAssembler* masm, Label* exit, int id, int x) {
+ ASSERT(x >= 0);
+ int powers[] = { 0, 1, 2, 3, 8, 16, 24, 31 };
+ int power_count = 8;
+ __ movl(rax, Immediate(id));
+ for (int i = 0; i < power_count; i++) {
+ int power = powers[i];
+ intptr_t result = static_cast<intptr_t>(x) << power;
+ __ Set(r8, result);
+ __ Move(rcx, Smi::FromInt(x));
+ __ movq(r11, rcx);
+ __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rcx, power);
+ __ SmiCompare(rdx, r8);
+ __ j(not_equal, exit);
+ __ incq(rax);
+ __ SmiCompare(r11, rcx); // rcx unchanged.
+ __ j(not_equal, exit);
+ __ incq(rax);
+ __ PositiveSmiTimesPowerOfTwoToInteger64(rcx, rcx, power);
+ __ SmiCompare(rdx, r8);
+ __ j(not_equal, exit);
+ __ incq(rax);
+ }
+}
+
+
+TEST(PositiveSmiTimesPowerOfTwoToInteger64) {
+ // Allocate an executable page of memory.
+ size_t actual_size;
+ byte* buffer =
+ static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
+ &actual_size,
+ true));
+ CHECK(buffer);
+ HandleScope handles;
+ MacroAssembler assembler(buffer, actual_size);
+
+ MacroAssembler* masm = &assembler;
+ masm->set_allow_stub_calls(false);
+ Label exit;
+
+ TestPositiveSmiPowerUp(masm, &exit, 0x20, 0);
+ TestPositiveSmiPowerUp(masm, &exit, 0x40, 1);
+ TestPositiveSmiPowerUp(masm, &exit, 0x60, 127);
+ TestPositiveSmiPowerUp(masm, &exit, 0x80, 128);
+ TestPositiveSmiPowerUp(masm, &exit, 0xA0, 255);
+ TestPositiveSmiPowerUp(masm, &exit, 0xC0, 256);
+ TestPositiveSmiPowerUp(masm, &exit, 0x100, 65535);
+ TestPositiveSmiPowerUp(masm, &exit, 0x120, 65536);
+ TestPositiveSmiPowerUp(masm, &exit, 0x140, Smi::kMaxValue);
+
+ __ xor_(rax, rax); // Success.
+ __ bind(&exit);
+ __ ret(0);
+
+ CodeDesc desc;
+ masm->GetCode(&desc);
+ // Call the function from C++.
+ int result = FUNCTION_CAST<F0>(buffer)();
+ CHECK_EQ(0, result);
+}
+
+
+#undef __
diff --git a/deps/v8/test/mjsunit/compiler/literals-assignment.js b/deps/v8/test/mjsunit/compiler/literals-assignment.js
new file mode 100644
index 0000000000..932bfa7f10
--- /dev/null
+++ b/deps/v8/test/mjsunit/compiler/literals-assignment.js
@@ -0,0 +1,71 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Tests for simple assignments and literals inside an anonymous function
+
+// Test simple return statement.
+assertEquals(8, eval("(function() { return 8; })()"));
+
+// Test simple assignment
+var code = "(function() {\
+ var a;\
+ a = 8;\
+ return a;\
+ })()";
+assertEquals(8, eval(code));
+
+code = "(function() {\
+ var x;\
+ x = 'abc';\
+ return x;\
+ })()";
+assertEquals("abc", eval(code));
+
+// Test assignment as an RHS expression
+
+code = "(function() {\
+ var x, y;\
+ x = y = 8;\
+ return x;\
+ })()";
+assertEquals(8, eval(code));
+
+
+code = "(function() {\
+ var x, y;\
+ x = y = 8;\
+ return y;\
+ })()";
+assertEquals(8, eval(code));
+
+
+code = "(function() {\
+ var x,y,z;\
+ return x = y = z = 8;\
+ })()";
+assertEquals(8, eval(code));
+
diff --git a/deps/v8/test/mjsunit/compiler/literals.js b/deps/v8/test/mjsunit/compiler/literals.js
new file mode 100644
index 0000000000..e0e532fa2a
--- /dev/null
+++ b/deps/v8/test/mjsunit/compiler/literals.js
@@ -0,0 +1,35 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test simple literals.
+assertEquals(8, eval("8"));
+
+assertEquals(null, eval("null"));
+
+assertEquals("abc", eval("'abc'"));
+
+assertEquals(8, eval("6;'abc';8"));
diff --git a/deps/v8/test/mjsunit/debug-backtrace.js b/deps/v8/test/mjsunit/debug-backtrace.js
index 0c200aee3e..d15b2d2619 100644
--- a/deps/v8/test/mjsunit/debug-backtrace.js
+++ b/deps/v8/test/mjsunit/debug-backtrace.js
@@ -69,6 +69,11 @@ ParsedResponse.prototype.body = function() {
}
+ParsedResponse.prototype.running = function() {
+ return this.response_.running;
+}
+
+
ParsedResponse.prototype.lookup = function(handle) {
return this.refs_[handle];
}
@@ -88,8 +93,9 @@ function listener(event, exec_state, event_data, data) {
var frame;
var source;
- // Get the debug command processor.
- var dcp = exec_state.debugCommandProcessor();
+ var dcp;
+ // New copy of debug command processor paused state.
+ dcp = exec_state.debugCommandProcessor(false);
// Get the backtrace.
var json;
@@ -114,6 +120,7 @@ function listener(event, exec_state, event_data, data) {
assertEquals("g", response.lookup(frames[2].func.ref).name);
assertEquals(3, frames[3].index);
assertEquals("", response.lookup(frames[3].func.ref).name);
+ assertFalse(response.running(), "expected not running");
// Get backtrace with two frames.
json = '{"seq":0,"type":"request","command":"backtrace","arguments":{"fromFrame":1,"toFrame":3}}'
@@ -234,6 +241,17 @@ function listener(event, exec_state, event_data, data) {
source = response.body();
assertEquals(Debug.findScript(f).source, source.source);
+ // New copy of debug command processor in running state.
+ dcp = exec_state.debugCommandProcessor(true);
+ // Get the backtrace.
+ json = '{"seq":0,"type":"request","command":"backtrace"}'
+ resp = dcp.processDebugJSONRequest(json);
+ response = new ParsedResponse(resp);
+ // It might be argueable, but we expect response to have body when
+ // not suspended
+ assertTrue(!!response.body(), "response should be null");
+ assertTrue(response.running(), "expected running");
+
listenerCalled = true;
}
} catch (e) {
diff --git a/deps/v8/test/mjsunit/debug-changebreakpoint.js b/deps/v8/test/mjsunit/debug-changebreakpoint.js
index 477c908136..936523a0e7 100644
--- a/deps/v8/test/mjsunit/debug-changebreakpoint.js
+++ b/deps/v8/test/mjsunit/debug-changebreakpoint.js
@@ -59,7 +59,7 @@ function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
// Get the debug command processor.
- var dcp = exec_state.debugCommandProcessor();
+ var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
// Test some illegal clearbreakpoint requests.
var request = '{' + base_request + '}'
diff --git a/deps/v8/test/mjsunit/debug-clearbreakpoint.js b/deps/v8/test/mjsunit/debug-clearbreakpoint.js
index 28920c53a5..59479f2daa 100644
--- a/deps/v8/test/mjsunit/debug-clearbreakpoint.js
+++ b/deps/v8/test/mjsunit/debug-clearbreakpoint.js
@@ -59,7 +59,7 @@ function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
// Get the debug command processor.
- var dcp = exec_state.debugCommandProcessor();
+ var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
// Test some illegal clearbreakpoint requests.
var request = '{' + base_request + '}'
diff --git a/deps/v8/test/mjsunit/debug-clearbreakpointgroup.js b/deps/v8/test/mjsunit/debug-clearbreakpointgroup.js
index eca9378759..aad6c3aff7 100644
--- a/deps/v8/test/mjsunit/debug-clearbreakpointgroup.js
+++ b/deps/v8/test/mjsunit/debug-clearbreakpointgroup.js
@@ -60,7 +60,7 @@ function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
// Get the debug command processor.
- var dcp = exec_state.debugCommandProcessor();
+ var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
// Clear breakpoint group 1.
testArguments(dcp, '{"groupId":1}', true);
diff --git a/deps/v8/test/mjsunit/debug-continue.js b/deps/v8/test/mjsunit/debug-continue.js
index 0c11abc56e..a501aa925c 100644
--- a/deps/v8/test/mjsunit/debug-continue.js
+++ b/deps/v8/test/mjsunit/debug-continue.js
@@ -44,7 +44,10 @@ function safeEval(code) {
}
}
-function testArguments(dcp, arguments, success) {
+function testArguments(exec_state, arguments, success) {
+ // Get the debug command processor in paused state.
+ var dcp = exec_state.debugCommandProcessor(false);
+
// Generate request with the supplied arguments
var request;
if (arguments) {
@@ -65,25 +68,23 @@ function testArguments(dcp, arguments, success) {
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
- // Get the debug command processor.
- var dcp = exec_state.debugCommandProcessor();
// Test simple continue request.
- testArguments(dcp, void 0, true);
+ testArguments(exec_state, void 0, true);
// Test some illegal continue requests.
- testArguments(dcp, '{"stepaction":"maybe"}', false);
- testArguments(dcp, '{"stepcount":-1}', false);
+ testArguments(exec_state, '{"stepaction":"maybe"}', false);
+ testArguments(exec_state, '{"stepcount":-1}', false);
// Test some legal continue requests.
- testArguments(dcp, '{"stepaction":"in"}', true);
- testArguments(dcp, '{"stepaction":"min"}', true);
- testArguments(dcp, '{"stepaction":"next"}', true);
- testArguments(dcp, '{"stepaction":"out"}', true);
- testArguments(dcp, '{"stepcount":1}', true);
- testArguments(dcp, '{"stepcount":10}', true);
- testArguments(dcp, '{"stepcount":"10"}', true);
- testArguments(dcp, '{"stepaction":"next","stepcount":10}', true);
+ testArguments(exec_state, '{"stepaction":"in"}', true);
+ testArguments(exec_state, '{"stepaction":"min"}', true);
+ testArguments(exec_state, '{"stepaction":"next"}', true);
+ testArguments(exec_state, '{"stepaction":"out"}', true);
+ testArguments(exec_state, '{"stepcount":1}', true);
+ testArguments(exec_state, '{"stepcount":10}', true);
+ testArguments(exec_state, '{"stepcount":"10"}', true);
+ testArguments(exec_state, '{"stepaction":"next","stepcount":10}', true);
// Indicate that all was processed.
listenerComplete = true;
@@ -108,6 +109,6 @@ function g() {
Debug.setBreakPoint(g, 0, 0);
g();
+assertFalse(exception, "exception in listener")
// Make sure that the debug event listener vas invoked.
assertTrue(listenerComplete, "listener did not run to completion");
-assertFalse(exception, "exception in listener")
diff --git a/deps/v8/test/mjsunit/debug-evaluate-bool-constructor.js b/deps/v8/test/mjsunit/debug-evaluate-bool-constructor.js
new file mode 100644
index 0000000000..809a5ccc69
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-evaluate-bool-constructor.js
@@ -0,0 +1,80 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+var listenerComplete = false;
+var exception = false;
+
+function listener(event, exec_state, event_data, data) {
+ try {
+ if (event == Debug.DebugEvent.Break) {
+ // Get the debug command processor.
+ var dcp = exec_state.debugCommandProcessor();
+
+ var request = {
+ seq: 0,
+ type: 'request',
+ command: 'evaluate',
+ arguments: {
+ expression: 'a',
+ frame: 0
+ }
+ };
+ request = JSON.stringify(request);
+
+ var resp = dcp.processDebugJSONRequest(request);
+ var response = JSON.parse(resp);
+ assertTrue(response.success, 'Command failed: ' + resp);
+ assertEquals('object', response.body.type);
+ assertEquals('Object', response.body.className);
+
+ // Indicate that all was processed.
+ listenerComplete = true;
+ }
+ } catch (e) {
+ exception = e
+ };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function callDebugger() {
+ // Add set constructor field to a non-function value.
+ var a = {constructor:true};
+ debugger;
+}
+
+callDebugger();
+
+
+// Make sure that the debug event listener vas invoked.
+assertFalse(exception, "exception in listener")
+assertTrue(listenerComplete, "listener did not run to completion");
diff --git a/deps/v8/test/mjsunit/debug-evaluate-recursive.js b/deps/v8/test/mjsunit/debug-evaluate-recursive.js
index 9f037e5783..6ee391b63b 100644
--- a/deps/v8/test/mjsunit/debug-evaluate-recursive.js
+++ b/deps/v8/test/mjsunit/debug-evaluate-recursive.js
@@ -44,7 +44,10 @@ function safeEval(code) {
}
}
-function testRequest(dcp, arguments, success, result) {
+function testRequest(exec_state, arguments, success, result) {
+ // Get the debug command processor in paused state.
+ var dcp = exec_state.debugCommandProcessor(false);
+
// Generate request with the supplied arguments.
var request;
if (arguments) {
@@ -74,23 +77,20 @@ function listener(event, exec_state, event_data, data) {
assertEquals(1, exec_state.frame(0).evaluate('f()', true).value());
assertEquals(2, exec_state.frame(0).evaluate('g()', true).value());
- // Get the debug command processor.
- var dcp = exec_state.debugCommandProcessor();
-
// Call functions with break using the JSON protocol. Tests that argument
// disable_break is default true.
- testRequest(dcp, '{"expression":"f()"}', true, 1);
- testRequest(dcp, '{"expression":"f()","frame":0}', true, 1);
- testRequest(dcp, '{"expression":"g()"}', true, 2);
- testRequest(dcp, '{"expression":"g()","frame":0}', true, 2);
+ testRequest(exec_state, '{"expression":"f()"}', true, 1);
+ testRequest(exec_state, '{"expression":"f()","frame":0}', true, 1);
+ testRequest(exec_state, '{"expression":"g()"}', true, 2);
+ testRequest(exec_state, '{"expression":"g()","frame":0}', true, 2);
// Call functions with break using the JSON protocol. Tests passing
// argument disable_break is default true.
- testRequest(dcp, '{"expression":"f()","disable_break":true}', true, 1);
- testRequest(dcp, '{"expression":"f()","frame":0,"disable_break":true}',
+ testRequest(exec_state, '{"expression":"f()","disable_break":true}', true, 1);
+ testRequest(exec_state, '{"expression":"f()","frame":0,"disable_break":true}',
true, 1);
- testRequest(dcp, '{"expression":"g()","disable_break":true}', true, 2);
- testRequest(dcp, '{"expression":"g()","frame":0,"disable_break":true}',
+ testRequest(exec_state, '{"expression":"g()","disable_break":true}', true, 2);
+ testRequest(exec_state, '{"expression":"g()","frame":0,"disable_break":true}',
true, 2);
// Indicate that all was processed.
@@ -146,9 +146,9 @@ Debug.setBreakPoint(f, 2, 0);
// Cause a debug break event.
debugger;
+assertFalse(exception, "exception in listener")
// Make sure that the debug event listener vas invoked.
assertTrue(listenerComplete);
-assertFalse(exception, "exception in listener")
// Remove the debug event listener.
Debug.setListener(null);
@@ -161,7 +161,7 @@ Debug.setBreakPoint(f, 2, 0);
debugger;
+assertFalse(exception, "exception in listener")
// Make sure that the debug event listener vas invoked.
assertTrue(listenerComplete);
-assertFalse(exception, "exception in listener")
assertEquals(2, break_count);
diff --git a/deps/v8/test/mjsunit/debug-evaluate.js b/deps/v8/test/mjsunit/debug-evaluate.js
index 5c5734f877..c4779072ac 100644
--- a/deps/v8/test/mjsunit/debug-evaluate.js
+++ b/deps/v8/test/mjsunit/debug-evaluate.js
@@ -59,14 +59,15 @@ function testRequest(dcp, arguments, success, result) {
} else {
assertFalse(response.success, request + ' -> ' + response.message);
}
- assertFalse(response.running, request + ' -> expected not running');
+ assertEquals(response.running, "unspecified_running_state",
+ request + ' -> expected not running');
}
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
// Get the debug command processor.
- var dcp = exec_state.debugCommandProcessor();
+ var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
// Test some illegal evaluate requests.
testRequest(dcp, void 0, false);
@@ -112,6 +113,6 @@ a = 1;
Debug.setBreakPoint(f, 2, 0);
g();
+assertFalse(exception, "exception in listener")
// Make sure that the debug event listener vas invoked.
assertTrue(listenerComplete, "listener did not run to completion");
-assertFalse(exception, "exception in listener")
diff --git a/deps/v8/test/mjsunit/debug-handle.js b/deps/v8/test/mjsunit/debug-handle.js
index c7ab76af44..98875ceb41 100644
--- a/deps/v8/test/mjsunit/debug-handle.js
+++ b/deps/v8/test/mjsunit/debug-handle.js
@@ -43,7 +43,10 @@ function safeEval(code) {
// Send an evaluation request and return the handle of the result.
-function evaluateRequest(dcp, arguments) {
+function evaluateRequest(exec_state, arguments) {
+ // Get the debug command processor.
+ var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
+
// The base part of all evaluate requests.
var base_request = '"seq":0,"type":"request","command":"evaluate"'
@@ -63,7 +66,10 @@ function evaluateRequest(dcp, arguments) {
// Send a lookup request and return the evaluated JSON response.
-function lookupRequest(dcp, arguments, success) {
+function lookupRequest(exec_state, arguments, success) {
+ // Get the debug command processor.
+ var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
+
// The base part of all lookup requests.
var base_request = '"seq":0,"type":"request","command":"lookup"'
@@ -81,7 +87,7 @@ function lookupRequest(dcp, arguments, success) {
} else {
assertFalse(response.success, request + ' -> ' + response.message);
}
- assertFalse(response.running, request + ' -> expected not running');
+ assertEquals(response.running, dcp.isRunning(), request + ' -> expected not running');
return response;
}
@@ -90,26 +96,23 @@ function lookupRequest(dcp, arguments, success) {
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
- // Get the debug command processor.
- var dcp = exec_state.debugCommandProcessor();
-
// Test some illegal lookup requests.
- lookupRequest(dcp, void 0, false);
- lookupRequest(dcp, '{"handles":["a"]}', false);
- lookupRequest(dcp, '{"handles":[-1]}', false);
+ lookupRequest(exec_state, void 0, false);
+ lookupRequest(exec_state, '{"handles":["a"]}', false);
+ lookupRequest(exec_state, '{"handles":[-1]}', false);
// Evaluate and get some handles.
- var handle_o = evaluateRequest(dcp, '{"expression":"o"}');
- var handle_p = evaluateRequest(dcp, '{"expression":"p"}');
- var handle_b = evaluateRequest(dcp, '{"expression":"a"}');
- var handle_a = evaluateRequest(dcp, '{"expression":"b","frame":1}');
+ var handle_o = evaluateRequest(exec_state, '{"expression":"o"}');
+ var handle_p = evaluateRequest(exec_state, '{"expression":"p"}');
+ var handle_b = evaluateRequest(exec_state, '{"expression":"a"}');
+ var handle_a = evaluateRequest(exec_state, '{"expression":"b","frame":1}');
assertEquals(handle_o, handle_a);
assertEquals(handle_a, handle_b);
assertFalse(handle_o == handle_p, "o and p have he same handle");
var response;
var count;
- response = lookupRequest(dcp, '{"handles":[' + handle_o + ']}', true);
+ response = lookupRequest(exec_state, '{"handles":[' + handle_o + ']}', true);
var obj = response.body[handle_o];
assertTrue(!!obj, 'Object not found: ' + handle_o);
assertEquals(handle_o, obj.handle);
@@ -127,20 +130,20 @@ function listener(event, exec_state, event_data, data) {
}
}
assertEquals(2, count, 'Either "o" or "p" not found');
- response = lookupRequest(dcp, '{"handles":[' + handle_p + ']}', true);
+ response = lookupRequest(exec_state, '{"handles":[' + handle_p + ']}', true);
obj = response.body[handle_p];
assertTrue(!!obj, 'Object not found: ' + handle_p);
assertEquals(handle_p, obj.handle);
// Check handles for functions on the stack.
- var handle_f = evaluateRequest(dcp, '{"expression":"f"}');
- var handle_g = evaluateRequest(dcp, '{"expression":"g"}');
- var handle_caller = evaluateRequest(dcp, '{"expression":"f.caller"}');
+ var handle_f = evaluateRequest(exec_state, '{"expression":"f"}');
+ var handle_g = evaluateRequest(exec_state, '{"expression":"g"}');
+ var handle_caller = evaluateRequest(exec_state, '{"expression":"f.caller"}');
assertFalse(handle_f == handle_g, "f and g have he same handle");
assertEquals(handle_g, handle_caller, "caller for f should be g");
- response = lookupRequest(dcp, '{"handles":[' + handle_f + ']}', true);
+ response = lookupRequest(exec_state, '{"handles":[' + handle_f + ']}', true);
obj = response.body[handle_f];
assertEquals(handle_f, obj.handle);
@@ -151,14 +154,14 @@ function listener(event, exec_state, event_data, data) {
switch (obj.properties[i].name) {
case 'name':
var response_name;
- response_name = lookupRequest(dcp, arguments, true);
+ response_name = lookupRequest(exec_state, arguments, true);
assertEquals('string', response_name.body[ref].type);
assertEquals("f", response_name.body[ref].value);
count++;
break;
case 'length':
var response_length;
- response_length = lookupRequest(dcp, arguments, true);
+ response_length = lookupRequest(exec_state, arguments, true);
assertEquals('number', response_length.body[ref].type);
assertEquals(1, response_length.body[ref].value);
count++;
@@ -179,7 +182,7 @@ function listener(event, exec_state, event_data, data) {
}
var arguments = '{"handles":[' + refs.join(',') + ']}';
- response = lookupRequest(dcp, arguments, true);
+ response = lookupRequest(exec_state, arguments, true);
count = 0;
for (i in obj.properties) {
var ref = obj.properties[i].ref;
@@ -244,6 +247,6 @@ p.o = o;
p.p = p;
g(o);
+assertFalse(exception, "exception in listener")
// Make sure that the debug event listener vas invoked.
assertTrue(listenerComplete, "listener did not run to completion: " + exception);
-assertFalse(exception, "exception in listener")
diff --git a/deps/v8/test/mjsunit/debug-mirror-cache.js b/deps/v8/test/mjsunit/debug-mirror-cache.js
index d15146faef..5b85306a18 100644
--- a/deps/v8/test/mjsunit/debug-mirror-cache.js
+++ b/deps/v8/test/mjsunit/debug-mirror-cache.js
@@ -41,7 +41,7 @@ function g() {
Debug = debug.Debug
listenerCallCount = 0;
-listenerExceptionCount = 0;
+listenerExceptions = [];
function listener(event, exec_state, event_data, data) {
@@ -54,8 +54,8 @@ function listener(event, exec_state, event_data, data) {
assertEquals(0, debug.next_handle_, "Mirror cache not cleared");
assertEquals(0, debug.mirror_cache_.length, "Mirror cache not cleared");
- // Get the debug command processor.
- var dcp = exec_state.debugCommandProcessor();
+ // Get the debug command processor in paused state.
+ var dcp = exec_state.debugCommandProcessor(false);
// Make a backtrace request to create some mirrors.
var json;
@@ -68,7 +68,7 @@ function listener(event, exec_state, event_data, data) {
}
} catch (e) {
print(e);
- listenerExceptionCount++;
+ listenerExceptions.push(e);
};
};
@@ -79,7 +79,7 @@ Debug.setListener(listener);
debugger;
debugger;
+assertEquals([], listenerExceptions, "Exception in listener");
// Make sure that the debug event listener vas invoked.
assertEquals(2, listenerCallCount, "Listener not called");
-assertEquals(0, listenerExceptionCount, "Exception in listener");
diff --git a/deps/v8/test/mjsunit/debug-references.js b/deps/v8/test/mjsunit/debug-references.js
index 1fde1ac74f..452761cf1c 100644
--- a/deps/v8/test/mjsunit/debug-references.js
+++ b/deps/v8/test/mjsunit/debug-references.js
@@ -66,14 +66,14 @@ function testRequest(dcp, arguments, success, count) {
} else {
assertFalse(response.success, request + ' -> ' + response.message);
}
- assertFalse(response.running, request + ' -> expected not running');
+ assertEquals(response.running, dcp.isRunning(), request + ' -> expected not running');
}
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
// Get the debug command processor.
- var dcp = exec_state.debugCommandProcessor();
+ var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
// Test some illegal references requests.
testRequest(dcp, void 0, false);
diff --git a/deps/v8/test/mjsunit/debug-scopes.js b/deps/v8/test/mjsunit/debug-scopes.js
index e87cbb7c22..af29df98cc 100644
--- a/deps/v8/test/mjsunit/debug-scopes.js
+++ b/deps/v8/test/mjsunit/debug-scopes.js
@@ -92,7 +92,7 @@ function CheckScopeChain(scopes, exec_state) {
}
// Get the debug command processor.
- var dcp = exec_state.debugCommandProcessor();
+ var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
// Send a scopes request and check the result.
var json;
@@ -155,7 +155,7 @@ function CheckScopeContent(content, number, exec_state) {
assertEquals(count, scope_size);
// Get the debug command processor.
- var dcp = exec_state.debugCommandProcessor();
+ var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
// Send a scope request for information on a single scope and check the
// result.
diff --git a/deps/v8/test/mjsunit/debug-scripts-request.js b/deps/v8/test/mjsunit/debug-scripts-request.js
index 80b3bce597..41bff0e805 100644
--- a/deps/v8/test/mjsunit/debug-scripts-request.js
+++ b/deps/v8/test/mjsunit/debug-scripts-request.js
@@ -60,7 +60,7 @@ function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
// Get the debug command processor.
- var dcp = exec_state.debugCommandProcessor();
+ var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
// Test illegal scripts requests.
testArguments(dcp, '{"types":"xx"}', false);
diff --git a/deps/v8/test/mjsunit/debug-setbreakpoint.js b/deps/v8/test/mjsunit/debug-setbreakpoint.js
index f8d9b157b2..08492b4ecc 100644
--- a/deps/v8/test/mjsunit/debug-setbreakpoint.js
+++ b/deps/v8/test/mjsunit/debug-setbreakpoint.js
@@ -69,7 +69,7 @@ function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
// Get the debug command processor.
- var dcp = exec_state.debugCommandProcessor();
+ var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
// Test some illegal setbreakpoint requests.
var request = '{' + base_request + '}'
diff --git a/deps/v8/test/mjsunit/debug-suspend.js b/deps/v8/test/mjsunit/debug-suspend.js
new file mode 100644
index 0000000000..73a2e8c24b
--- /dev/null
+++ b/deps/v8/test/mjsunit/debug-suspend.js
@@ -0,0 +1,96 @@
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --expose-debug-as debug
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+// Simple function which stores the last debug event.
+listenerComplete = false;
+exception = false;
+
+var base_backtrace_request = '"seq":0,"type":"request","command":"backtrace"'
+var base_suspend_request = '"seq":0,"type":"request","command":"suspend"'
+
+function safeEval(code) {
+ try {
+ return eval('(' + code + ')');
+ } catch (e) {
+ assertEquals(void 0, e);
+ return undefined;
+ }
+}
+
+function testArguments(exec_state) {
+ // Get the debug command processor in running state.
+ var dcp = exec_state.debugCommandProcessor(true);
+
+ assertTrue(dcp.isRunning());
+
+ var backtrace_request = '{' + base_backtrace_request + '}'
+ var backtrace_response = safeEval(dcp.processDebugJSONRequest(backtrace_request));
+
+ assertTrue(backtrace_response.success);
+
+ assertTrue(backtrace_response.running, backtrace_request + ' -> expected running');
+
+ assertTrue(dcp.isRunning());
+
+ var suspend_request = '{' + base_suspend_request + '}'
+ var suspend_response = safeEval(dcp.processDebugJSONRequest(suspend_request));
+
+ assertTrue(suspend_response.success);
+
+ assertFalse(suspend_response.running, suspend_request + ' -> expected not running');
+
+ assertFalse(dcp.isRunning());
+}
+
+function listener(event, exec_state, event_data, data) {
+ try {
+ if (event == Debug.DebugEvent.Break) {
+
+ // Test simple suspend request.
+ testArguments(exec_state);
+
+ // Indicate that all was processed.
+ listenerComplete = true;
+ }
+ } catch (e) {
+ exception = e
+ };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Stop debugger and check that suspend command changes running flag.
+debugger;
+
+assertFalse(exception, "exception in listener")
+// Make sure that the debug event listener vas invoked.
+assertTrue(listenerComplete, "listener did not run to completion");
diff --git a/deps/v8/test/mjsunit/for-in.js b/deps/v8/test/mjsunit/for-in.js
index dfe721dbee..e3436ff3be 100644
--- a/deps/v8/test/mjsunit/for-in.js
+++ b/deps/v8/test/mjsunit/for-in.js
@@ -31,21 +31,21 @@ function props(x) {
return array.sort();
}
-assertEquals(0, props({}).length);
-assertEquals(1, props({x:1}).length);
-assertEquals(2, props({x:1, y:2}).length);
+assertEquals(0, props({}).length, "olen0");
+assertEquals(1, props({x:1}).length, "olen1");
+assertEquals(2, props({x:1, y:2}).length, "olen2");
-assertArrayEquals(["x"], props({x:1}));
-assertArrayEquals(["x", "y"], props({x:1, y:2}));
-assertArrayEquals(["x", "y", "zoom"], props({x:1, y:2, zoom:3}));
+assertArrayEquals(["x"], props({x:1}), "x");
+assertArrayEquals(["x", "y"], props({x:1, y:2}), "xy");
+assertArrayEquals(["x", "y", "zoom"], props({x:1, y:2, zoom:3}), "xyzoom");
-assertEquals(0, props([]).length);
-assertEquals(1, props([1]).length);
-assertEquals(2, props([1,2]).length);
+assertEquals(0, props([]).length, "alen0");
+assertEquals(1, props([1]).length, "alen1");
+assertEquals(2, props([1,2]).length, "alen2");
-assertArrayEquals(["0"], props([1]));
-assertArrayEquals(["0", "1"], props([1,2]));
-assertArrayEquals(["0", "1", "2"], props([1,2,3]));
+assertArrayEquals(["0"], props([1]), "0");
+assertArrayEquals(["0", "1"], props([1,2]), "01");
+assertArrayEquals(["0", "1", "2"], props([1,2,3]), "012");
var o = {};
var a = [];
@@ -54,33 +54,33 @@ for (var i = 0x0020; i < 0x01ff; i+=2) {
a.push(s);
o[s] = i;
}
-assertArrayEquals(a, props(o));
+assertArrayEquals(a, props(o), "charcodes");
var a = [];
-assertEquals(0, props(a).length);
+assertEquals(0, props(a).length, "proplen0");
a[Math.pow(2,30)-1] = 0;
-assertEquals(1, props(a).length);
+assertEquals(1, props(a).length, "proplen1");
a[Math.pow(2,31)-1] = 0;
-assertEquals(2, props(a).length);
+assertEquals(2, props(a).length, "proplen2");
a[1] = 0;
-assertEquals(3, props(a).length);
+assertEquals(3, props(a).length, "proplen3");
for (var hest = 'hest' in {}) { }
-assertEquals('hest', hest);
+assertEquals('hest', hest, "empty-no-override");
var result = '';
for (var p in {a : [0], b : 1}) { result += p; }
-assertEquals('ab', result);
+assertEquals('ab', result, "ab");
var result = '';
for (var p in {a : {v:1}, b : 1}) { result += p; }
-assertEquals('ab', result);
+assertEquals('ab', result, "ab-nodeep");
var result = '';
for (var p in { get a() {}, b : 1}) { result += p; }
-assertEquals('ab', result);
+assertEquals('ab', result, "abget");
var result = '';
for (var p in { get a() {}, set a(x) {}, b : 1}) { result += p; }
-assertEquals('ab', result);
+assertEquals('ab', result, "abgetset");
diff --git a/deps/v8/test/mjsunit/regress/regress-1081309.js b/deps/v8/test/mjsunit/regress/regress-1081309.js
index a771ac0448..009ede1516 100644
--- a/deps/v8/test/mjsunit/regress/regress-1081309.js
+++ b/deps/v8/test/mjsunit/regress/regress-1081309.js
@@ -69,7 +69,7 @@ function listener(event, exec_state, event_data, data) {
// 0: [anonymous]
// Get the debug command processor.
- var dcp = exec_state.debugCommandProcessor();
+ var dcp = exec_state.debugCommandProcessor(false);
// Get the backtrace.
var json;
@@ -105,6 +105,6 @@ try {
// Ignore the exception "Cannot call method 'x' of undefined"
}
+assertFalse(exception, "exception in listener", exception)
// Make sure that the debug event listener vas invoked.
assertTrue(listenerCalled, "listener not called");
-assertFalse(exception, "exception in listener", exception)
diff --git a/deps/v8/test/mjsunit/regress/regress-1199401.js b/deps/v8/test/mjsunit/regress/regress-1199401.js
index 792faea982..cc7985d820 100644
--- a/deps/v8/test/mjsunit/regress/regress-1199401.js
+++ b/deps/v8/test/mjsunit/regress/regress-1199401.js
@@ -27,35 +27,49 @@
// Ensure that we can correctly change the sign of the most negative smi.
-assertEquals(1073741824, -1073741824 * -1);
-assertEquals(1073741824, -1073741824 / -1);
-assertEquals(1073741824, -(-1073741824));
-assertEquals(1073741824, 0 - (-1073741824));
-
-var min_smi = -1073741824;
-
-assertEquals(1073741824, min_smi * -1);
-assertEquals(1073741824, min_smi / -1);
-assertEquals(1073741824, -min_smi);
-assertEquals(1073741824, 0 - min_smi);
-
-var zero = 0;
-var minus_one = -1;
-
-assertEquals(1073741824, min_smi * minus_one);
-assertEquals(1073741824, min_smi / minus_one);
-assertEquals(1073741824, -min_smi);
-assertEquals(1073741824, zero - min_smi);
-
-assertEquals(1073741824, -1073741824 * minus_one);
-assertEquals(1073741824, -1073741824 / minus_one);
-assertEquals(1073741824, -(-1073741824));
-assertEquals(1073741824, zero - (-1073741824));
-
-var half_min_smi = -(1<<15);
-var half_max_smi = (1<<15);
-
-assertEquals(1073741824, -half_min_smi * half_max_smi);
-assertEquals(1073741824, half_min_smi * -half_max_smi);
-assertEquals(1073741824, half_max_smi * -half_min_smi);
-assertEquals(1073741824, -half_max_smi * half_min_smi);
+// Possible Smi ranges.
+var ranges = [{min: -1073741824, max: 1073741823, bits: 31},
+ {min: -2147483648, max: 2147483647, bits: 32}];
+
+for (var i = 0; i < ranges.length; i++) {
+ var range = ranges[i];
+ var min_smi = range.min;
+ var max_smi = range.max;
+ var bits = range.bits;
+ var name = bits + "-bit";
+
+ var result = max_smi + 1;
+
+ // Min smi as literal
+ assertEquals(result, eval(min_smi + " * -1"), name + "-litconmult");
+ assertEquals(result, eval(min_smi + " / -1"), name + "-litcondiv");
+ assertEquals(result, eval("-(" + min_smi + ")"), name + "-litneg");
+ assertEquals(result, eval("0 - (" + min_smi + ")")), name + "-conlitsub";
+
+ // As variable:
+ assertEquals(result, min_smi * -1, name + "-varconmult");
+ assertEquals(result, min_smi / -1, name + "-varcondiv");
+ assertEquals(result, -min_smi, name + "-varneg");
+ assertEquals(result, 0 - min_smi, name + "-convarsub");
+
+ // Only variables:
+ var zero = 0;
+ var minus_one = -1;
+
+ assertEquals(result, min_smi * minus_one, name + "-varvarmult");
+ assertEquals(result, min_smi / minus_one, name + "-varvardiv");
+ assertEquals(result, zero - min_smi, name + "-varvarsub");
+
+ // Constants as variables
+ assertEquals(result, eval(min_smi + " * minus_one"), name + "-litvarmult");
+ assertEquals(result, eval(min_smi + " / minus_one"), name + "-litvarmdiv");
+ assertEquals(result, eval("0 - (" + min_smi + ")"), name + "-varlitsub");
+
+ var half_min_smi = -(1 << (bits >> 1));
+ var half_max_smi = 1 << ((bits - 1) >> 1);
+
+ assertEquals(max_smi + 1, -half_min_smi * half_max_smi, name + "-half1");
+ assertEquals(max_smi + 1, half_min_smi * -half_max_smi, name + "-half2");
+ assertEquals(max_smi + 1, half_max_smi * -half_min_smi, name + "-half3");
+ assertEquals(max_smi + 1, -half_max_smi * half_min_smi, name + "-half4");
+}
diff --git a/deps/v8/test/mjsunit/smi-negative-zero.js b/deps/v8/test/mjsunit/smi-negative-zero.js
index 719ee49f01..690644317e 100644
--- a/deps/v8/test/mjsunit/smi-negative-zero.js
+++ b/deps/v8/test/mjsunit/smi-negative-zero.js
@@ -37,64 +37,64 @@ var minus_four = -4;
// variable op variable
-assertEquals(one / (-zero), -Infinity, "one / -0 I");
+assertEquals(-Infinity, one / (-zero), "one / -0 I");
-assertEquals(one / (zero * minus_one), -Infinity, "one / -1");
-assertEquals(one / (minus_one * zero), -Infinity, "one / -0 II");
-assertEquals(one / (zero * zero), Infinity, "one / 0 I");
-assertEquals(one / (minus_one * minus_one), 1, "one / 1");
+assertEquals(-Infinity, one / (zero * minus_one), "one / -1");
+assertEquals(-Infinity, one / (minus_one * zero), "one / -0 II");
+assertEquals(Infinity, one / (zero * zero), "one / 0 I");
+assertEquals(1, one / (minus_one * minus_one), "one / 1");
-assertEquals(one / (zero / minus_one), -Infinity, "one / -0 III");
-assertEquals(one / (zero / one), Infinity, "one / 0 II");
+assertEquals(-Infinity, one / (zero / minus_one), "one / -0 III");
+assertEquals(Infinity, one / (zero / one), "one / 0 II");
-assertEquals(one / (minus_four % two), -Infinity, "foo1");
-assertEquals(one / (minus_four % minus_two), -Infinity, "foo2");
-assertEquals(one / (four % two), Infinity, "foo3");
-assertEquals(one / (four % minus_two), Infinity, "foo4");
+assertEquals(-Infinity, one / (minus_four % two), "foo1");
+assertEquals(-Infinity, one / (minus_four % minus_two), "foo2");
+assertEquals(Infinity, one / (four % two), "foo3");
+assertEquals(Infinity, one / (four % minus_two), "foo4");
// literal op variable
-assertEquals(one / (0 * minus_one), -Infinity, "bar1");
-assertEquals(one / (-1 * zero), -Infinity, "bar2");
-assertEquals(one / (0 * zero), Infinity, "bar3");
-assertEquals(one / (-1 * minus_one), 1, "bar4");
+assertEquals(-Infinity, one / (0 * minus_one), "bar1");
+assertEquals(-Infinity, one / (-1 * zero), "bar2");
+assertEquals(Infinity, one / (0 * zero), "bar3");
+assertEquals(1, one / (-1 * minus_one), "bar4");
-assertEquals(one / (0 / minus_one), -Infinity, "baz1");
-assertEquals(one / (0 / one), Infinity, "baz2");
+assertEquals(-Infinity, one / (0 / minus_one), "baz1");
+assertEquals(Infinity, one / (0 / one), "baz2");
-assertEquals(one / (-4 % two), -Infinity, "baz3");
-assertEquals(one / (-4 % minus_two), -Infinity, "baz4");
-assertEquals(one / (4 % two), Infinity, "baz5");
-assertEquals(one / (4 % minus_two), Infinity, "baz6");
+assertEquals(-Infinity, one / (-4 % two), "baz3");
+assertEquals(-Infinity, one / (-4 % minus_two), "baz4");
+assertEquals(Infinity, one / (4 % two), "baz5");
+assertEquals(Infinity, one / (4 % minus_two), "baz6");
// variable op literal
-assertEquals(one / (zero * -1), -Infinity, "fizz1");
-assertEquals(one / (minus_one * 0), -Infinity, "fizz2");
-assertEquals(one / (zero * 0), Infinity, "fizz3");
-assertEquals(one / (minus_one * -1), 1, "fizz4");
+assertEquals(-Infinity, one / (zero * -1), "fizz1");
+assertEquals(-Infinity, one / (minus_one * 0), "fizz2");
+assertEquals(Infinity, one / (zero * 0), "fizz3");
+assertEquals(1, one / (minus_one * -1), "fizz4");
-assertEquals(one / (zero / -1), -Infinity, "buzz1");
-assertEquals(one / (zero / 1), Infinity, "buzz2");
+assertEquals(-Infinity, one / (zero / -1), "buzz1");
+assertEquals(Infinity, one / (zero / 1), "buzz2");
-assertEquals(one / (minus_four % 2), -Infinity, "buzz3");
-assertEquals(one / (minus_four % -2), -Infinity, "buzz4");
-assertEquals(one / (four % 2), Infinity, "buzz5");
-assertEquals(one / (four % -2), Infinity, "buzz6");
+assertEquals(-Infinity, one / (minus_four % 2), "buzz3");
+assertEquals(-Infinity, one / (minus_four % -2), "buzz4");
+assertEquals(Infinity, one / (four % 2), "buzz5");
+assertEquals(Infinity, one / (four % -2), "buzz6");
// literal op literal
-assertEquals(one / (-0), -Infinity, "fisk1");
+assertEquals(-Infinity, one / (-0), "fisk1");
-assertEquals(one / (0 * -1), -Infinity, "fisk2");
-assertEquals(one / (-1 * 0), -Infinity, "fisk3");
-assertEquals(one / (0 * 0), Infinity, "fisk4");
-assertEquals(one / (-1 * -1), 1, "fisk5");
+assertEquals(-Infinity, one / (0 * -1), "fisk2");
+assertEquals(-Infinity, one / (-1 * 0), "fisk3");
+assertEquals(Infinity, one / (0 * 0), "fisk4");
+assertEquals(1, one / (-1 * -1), "fisk5");
-assertEquals(one / (0 / -1), -Infinity, "hest1");
-assertEquals(one / (0 / 1), Infinity, "hest2");
+assertEquals(-Infinity, one / (0 / -1), "hest1");
+assertEquals(Infinity, one / (0 / 1), "hest2");
-assertEquals(one / (-4 % 2), -Infinity, "fiskhest1");
-assertEquals(one / (-4 % -2), -Infinity, "fiskhest2");
-assertEquals(one / (4 % 2), Infinity, "fiskhest3");
-assertEquals(one / (4 % -2), Infinity, "fiskhest4");
+assertEquals(-Infinity, one / (-4 % 2), "fiskhest1");
+assertEquals(-Infinity, one / (-4 % -2), "fiskhest2");
+assertEquals(Infinity, one / (4 % 2), "fiskhest3");
+assertEquals(Infinity, one / (4 % -2), "fiskhest4");
diff --git a/deps/v8/test/mjsunit/testcfg.py b/deps/v8/test/mjsunit/testcfg.py
index e3f3fcd940..49064b12fe 100644
--- a/deps/v8/test/mjsunit/testcfg.py
+++ b/deps/v8/test/mjsunit/testcfg.py
@@ -114,7 +114,8 @@ class MjsunitTestConfiguration(test.TestConfiguration):
bugs = [current_path + ['bugs', t] for t in self.Ls(join(self.root, 'bugs'))]
third_party = [current_path + ['third_party', t] for t in self.Ls(join(self.root, 'third_party'))]
tools = [current_path + ['tools', t] for t in self.Ls(join(self.root, 'tools'))]
- all_tests = mjsunit + regress + bugs + third_party + tools
+ compiler = [current_path + ['compiler', t] for t in self.Ls(join(self.root, 'compiler'))]
+ all_tests = mjsunit + regress + bugs + third_party + tools + compiler
result = []
for test in all_tests:
if self.Contains(path, test):
diff --git a/deps/v8/test/mjsunit/third_party/array-isarray.js b/deps/v8/test/mjsunit/third_party/array-isarray.js
new file mode 100644
index 0000000000..0fc42a3f27
--- /dev/null
+++ b/deps/v8/test/mjsunit/third_party/array-isarray.js
@@ -0,0 +1,48 @@
+// Copyright (c) 2009 Apple Computer, Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. 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.
+//
+// 3. Neither the name of the copyright holder(s) nor the names of any
+// 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.
+
+// Based on LayoutTests/fast/js/resources/Array-isArray.js
+
+assertTrue(Array.isArray([]));
+assertTrue(Array.isArray(new Array));
+assertTrue(Array.isArray(Array()));
+assertTrue(Array.isArray('abc'.match(/(a)*/g)));
+assertFalse((function(){ return Array.isArray(arguments); })());
+assertFalse(Array.isArray());
+assertFalse(Array.isArray(null));
+assertFalse(Array.isArray(undefined));
+assertFalse(Array.isArray(true));
+assertFalse(Array.isArray(false));
+assertFalse(Array.isArray('a string'));
+assertFalse(Array.isArray({}));
+assertFalse(Array.isArray({length: 5}));
+assertFalse(Array.isArray({__proto__: Array.prototype, length:1, 0:1, 1:2}));
+
diff --git a/deps/v8/test/mjsunit/third_party/string-trim.js b/deps/v8/test/mjsunit/third_party/string-trim.js
new file mode 100644
index 0000000000..234dff6dcd
--- /dev/null
+++ b/deps/v8/test/mjsunit/third_party/string-trim.js
@@ -0,0 +1,107 @@
+// Copyright (c) 2009 Apple Computer, Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. 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.
+//
+// 3. Neither the name of the copyright holder(s) nor the names of any
+// 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.
+
+// Based on LayoutTests/fast/js/script-tests/string-trim.js
+
+// References to trim(), trimLeft() and trimRight() functions for
+// testing Function's *.call() and *.apply() methods.
+
+var trim = String.prototype.trim;
+var trimLeft = String.prototype.trimLeft;
+var trimRight = String.prototype.trimRight;
+
+var testString = 'foo bar';
+var trimString = '';
+var leftTrimString = '';
+var rightTrimString = '';
+var wsString = '';
+
+var whitespace = [
+ {s : '\u0009', t : 'HORIZONTAL TAB'},
+ {s : '\u000A', t : 'LINE FEED OR NEW LINE'},
+ {s : '\u000B', t : 'VERTICAL TAB'},
+ {s : '\u000C', t : 'FORMFEED'},
+ {s : '\u000D', t : 'CARRIAGE RETURN'},
+ {s : '\u0020', t : 'SPACE'},
+ {s : '\u00A0', t : 'NO-BREAK SPACE'},
+ {s : '\u2000', t : 'EN QUAD'},
+ {s : '\u2001', t : 'EM QUAD'},
+ {s : '\u2002', t : 'EN SPACE'},
+ {s : '\u2003', t : 'EM SPACE'},
+ {s : '\u2004', t : 'THREE-PER-EM SPACE'},
+ {s : '\u2005', t : 'FOUR-PER-EM SPACE'},
+ {s : '\u2006', t : 'SIX-PER-EM SPACE'},
+ {s : '\u2007', t : 'FIGURE SPACE'},
+ {s : '\u2008', t : 'PUNCTUATION SPACE'},
+ {s : '\u2009', t : 'THIN SPACE'},
+ {s : '\u200A', t : 'HAIR SPACE'},
+ {s : '\u3000', t : 'IDEOGRAPHIC SPACE'},
+ {s : '\u2028', t : 'LINE SEPARATOR'},
+ {s : '\u2029', t : 'PARAGRAPH SEPARATOR'},
+ {s : '\u200B', t : 'ZERO WIDTH SPACE (category Cf)'}
+];
+
+for (var i = 0; i < whitespace.length; i++) {
+ assertEquals(whitespace[i].s.trim(), '');
+ assertEquals(whitespace[i].s.trimLeft(), '');
+ assertEquals(whitespace[i].s.trimRight(), '');
+ wsString += whitespace[i].s;
+}
+
+trimString = wsString + testString + wsString;
+leftTrimString = testString + wsString; // Trimmed from the left.
+rightTrimString = wsString + testString; // Trimmed from the right.
+
+assertEquals(wsString.trim(), '');
+assertEquals(wsString.trimLeft(), '');
+assertEquals(wsString.trimRight(), '');
+
+assertEquals(trimString.trim(), testString);
+assertEquals(trimString.trimLeft(), leftTrimString);
+assertEquals(trimString.trimRight(), rightTrimString);
+
+assertEquals(leftTrimString.trim(), testString);
+assertEquals(leftTrimString.trimLeft(), leftTrimString);
+assertEquals(leftTrimString.trimRight(), testString);
+
+assertEquals(rightTrimString.trim(), testString);
+assertEquals(rightTrimString.trimLeft(), testString);
+assertEquals(rightTrimString.trimRight(), rightTrimString);
+
+var testValues = [0, Infinity, NaN, true, false, ({}), ['an','array'],
+ ({toString:function(){return 'wibble'}})
+];
+
+for (var i = 0; i < testValues.length; i++) {
+ assertEquals(trim.call(testValues[i]), String(testValues[i]));
+ assertEquals(trimLeft.call(testValues[i]), String(testValues[i]));
+ assertEquals(trimRight.call(testValues[i]), String(testValues[i]));
+}